Update Qt version used in qubesmanager to Qt5
Fixed dependencies, places where obsolete functions stopped working, code fragments that started throwing warnings and an .ui file that stopped being readable after the update.
This commit is contained in:
parent
492b8705b6
commit
e79724f9db
8
Makefile
8
Makefile
@ -20,15 +20,15 @@ rpms-dom0:
|
|||||||
rpm --addsign $(RPMS_DIR)/x86_64/qubes-manager*$(VERSION)*.rpm
|
rpm --addsign $(RPMS_DIR)/x86_64/qubes-manager*$(VERSION)*.rpm
|
||||||
|
|
||||||
qubesmanager/ui_%.py: ui/%.ui
|
qubesmanager/ui_%.py: ui/%.ui
|
||||||
pyuic4 --from-imports -o $@ $<
|
pyuic5 --from-imports -o $@ $<
|
||||||
|
|
||||||
ui: $(patsubst ui/%.ui,qubesmanager/ui_%.py,$(wildcard ui/*.ui))
|
ui: $(patsubst ui/%.ui,qubesmanager/ui_%.py,$(wildcard ui/*.ui))
|
||||||
|
|
||||||
res:
|
res:
|
||||||
pyrcc4 -py3 -o qubesmanager/resources_rc.py resources.qrc
|
pyrcc5 -o qubesmanager/resources_rc.py resources.qrc
|
||||||
|
|
||||||
translations:
|
translations:
|
||||||
lrelease-qt4 qubesmanager.pro
|
lrelease-qt5 qubesmanager.pro
|
||||||
|
|
||||||
python:
|
python:
|
||||||
$(PYTHON) ./setup.py build
|
$(PYTHON) ./setup.py build
|
||||||
@ -37,7 +37,7 @@ python_install:
|
|||||||
$(PYTHON) ./setup.py install -O1 --skip-build --root $(DESTDIR)
|
$(PYTHON) ./setup.py install -O1 --skip-build --root $(DESTDIR)
|
||||||
|
|
||||||
update_ts: res
|
update_ts: res
|
||||||
pylupdate4 qubesmanager.pro
|
pylupdate5 qubesmanager.pro
|
||||||
|
|
||||||
update-repo-current:
|
update-repo-current:
|
||||||
ln -f $(RPMS_DIR)/x86_64/qubes-manager-*$(VERSION)*.rpm ../yum/current-release/current/dom0/rpm/
|
ln -f $(RPMS_DIR)/x86_64/qubes-manager-*$(VERSION)*.rpm ../yum/current-release/current/dom0/rpm/
|
||||||
|
@ -1 +1 @@
|
|||||||
PyQt4-devel
|
PyQt5-devel
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
# with this program; if not, see <http://www.gnu.org/licenses/>.
|
# with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
from PyQt4.QtGui import QDialog, QIcon # pylint: disable=import-error
|
from PyQt5.QtWidgets import QDialog # pylint: disable=import-error
|
||||||
|
from PyQt5.QtGui import QIcon # pylint: disable=import-error
|
||||||
from qubesmanager.releasenotes import ReleaseNotesDialog
|
from qubesmanager.releasenotes import ReleaseNotesDialog
|
||||||
from qubesmanager.informationnotes import InformationNotesDialog
|
from qubesmanager.informationnotes import InformationNotesDialog
|
||||||
|
|
||||||
@ -42,10 +43,12 @@ class AboutDialog(ui_about.Ui_AboutDialog, QDialog):
|
|||||||
self.releaseNotes.clicked.connect(on_release_notes_clicked)
|
self.releaseNotes.clicked.connect(on_release_notes_clicked)
|
||||||
self.informationNotes.clicked.connect(on_information_notes_clicked)
|
self.informationNotes.clicked.connect(on_information_notes_clicked)
|
||||||
|
|
||||||
|
|
||||||
def on_release_notes_clicked():
|
def on_release_notes_clicked():
|
||||||
release_notes_dialog = ReleaseNotesDialog()
|
release_notes_dialog = ReleaseNotesDialog()
|
||||||
release_notes_dialog.exec_()
|
release_notes_dialog.exec_()
|
||||||
|
|
||||||
|
|
||||||
def on_information_notes_clicked():
|
def on_information_notes_clicked():
|
||||||
information_notes_dialog = InformationNotesDialog()
|
information_notes_dialog = InformationNotesDialog()
|
||||||
information_notes_dialog.exec_()
|
information_notes_dialog.exec_()
|
||||||
|
@ -20,13 +20,13 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import PyQt5.QtWidgets # pylint: disable=import-error
|
||||||
|
|
||||||
import PyQt4.QtGui # pylint: disable=import-error
|
|
||||||
|
|
||||||
# TODO description in tooltip
|
# TODO description in tooltip
|
||||||
# TODO icon
|
# TODO icon
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
class AppListWidgetItem(PyQt4.QtGui.QListWidgetItem):
|
class AppListWidgetItem(PyQt5.QtWidgets.QListWidgetItem):
|
||||||
def __init__(self, name, ident, parent=None):
|
def __init__(self, name, ident, parent=None):
|
||||||
super(AppListWidgetItem, self).__init__(name, parent)
|
super(AppListWidgetItem, self).__init__(name, parent)
|
||||||
# self.setToolTip(command)
|
# self.setToolTip(command)
|
||||||
@ -58,7 +58,8 @@ class AppmenuSelectManager:
|
|||||||
self.app_list.clear()
|
self.app_list.clear()
|
||||||
|
|
||||||
available_appmenus = [AppListWidgetItem.from_line(line)
|
available_appmenus = [AppListWidgetItem.from_line(line)
|
||||||
for line in subprocess.check_output(['qvm-appmenus',
|
for line in subprocess.check_output(
|
||||||
|
['qvm-appmenus',
|
||||||
'--get-available', '--i-understand-format-is-unstable',
|
'--get-available', '--i-understand-format-is-unstable',
|
||||||
self.vm.name]).decode().splitlines()]
|
self.vm.name]).decode().splitlines()]
|
||||||
|
|
||||||
|
@ -30,8 +30,8 @@ from qubesadmin import utils as admin_utils
|
|||||||
from qubesadmin import events
|
from qubesadmin import events
|
||||||
from qubes.storage.file import get_disk_usage
|
from qubes.storage.file import get_disk_usage
|
||||||
|
|
||||||
from PyQt4 import QtCore # pylint: disable=import-error
|
from PyQt5 import QtCore # pylint: disable=import-error
|
||||||
from PyQt4 import QtGui # pylint: disable=import-error
|
from PyQt5 import QtWidgets # pylint: disable=import-error
|
||||||
from . import ui_backupdlg # pylint: disable=no-name-in-module
|
from . import ui_backupdlg # pylint: disable=no-name-in-module
|
||||||
from . import multiselectwidget
|
from . import multiselectwidget
|
||||||
|
|
||||||
@ -45,6 +45,7 @@ import os
|
|||||||
import asyncio
|
import asyncio
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
class BackupThread(QtCore.QThread):
|
class BackupThread(QtCore.QThread):
|
||||||
def __init__(self, vm):
|
def __init__(self, vm):
|
||||||
@ -67,7 +68,7 @@ class BackupThread(QtCore.QThread):
|
|||||||
self.msg = '\n'.join(msg)
|
self.msg = '\n'.join(msg)
|
||||||
|
|
||||||
|
|
||||||
class BackupVMsWindow(ui_backupdlg.Ui_Backup, multiselectwidget.QtGui.QWizard):
|
class BackupVMsWindow(ui_backupdlg.Ui_Backup, QtWidgets.QWizard):
|
||||||
def __init__(self, qt_app, qubes_app, dispatcher, parent=None):
|
def __init__(self, qt_app, qubes_app, dispatcher, parent=None):
|
||||||
super(BackupVMsWindow, self).__init__(parent)
|
super(BackupVMsWindow, self).__init__(parent)
|
||||||
|
|
||||||
@ -86,33 +87,20 @@ class BackupVMsWindow(ui_backupdlg.Ui_Backup, multiselectwidget.QtGui.QWizard):
|
|||||||
self.select_vms_widget = multiselectwidget.MultiSelectWidget(self)
|
self.select_vms_widget = multiselectwidget.MultiSelectWidget(self)
|
||||||
self.verticalLayout.insertWidget(1, self.select_vms_widget)
|
self.verticalLayout.insertWidget(1, self.select_vms_widget)
|
||||||
|
|
||||||
self.connect(self, QtCore.SIGNAL("currentIdChanged(int)"),
|
self.currentIdChanged.connect(self.current_page_changed)
|
||||||
self.current_page_changed)
|
self.select_vms_widget.itemsRemoved.connect(self.vms_removed)
|
||||||
self.connect(self.select_vms_widget,
|
self.select_vms_widget.itemsAdded.connect(self.vms_added)
|
||||||
QtCore.SIGNAL("items_removed(PyQt_PyObject)"),
|
self.dir_line_edit.textChanged.connect(self.backup_location_changed)
|
||||||
self.vms_removed)
|
|
||||||
self.connect(self.select_vms_widget,
|
|
||||||
QtCore.SIGNAL("items_added(PyQt_PyObject)"),
|
|
||||||
self.vms_added)
|
|
||||||
self.dir_line_edit.connect(self.dir_line_edit,
|
|
||||||
QtCore.SIGNAL("textChanged(QString)"),
|
|
||||||
self.backup_location_changed)
|
|
||||||
|
|
||||||
self.select_vms_page.isComplete = self.has_selected_vms
|
self.select_vms_page.isComplete = self.has_selected_vms
|
||||||
self.select_dir_page.isComplete = self.has_selected_dir_and_pass
|
self.select_dir_page.isComplete = self.has_selected_dir_and_pass
|
||||||
# FIXME
|
# FIXME
|
||||||
# this causes to run isComplete() twice, I don't know why
|
# this causes to run isComplete() twice, I don't know why
|
||||||
self.select_vms_page.connect(
|
self.select_vms_widget.selectedChanged.connect(
|
||||||
self.select_vms_widget,
|
self.select_vms_page.completeChanged.emit)
|
||||||
QtCore.SIGNAL("selected_changed()"),
|
self.passphrase_line_edit.textChanged.connect(
|
||||||
QtCore.SIGNAL("completeChanged()"))
|
|
||||||
self.passphrase_line_edit.connect(
|
|
||||||
self.passphrase_line_edit,
|
|
||||||
QtCore.SIGNAL("textChanged(QString)"),
|
|
||||||
self.backup_location_changed)
|
self.backup_location_changed)
|
||||||
self.passphrase_line_edit_verify.connect(
|
self.passphrase_line_edit_verify.textChanged.connect(
|
||||||
self.passphrase_line_edit_verify,
|
|
||||||
QtCore.SIGNAL("textChanged(QString)"),
|
|
||||||
self.backup_location_changed)
|
self.backup_location_changed)
|
||||||
|
|
||||||
self.total_size = 0
|
self.total_size = 0
|
||||||
@ -173,8 +161,8 @@ class BackupVMsWindow(ui_backupdlg.Ui_Backup, multiselectwidget.QtGui.QWizard):
|
|||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
return
|
return
|
||||||
except exc.QubesException:
|
except exc.QubesException:
|
||||||
QtGui.QMessageBox.information(
|
QtWidgets.QMessageBox.information(
|
||||||
None, self.tr("Error loading backup profile"),
|
self, self.tr("Error loading backup profile"),
|
||||||
self.tr("Unable to load saved backup profile."))
|
self.tr("Unable to load saved backup profile."))
|
||||||
return
|
return
|
||||||
if not profile_data:
|
if not profile_data:
|
||||||
@ -216,7 +204,7 @@ class BackupVMsWindow(ui_backupdlg.Ui_Backup, multiselectwidget.QtGui.QWizard):
|
|||||||
|
|
||||||
backup_utils.write_backup_profile(settings, use_temp)
|
backup_utils.write_backup_profile(settings, use_temp)
|
||||||
|
|
||||||
class VmListItem(QtGui.QListWidgetItem):
|
class VmListItem(QtWidgets.QListWidgetItem):
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
def __init__(self, vm):
|
def __init__(self, vm):
|
||||||
self.vm = vm
|
self.vm = vm
|
||||||
@ -276,33 +264,32 @@ class BackupVMsWindow(ui_backupdlg.Ui_Backup, multiselectwidget.QtGui.QWizard):
|
|||||||
elif self.currentPage() is self.select_dir_page:
|
elif self.currentPage() is self.select_dir_page:
|
||||||
backup_location = str(self.dir_line_edit.text())
|
backup_location = str(self.dir_line_edit.text())
|
||||||
if not backup_location:
|
if not backup_location:
|
||||||
QtGui.QMessageBox.information(
|
QtWidgets.QMessageBox.information(
|
||||||
None, self.tr("Wait!"),
|
self, self.tr("Wait!"),
|
||||||
self.tr("Enter backup target location first."))
|
self.tr("Enter backup target location first."))
|
||||||
return False
|
return False
|
||||||
if self.appvm_combobox.currentText() == "dom0" \
|
if self.appvm_combobox.currentText() == "dom0" \
|
||||||
and not os.path.isdir(backup_location):
|
and not os.path.isdir(backup_location):
|
||||||
QtGui.QMessageBox.information(
|
QtWidgets.QMessageBox.information(
|
||||||
None, self.tr("Wait!"),
|
self, self.tr("Wait!"),
|
||||||
self.tr("Selected directory do not exists or "
|
self.tr("Selected directory do not exists or "
|
||||||
"not a directory (%s).") % backup_location)
|
"not a directory (%s).") % backup_location)
|
||||||
return False
|
return False
|
||||||
if not self.passphrase_line_edit.text():
|
if not self.passphrase_line_edit.text():
|
||||||
QtGui.QMessageBox.information(
|
QtWidgets.QMessageBox.information(
|
||||||
None, self.tr("Wait!"),
|
self, self.tr("Wait!"),
|
||||||
self.tr("Enter passphrase for backup "
|
self.tr("Enter passphrase for backup "
|
||||||
"encryption/verification first."))
|
"encryption/verification first."))
|
||||||
return False
|
return False
|
||||||
if self.passphrase_line_edit.text() !=\
|
if self.passphrase_line_edit.text() !=\
|
||||||
self.passphrase_line_edit_verify.text():
|
self.passphrase_line_edit_verify.text():
|
||||||
QtGui.QMessageBox.information(
|
QtWidgets.QMessageBox.information(
|
||||||
None, self.tr("Wait!"),
|
self, self.tr("Wait!"),
|
||||||
self.tr("Enter the same passphrase in both fields."))
|
self.tr("Enter the same passphrase in both fields."))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def cleanup_temporary_files():
|
def cleanup_temporary_files():
|
||||||
try:
|
try:
|
||||||
@ -347,7 +334,7 @@ class BackupVMsWindow(ui_backupdlg.Ui_Backup, multiselectwidget.QtGui.QWizard):
|
|||||||
def backup_finished(self):
|
def backup_finished(self):
|
||||||
if self.thread.msg:
|
if self.thread.msg:
|
||||||
self.progress_status.setText(self.tr("Backup error."))
|
self.progress_status.setText(self.tr("Backup error."))
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
self, self.tr("Backup error!"),
|
self, self.tr("Backup error!"),
|
||||||
self.tr("ERROR: {}").format(
|
self.tr("ERROR: {}").format(
|
||||||
self.thread.msg))
|
self.thread.msg))
|
||||||
@ -383,7 +370,7 @@ class BackupVMsWindow(ui_backupdlg.Ui_Backup, multiselectwidget.QtGui.QWizard):
|
|||||||
'dom0', 'admin.backup.Cancel',
|
'dom0', 'admin.backup.Cancel',
|
||||||
backup_utils.get_profile_name(True))
|
backup_utils.get_profile_name(True))
|
||||||
self.thread.wait()
|
self.thread.wait()
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
self, self.tr("Backup aborted!"),
|
self, self.tr("Backup aborted!"),
|
||||||
self.tr("ERROR: {}").format("Aborted!"))
|
self.tr("ERROR: {}").format("Aborted!"))
|
||||||
|
|
||||||
@ -403,7 +390,7 @@ class BackupVMsWindow(ui_backupdlg.Ui_Backup, multiselectwidget.QtGui.QWizard):
|
|||||||
|
|
||||||
def backup_location_changed(self, new_dir=None):
|
def backup_location_changed(self, new_dir=None):
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
self.select_dir_page.emit(QtCore.SIGNAL("completeChanged()"))
|
self.select_dir_page.completeChanged.emit()
|
||||||
|
|
||||||
|
|
||||||
# Bases on the original code by:
|
# Bases on the original code by:
|
||||||
@ -414,7 +401,7 @@ def handle_exception(exc_type, exc_value, exc_traceback):
|
|||||||
filename = os.path.basename(filename)
|
filename = os.path.basename(filename)
|
||||||
error = "%s: %s" % (exc_type.__name__, exc_value)
|
error = "%s: %s" % (exc_type.__name__, exc_value)
|
||||||
|
|
||||||
QtGui.QMessageBox.critical(
|
QtWidgets.QMessageBox.critical(
|
||||||
None,
|
None,
|
||||||
"Houston, we have a problem...",
|
"Houston, we have a problem...",
|
||||||
"Whoops. A critical error has occured. This is most likely a bug "
|
"Whoops. A critical error has occured. This is most likely a bug "
|
||||||
@ -422,6 +409,7 @@ def handle_exception(exc_type, exc_value, exc_traceback):
|
|||||||
error + "at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
|
error + "at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
|
||||||
% (line, filename))
|
% (line, filename))
|
||||||
|
|
||||||
|
|
||||||
def loop_shutdown():
|
def loop_shutdown():
|
||||||
pending = asyncio.Task.all_tasks()
|
pending = asyncio.Task.all_tasks()
|
||||||
for task in pending:
|
for task in pending:
|
||||||
@ -430,7 +418,7 @@ def loop_shutdown():
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
qt_app = QtGui.QApplication(sys.argv)
|
qt_app = QtWidgets.QApplication(sys.argv)
|
||||||
qt_app.setOrganizationName("The Qubes Project")
|
qt_app.setOrganizationName("The Qubes Project")
|
||||||
qt_app.setOrganizationDomain("http://qubes-os.org")
|
qt_app.setOrganizationDomain("http://qubes-os.org")
|
||||||
qt_app.setApplicationName("Qubes Backup VMs")
|
qt_app.setApplicationName("Qubes Backup VMs")
|
||||||
|
@ -21,8 +21,7 @@
|
|||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
from PyQt4 import QtGui # pylint: disable=import-error
|
from PyQt5 import QtWidgets # pylint: disable=import-error
|
||||||
from PyQt4 import QtCore # pylint: disable=import-error
|
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
from . import utils
|
from . import utils
|
||||||
@ -76,7 +75,7 @@ def select_path_button_clicked(dialog, select_file=False, read_only=False):
|
|||||||
vm = dialog.qubes_app.domains[new_appvm]
|
vm = dialog.qubes_app.domains[new_appvm]
|
||||||
try:
|
try:
|
||||||
if vm.name == socket.gethostname():
|
if vm.name == socket.gethostname():
|
||||||
file_dialog = QtGui.QFileDialog()
|
file_dialog = QtWidgets.QFileDialog()
|
||||||
file_dialog.setReadOnly(True)
|
file_dialog.setReadOnly(True)
|
||||||
|
|
||||||
if select_file:
|
if select_file:
|
||||||
@ -94,8 +93,8 @@ def select_path_button_clicked(dialog, select_file=False, read_only=False):
|
|||||||
else "qubes.SelectDirectory")
|
else "qubes.SelectDirectory")
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
if not read_only:
|
if not read_only:
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
None,
|
dialog,
|
||||||
dialog.tr("Nothing selected!"),
|
dialog.tr("Nothing selected!"),
|
||||||
dialog.tr("No file or directory selected."))
|
dialog.tr("No file or directory selected."))
|
||||||
else:
|
else:
|
||||||
@ -105,7 +104,7 @@ def select_path_button_clicked(dialog, select_file=False, read_only=False):
|
|||||||
dialog.dir_line_edit.setText(new_path)
|
dialog.dir_line_edit.setText(new_path)
|
||||||
|
|
||||||
if new_path and backup_location and not read_only:
|
if new_path and backup_location and not read_only:
|
||||||
dialog.select_dir_page.emit(QtCore.SIGNAL("completeChanged()"))
|
dialog.select_dir_page.completeChanged.emit()
|
||||||
|
|
||||||
|
|
||||||
def get_profile_name(use_temp):
|
def get_profile_name(use_temp):
|
||||||
|
@ -21,12 +21,13 @@ import sys
|
|||||||
import subprocess
|
import subprocess
|
||||||
from . import utils
|
from . import utils
|
||||||
from . import ui_bootfromdevice # pylint: disable=no-name-in-module
|
from . import ui_bootfromdevice # pylint: disable=no-name-in-module
|
||||||
from PyQt4 import QtGui, QtCore # pylint: disable=import-error
|
from PyQt5 import QtWidgets # pylint: disable=import-error
|
||||||
from qubesadmin import tools
|
from qubesadmin import tools
|
||||||
from qubesadmin.tools import qvm_start
|
from qubesadmin.tools import qvm_start
|
||||||
|
|
||||||
|
|
||||||
class VMBootFromDeviceWindow(ui_bootfromdevice.Ui_BootDialog, QtGui.QDialog):
|
class VMBootFromDeviceWindow(ui_bootfromdevice.Ui_BootDialog,
|
||||||
|
QtWidgets.QDialog):
|
||||||
def __init__(self, vm, qapp, parent=None):
|
def __init__(self, vm, qapp, parent=None):
|
||||||
super(VMBootFromDeviceWindow, self).__init__(parent)
|
super(VMBootFromDeviceWindow, self).__init__(parent)
|
||||||
|
|
||||||
@ -37,11 +38,8 @@ class VMBootFromDeviceWindow(ui_bootfromdevice.Ui_BootDialog, QtGui.QDialog):
|
|||||||
self.setWindowTitle(
|
self.setWindowTitle(
|
||||||
self.tr("Boot {vm} from device").format(vm=self.vm.name))
|
self.tr("Boot {vm} from device").format(vm=self.vm.name))
|
||||||
|
|
||||||
self.connect(
|
self.buttonBox.accepted.connect(self.save_and_apply)
|
||||||
self.buttonBox,
|
self.buttonBox.rejected.connect(self.reject)
|
||||||
QtCore.SIGNAL("accepted()"),
|
|
||||||
self.save_and_apply)
|
|
||||||
self.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), self.reject)
|
|
||||||
|
|
||||||
# populate buttons and such
|
# populate buttons and such
|
||||||
self.__init_buttons__()
|
self.__init_buttons__()
|
||||||
@ -59,8 +57,8 @@ class VMBootFromDeviceWindow(ui_bootfromdevice.Ui_BootDialog, QtGui.QDialog):
|
|||||||
self.vm_list[self.fileVM.currentIndex()]) + \
|
self.vm_list[self.fileVM.currentIndex()]) + \
|
||||||
":" + self.pathText.text()
|
":" + self.pathText.text()
|
||||||
else:
|
else:
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
None,
|
self,
|
||||||
self.tr("ERROR!"),
|
self.tr("ERROR!"),
|
||||||
self.tr("No file or block device selected; please select one."))
|
self.tr("No file or block device selected; please select one."))
|
||||||
return
|
return
|
||||||
@ -74,8 +72,8 @@ class VMBootFromDeviceWindow(ui_bootfromdevice.Ui_BootDialog, QtGui.QDialog):
|
|||||||
|
|
||||||
def __warn_if_running__(self):
|
def __warn_if_running__(self):
|
||||||
if self.vm.is_running():
|
if self.vm.is_running():
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
None,
|
self,
|
||||||
self.tr("Warning!"),
|
self.tr("Warning!"),
|
||||||
self.tr("Qube must be turned off before booting it from "
|
self.tr("Qube must be turned off before booting it from "
|
||||||
"device. Please turn off the qube.")
|
"device. Please turn off the qube.")
|
||||||
@ -134,7 +132,7 @@ def main(args=None):
|
|||||||
args = parser.parse_args(args)
|
args = parser.parse_args(args)
|
||||||
vm = args.domains.pop()
|
vm = args.domains.pop()
|
||||||
|
|
||||||
qapp = QtGui.QApplication(sys.argv)
|
qapp = QtWidgets.QApplication(sys.argv)
|
||||||
qapp.setOrganizationName('Invisible Things Lab')
|
qapp.setOrganizationName('Invisible Things Lab')
|
||||||
qapp.setOrganizationDomain("https://www.qubes-os.org/")
|
qapp.setOrganizationDomain("https://www.qubes-os.org/")
|
||||||
qapp.setApplicationName("Boot Qube From Device")
|
qapp.setApplicationName("Boot Qube From Device")
|
||||||
@ -148,5 +146,6 @@ def main(args=None):
|
|||||||
qapp.exec_()
|
qapp.exec_()
|
||||||
qapp.exit()
|
qapp.exit()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/python2
|
#!/usr/bin/python3
|
||||||
# pylint: skip-file
|
|
||||||
#
|
#
|
||||||
# The Qubes OS Project, http://www.qubes-os.org
|
# The Qubes OS Project, http://www.qubes-os.org
|
||||||
#
|
#
|
||||||
@ -26,51 +25,63 @@ import os
|
|||||||
import fcntl
|
import fcntl
|
||||||
from math import log
|
from math import log
|
||||||
|
|
||||||
from PyQt4.QtGui import QApplication
|
# pylint: disable=import-error
|
||||||
|
from PyQt5.QtWidgets import QApplication, QMessageBox
|
||||||
|
|
||||||
APPVIEWER_LOCK = "/var/run/qubes/appviewer.lock"
|
APPVIEWER_LOCK = "/var/run/qubes/appviewer.lock"
|
||||||
CLIPBOARD_CONTENTS = "/var/run/qubes/qubes-clipboard.bin"
|
CLIPBOARD_CONTENTS = "/var/run/qubes/qubes-clipboard.bin"
|
||||||
CLIPBOARD_SOURCE = CLIPBOARD_CONTENTS + ".source"
|
CLIPBOARD_SOURCE = CLIPBOARD_CONTENTS + ".source"
|
||||||
|
|
||||||
|
|
||||||
def do_dom0_copy():
|
def do_dom0_copy():
|
||||||
copy_text_to_qubes_clipboard(QApplication.clipboard().text())
|
copy_text_to_qubes_clipboard(QApplication.clipboard().text())
|
||||||
|
|
||||||
|
|
||||||
def copy_text_to_qubes_clipboard(text):
|
def copy_text_to_qubes_clipboard(text):
|
||||||
# inter-appviewer lock
|
# inter-appviewer lock
|
||||||
|
|
||||||
try:
|
try:
|
||||||
fd = os.open(APPVIEWER_LOCK, os.O_RDWR|os.O_CREAT, 0o0666)
|
file = os.open(APPVIEWER_LOCK, os.O_RDWR | os.O_CREAT, 0o0666)
|
||||||
except:
|
except Exception: # pylint: disable=broad-except
|
||||||
QMessageBox.warning(None, "Warning!", "Error while accessing Qubes clipboard!")
|
QMessageBox.warning(None, "Warning!",
|
||||||
|
"Error while accessing Qubes clipboard!")
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
fcntl.flock(fd, fcntl.LOCK_EX)
|
fcntl.flock(file, fcntl.LOCK_EX)
|
||||||
except:
|
except Exception: # pylint: disable=broad-except
|
||||||
QMessageBox.warning(None, "Warning!", "Error while locking Qubes clipboard!")
|
QMessageBox.warning(None, "Warning!",
|
||||||
|
"Error while locking Qubes clipboard!")
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
with open(CLIPBOARD_CONTENTS, "w") as contents:
|
with open(CLIPBOARD_CONTENTS, "w") as contents:
|
||||||
contents.write(text)
|
contents.write(text)
|
||||||
with open(CLIPBOARD_SOURCE, "w") as source:
|
with open(CLIPBOARD_SOURCE, "w") as source:
|
||||||
source.write("dom0")
|
source.write("dom0")
|
||||||
except:
|
except Exception: # pylint: disable=broad-except
|
||||||
QMessageBox.warning(None, "Warning!", "Error while writing to Qubes clipboard!")
|
QMessageBox.warning(None, "Warning!",
|
||||||
fcntl.flock(fd, fcntl.LOCK_UN)
|
"Error while writing to Qubes clipboard!")
|
||||||
os.close(fd)
|
fcntl.flock(file, fcntl.LOCK_UN)
|
||||||
|
os.close(file)
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=invalid-name
|
||||||
def get_qubes_clipboard_formatted_size():
|
def get_qubes_clipboard_formatted_size():
|
||||||
units = ['B', 'KiB', 'MiB', 'GiB']
|
units = ['B', 'KiB', 'MiB', 'GiB']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
file_size = os.path.getsize(CLIPBOARD_CONTENTS)
|
file_size = os.path.getsize(CLIPBOARD_CONTENTS)
|
||||||
except:
|
except Exception: # pylint: disable=broad-except
|
||||||
QMessageBox.warning(None, "Warning!", "Error while accessing Qubes clipboard!")
|
QMessageBox.warning(None, "Warning!",
|
||||||
|
"Error while accessing Qubes clipboard!")
|
||||||
else:
|
else:
|
||||||
formatted_bytes = '1 byte' if file_size == 1 else str(file_size) + ' bytes'
|
formatted_bytes = '1 byte' if file_size == 1 \
|
||||||
|
else str(file_size) + ' bytes'
|
||||||
if file_size > 0:
|
if file_size > 0:
|
||||||
magnitude = min(int(log(file_size)/log(2)*0.1), len(units)-1)
|
magnitude = min(int(log(file_size)/log(2)*0.1), len(units)-1)
|
||||||
if magnitude > 0:
|
if magnitude > 0:
|
||||||
return '%s (%.1f %s)' % (formatted_bytes, file_size/(2.0**(10*magnitude)), units[magnitude])
|
return '%s (%.1f %s)' % (formatted_bytes,
|
||||||
return '%s' % (formatted_bytes)
|
file_size/(2.0**(10*magnitude)),
|
||||||
|
units[magnitude])
|
||||||
|
return '%s' % formatted_bytes
|
||||||
|
|
||||||
return '? bytes'
|
return '? bytes'
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui # pylint: disable=import-error
|
from PyQt5 import QtCore, QtWidgets # pylint: disable=import-error
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
from qubesadmin import exc
|
from qubesadmin import exc
|
||||||
@ -29,10 +29,10 @@ from qubesadmin import exc
|
|||||||
@contextmanager
|
@contextmanager
|
||||||
def busy_cursor():
|
def busy_cursor():
|
||||||
try:
|
try:
|
||||||
QtGui.QApplication.setOverrideCursor(QtCore.Qt.BusyCursor)
|
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.BusyCursor)
|
||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
QtGui.QApplication.restoreOverrideCursor()
|
QtWidgets.QApplication.restoreOverrideCursor()
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui # pylint: disable=import-error
|
from PyQt5 import QtCore, QtWidgets, QtGui # pylint: disable=import-error
|
||||||
|
|
||||||
import qubesadmin
|
import qubesadmin
|
||||||
import qubesadmin.tools
|
import qubesadmin.tools
|
||||||
@ -34,6 +34,7 @@ from . import utils
|
|||||||
|
|
||||||
from .ui_newappvmdlg import Ui_NewVMDlg # pylint: disable=import-error
|
from .ui_newappvmdlg import Ui_NewVMDlg # pylint: disable=import-error
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
class CreateVMThread(QtCore.QThread):
|
class CreateVMThread(QtCore.QThread):
|
||||||
def __init__(self, app, vmclass, name, label, template, properties):
|
def __init__(self, app, vmclass, name, label, template, properties):
|
||||||
@ -59,8 +60,9 @@ class CreateVMThread(QtCore.QThread):
|
|||||||
for k, v in self.properties.items():
|
for k, v in self.properties.items():
|
||||||
setattr(vm, k, v)
|
setattr(vm, k, v)
|
||||||
else:
|
else:
|
||||||
vm = self.app.add_new_vm(self.vmclass,
|
vm = self.app.add_new_vm(
|
||||||
name=self.name, label=self.label, template=self.template)
|
self.vmclass, name=self.name,
|
||||||
|
label=self.label, template=self.template)
|
||||||
for k, v in self.properties.items():
|
for k, v in self.properties.items():
|
||||||
setattr(vm, k, v)
|
setattr(vm, k, v)
|
||||||
|
|
||||||
@ -70,7 +72,7 @@ class CreateVMThread(QtCore.QThread):
|
|||||||
self.msg = repr(ex)
|
self.msg = repr(ex)
|
||||||
|
|
||||||
|
|
||||||
class NewVmDlg(QtGui.QDialog, Ui_NewVMDlg):
|
class NewVmDlg(QtWidgets.QDialog, Ui_NewVMDlg):
|
||||||
def __init__(self, qtapp, app, parent=None):
|
def __init__(self, qtapp, app, parent=None):
|
||||||
super(NewVmDlg, self).__init__(parent)
|
super(NewVmDlg, self).__init__(parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
@ -111,7 +113,8 @@ class NewVmDlg(QtGui.QDialog, Ui_NewVMDlg):
|
|||||||
self.name.setFocus()
|
self.name.setFocus()
|
||||||
|
|
||||||
if not self.template_list:
|
if not self.template_list:
|
||||||
QtGui.QMessageBox.warning(None,
|
QtWidgets.QMessageBox.warning(
|
||||||
|
self,
|
||||||
self.tr('No template available!'),
|
self.tr('No template available!'),
|
||||||
self.tr('Cannot create a qube when no template exists.'))
|
self.tr('Cannot create a qube when no template exists.'))
|
||||||
|
|
||||||
@ -140,7 +143,8 @@ class NewVmDlg(QtGui.QDialog, Ui_NewVMDlg):
|
|||||||
except LookupError:
|
except LookupError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
QtGui.QMessageBox.warning(None,
|
QtWidgets.QMessageBox.warning(
|
||||||
|
self,
|
||||||
self.tr('Incorrect qube name!'),
|
self.tr('Incorrect qube name!'),
|
||||||
self.tr('A qube with the name <b>{}</b> already exists in the '
|
self.tr('A qube with the name <b>{}</b> already exists in the '
|
||||||
'system!').format(name))
|
'system!').format(name))
|
||||||
@ -153,20 +157,19 @@ class NewVmDlg(QtGui.QDialog, Ui_NewVMDlg):
|
|||||||
else:
|
else:
|
||||||
template = self.template_list[self.template_vm.currentIndex()]
|
template = self.template_list[self.template_vm.currentIndex()]
|
||||||
|
|
||||||
properties = {}
|
properties = {'provides_network': self.provides_network.isChecked()}
|
||||||
properties['provides_network'] = self.provides_network.isChecked()
|
|
||||||
if self.netvm.currentIndex() != 0:
|
if self.netvm.currentIndex() != 0:
|
||||||
properties['netvm'] = self.netvm_list[self.netvm.currentIndex()]
|
properties['netvm'] = self.netvm_list[self.netvm.currentIndex()]
|
||||||
if self.install_system.isChecked():
|
if self.install_system.isChecked():
|
||||||
properties['virt_mode'] = 'hvm'
|
properties['virt_mode'] = 'hvm'
|
||||||
properties['kernel'] = None
|
properties['kernel'] = None
|
||||||
|
|
||||||
self.thread = CreateVMThread(self.app, vmclass, name, label,
|
self.thread = CreateVMThread(
|
||||||
template, properties)
|
self.app, vmclass, name, label, template, properties)
|
||||||
self.thread.finished.connect(self.create_finished)
|
self.thread.finished.connect(self.create_finished)
|
||||||
self.thread.start()
|
self.thread.start()
|
||||||
|
|
||||||
self.progress = QtGui.QProgressDialog(
|
self.progress = QtWidgets.QProgressDialog(
|
||||||
self.tr("Creating new qube <b>{}</b>...").format(name), "", 0, 0)
|
self.tr("Creating new qube <b>{}</b>...").format(name), "", 0, 0)
|
||||||
self.progress.setCancelButton(None)
|
self.progress.setCancelButton(None)
|
||||||
self.progress.setModal(True)
|
self.progress.setModal(True)
|
||||||
@ -176,7 +179,8 @@ class NewVmDlg(QtGui.QDialog, Ui_NewVMDlg):
|
|||||||
self.progress.hide()
|
self.progress.hide()
|
||||||
|
|
||||||
if self.thread.msg:
|
if self.thread.msg:
|
||||||
QtGui.QMessageBox.warning(None,
|
QtWidgets.QMessageBox.warning(
|
||||||
|
self,
|
||||||
self.tr("Error creating the qube!"),
|
self.tr("Error creating the qube!"),
|
||||||
self.tr("ERROR: {}").format(self.thread.msg))
|
self.tr("ERROR: {}").format(self.thread.msg))
|
||||||
|
|
||||||
@ -190,7 +194,6 @@ class NewVmDlg(QtGui.QDialog, Ui_NewVMDlg):
|
|||||||
subprocess.check_call(
|
subprocess.check_call(
|
||||||
['qubes-vm-boot-from-device', str(self.name.text())])
|
['qubes-vm-boot-from-device', str(self.name.text())])
|
||||||
|
|
||||||
|
|
||||||
def type_change(self):
|
def type_change(self):
|
||||||
# AppVM
|
# AppVM
|
||||||
if self.vm_type.currentIndex() == 0:
|
if self.vm_type.currentIndex() == 0:
|
||||||
@ -221,12 +224,14 @@ class NewVmDlg(QtGui.QDialog, Ui_NewVMDlg):
|
|||||||
if self.launch_settings.isChecked() and self.install_system.isEnabled():
|
if self.launch_settings.isChecked() and self.install_system.isEnabled():
|
||||||
self.install_system.setChecked(False)
|
self.install_system.setChecked(False)
|
||||||
|
|
||||||
|
|
||||||
parser = qubesadmin.tools.QubesArgumentParser()
|
parser = qubesadmin.tools.QubesArgumentParser()
|
||||||
|
|
||||||
|
|
||||||
def main(args=None):
|
def main(args=None):
|
||||||
args = parser.parse_args(args)
|
args = parser.parse_args(args)
|
||||||
|
|
||||||
qtapp = QtGui.QApplication(sys.argv)
|
qtapp = QtWidgets.QApplication(sys.argv)
|
||||||
qtapp.setOrganizationName('Invisible Things Lab')
|
qtapp.setOrganizationName('Invisible Things Lab')
|
||||||
qtapp.setOrganizationDomain('https://www.qubes-os.org/')
|
qtapp.setOrganizationDomain('https://www.qubes-os.org/')
|
||||||
qtapp.setApplicationName('Create qube')
|
qtapp.setApplicationName('Create qube')
|
||||||
|
@ -18,10 +18,10 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
from . import ui_devicelist # pylint: disable=no-name-in-module
|
from . import ui_devicelist # pylint: disable=no-name-in-module
|
||||||
from PyQt4 import QtGui, QtCore # pylint: disable=import-error
|
from PyQt5 import QtWidgets # pylint: disable=import-error
|
||||||
|
|
||||||
|
|
||||||
class PCIDeviceListWindow(ui_devicelist.Ui_Dialog, QtGui.QDialog):
|
class PCIDeviceListWindow(ui_devicelist.Ui_Dialog, QtWidgets.QDialog):
|
||||||
def __init__(self, vm, qapp, dev_list, no_strict_reset_list, parent=None):
|
def __init__(self, vm, qapp, dev_list, no_strict_reset_list, parent=None):
|
||||||
super(PCIDeviceListWindow, self).__init__(parent)
|
super(PCIDeviceListWindow, self).__init__(parent)
|
||||||
|
|
||||||
@ -32,10 +32,8 @@ class PCIDeviceListWindow(ui_devicelist.Ui_Dialog, QtGui.QDialog):
|
|||||||
|
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
self.connect(
|
self.buttonBox.accepted.connect(self.save_and_apply)
|
||||||
self.buttonBox, QtCore.SIGNAL("accepted()"), self.save_and_apply)
|
self.buttonBox.rejected.connect(self.reject)
|
||||||
self.connect(
|
|
||||||
self.buttonBox, QtCore.SIGNAL("rejected()"), self.reject)
|
|
||||||
|
|
||||||
self.ident_list = {}
|
self.ident_list = {}
|
||||||
self.fill_device_list()
|
self.fill_device_list()
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui # pylint: disable=import-error
|
from PyQt5 import QtCore, QtGui, QtWidgets # pylint: disable=import-error
|
||||||
import qubesadmin.firewall
|
import qubesadmin.firewall
|
||||||
|
|
||||||
from . import ui_newfwruledlg # pylint: disable=no-name-in-module
|
from . import ui_newfwruledlg # pylint: disable=no-name-in-module
|
||||||
@ -30,6 +30,7 @@ from . import ui_newfwruledlg # pylint: disable=no-name-in-module
|
|||||||
class FirewallModifiedOutsideError(ValueError):
|
class FirewallModifiedOutsideError(ValueError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class QIPAddressValidator(QtGui.QValidator):
|
class QIPAddressValidator(QtGui.QValidator):
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
@ -40,10 +41,10 @@ class QIPAddressValidator(QtGui.QValidator):
|
|||||||
hostname = str(input_string)
|
hostname = str(input_string)
|
||||||
|
|
||||||
if len(hostname) > 255 or not hostname:
|
if len(hostname) > 255 or not hostname:
|
||||||
return (QtGui.QValidator.Intermediate, input_string, pos)
|
return QtGui.QValidator.Intermediate, input_string, pos
|
||||||
|
|
||||||
if hostname == "*":
|
if hostname == "*":
|
||||||
return (QtGui.QValidator.Acceptable, input_string, pos)
|
return QtGui.QValidator.Acceptable, input_string, pos
|
||||||
|
|
||||||
unmask = hostname.split("/", 1)
|
unmask = hostname.split("/", 1)
|
||||||
if len(unmask) == 2:
|
if len(unmask) == 2:
|
||||||
@ -51,27 +52,28 @@ class QIPAddressValidator(QtGui.QValidator):
|
|||||||
mask = unmask[1]
|
mask = unmask[1]
|
||||||
if mask.isdigit() or mask == "":
|
if mask.isdigit() or mask == "":
|
||||||
if re.match(r"^([0-9]{1,3}\.){3}[0-9]{1,3}$", hostname) is None:
|
if re.match(r"^([0-9]{1,3}\.){3}[0-9]{1,3}$", hostname) is None:
|
||||||
return (QtGui.QValidator.Invalid, input_string, pos)
|
return QtGui.QValidator.Invalid, input_string, pos
|
||||||
if mask != "":
|
if mask != "":
|
||||||
mask = int(unmask[1])
|
mask = int(unmask[1])
|
||||||
if mask < 0 or mask > 32:
|
if mask < 0 or mask > 32:
|
||||||
return (QtGui.QValidator.Invalid, input_string, pos)
|
return QtGui.QValidator.Invalid, input_string, pos
|
||||||
else:
|
else:
|
||||||
return (QtGui.QValidator.Invalid, input_string, pos)
|
return QtGui.QValidator.Invalid, input_string, pos
|
||||||
|
|
||||||
if hostname[-1:] == ".":
|
if hostname[-1:] == ".":
|
||||||
hostname = hostname[:-1]
|
hostname = hostname[:-1]
|
||||||
|
|
||||||
if hostname[-1:] == "-":
|
if hostname[-1:] == "-":
|
||||||
return (QtGui.QValidator.Intermediate, input_string, pos)
|
return QtGui.QValidator.Intermediate, input_string, pos
|
||||||
|
|
||||||
allowed = re.compile(r"(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
|
allowed = re.compile(r"(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
|
||||||
if all(allowed.match(x) for x in hostname.split(".")):
|
if all(allowed.match(x) for x in hostname.split(".")):
|
||||||
return (QtGui.QValidator.Acceptable, input_string, pos)
|
return QtGui.QValidator.Acceptable, input_string, pos
|
||||||
|
|
||||||
return (QtGui.QValidator.Invalid, input_string, pos)
|
return QtGui.QValidator.Invalid, input_string, pos
|
||||||
|
|
||||||
class NewFwRuleDlg(QtGui.QDialog, ui_newfwruledlg.Ui_NewFwRuleDlg):
|
|
||||||
|
class NewFwRuleDlg(QtWidgets.QDialog, ui_newfwruledlg.Ui_NewFwRuleDlg):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super(NewFwRuleDlg, self).__init__(parent)
|
super(NewFwRuleDlg, self).__init__(parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
@ -84,19 +86,20 @@ class NewFwRuleDlg(QtGui.QDialog, ui_newfwruledlg.Ui_NewFwRuleDlg):
|
|||||||
QtCore.QRegExp("[a-z][a-z0-9-]+|[0-9]+(-[0-9]+)?",
|
QtCore.QRegExp("[a-z][a-z0-9-]+|[0-9]+(-[0-9]+)?",
|
||||||
QtCore.Qt.CaseInsensitive), None))
|
QtCore.Qt.CaseInsensitive), None))
|
||||||
self.serviceComboBox.setEnabled(False)
|
self.serviceComboBox.setEnabled(False)
|
||||||
self.serviceComboBox.setInsertPolicy(QtGui.QComboBox.InsertAtBottom)
|
self.serviceComboBox.setInsertPolicy(QtWidgets.QComboBox.InsertAtBottom)
|
||||||
self.populate_combos()
|
self.populate_combos()
|
||||||
self.serviceComboBox.setInsertPolicy(QtGui.QComboBox.InsertAtTop)
|
self.serviceComboBox.setInsertPolicy(QtWidgets.QComboBox.InsertAtTop)
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
if self.tcp_radio.isChecked() or self.udp_radio.isChecked():
|
if self.tcp_radio.isChecked() or self.udp_radio.isChecked():
|
||||||
if not self.serviceComboBox.currentText():
|
if not self.serviceComboBox.currentText():
|
||||||
msg = QtGui.QMessageBox()
|
msg = QtWidgets.QMessageBox()
|
||||||
msg.warning(self, self.tr("Firewall rule"),
|
msg.warning(
|
||||||
|
self, self.tr("Firewall rule"),
|
||||||
self.tr("You need to fill service "
|
self.tr("You need to fill service "
|
||||||
"name/port for TCP/UDP rule"))
|
"name/port for TCP/UDP rule"))
|
||||||
return
|
return
|
||||||
QtGui.QDialog.accept(self)
|
super().accept()
|
||||||
|
|
||||||
def populate_combos(self):
|
def populate_combos(self):
|
||||||
example_addresses = [
|
example_addresses = [
|
||||||
@ -122,7 +125,7 @@ class NewFwRuleDlg(QtGui.QDialog, ui_newfwruledlg.Ui_NewFwRuleDlg):
|
|||||||
self.set_ok_state(True)
|
self.set_ok_state(True)
|
||||||
|
|
||||||
def set_ok_state(self, ok_state):
|
def set_ok_state(self, ok_state):
|
||||||
ok_button = self.buttonBox.button(QtGui.QDialogButtonBox.Ok)
|
ok_button = self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok)
|
||||||
if ok_button is not None:
|
if ok_button is not None:
|
||||||
ok_button.setEnabled(ok_state)
|
ok_button.setEnabled(ok_state)
|
||||||
|
|
||||||
@ -172,7 +175,6 @@ class QubesFirewallRulesModel(QtCore.QAbstractItemModel):
|
|||||||
index2 = self.createIndex(len(self) - 1, len(self.__column_names) - 1)
|
index2 = self.createIndex(len(self) - 1, len(self.__column_names) - 1)
|
||||||
self.dataChanged.emit(index1, index2)
|
self.dataChanged.emit(index1, index2)
|
||||||
|
|
||||||
|
|
||||||
def get_service_name(self, port):
|
def get_service_name(self, port):
|
||||||
for service in self.__services:
|
for service in self.__services:
|
||||||
if str(service[1]) == str(port):
|
if str(service[1]) == str(port):
|
||||||
@ -286,19 +288,19 @@ class QubesFirewallRulesModel(QtCore.QAbstractItemModel):
|
|||||||
rules.append(rule)
|
rules.append(rule)
|
||||||
|
|
||||||
if not conf['allow']:
|
if not conf['allow']:
|
||||||
rules.append(qubesadmin.firewall.Rule(None,
|
rules.append(qubesadmin.firewall.Rule(
|
||||||
action='accept', specialtarget='dns'))
|
None, action='accept', specialtarget='dns'))
|
||||||
|
|
||||||
if not conf['allow']:
|
if not conf['allow']:
|
||||||
rules.append(qubesadmin.firewall.Rule(None,
|
rules.append(qubesadmin.firewall.Rule(
|
||||||
action='accept', proto='icmp'))
|
None, action='accept', proto='icmp'))
|
||||||
|
|
||||||
if conf['allow']:
|
if conf['allow']:
|
||||||
rules.append(qubesadmin.firewall.Rule(None,
|
rules.append(qubesadmin.firewall.Rule(
|
||||||
action='accept'))
|
None, action='accept'))
|
||||||
else:
|
else:
|
||||||
rules.append(qubesadmin.firewall.Rule(None,
|
rules.append(qubesadmin.firewall.Rule(
|
||||||
action='drop'))
|
None, action='drop'))
|
||||||
|
|
||||||
vm.firewall.rules = rules
|
vm.firewall.rules = rules
|
||||||
|
|
||||||
@ -372,7 +374,8 @@ class QubesFirewallRulesModel(QtCore.QAbstractItemModel):
|
|||||||
try:
|
try:
|
||||||
rule.dsthost = address
|
rule.dsthost = address
|
||||||
except ValueError:
|
except ValueError:
|
||||||
QtGui.QMessageBox.warning(None, self.tr("Invalid address"),
|
QtWidgets.QMessageBox.warning(
|
||||||
|
dialog, self.tr("Invalid address"),
|
||||||
self.tr("Address '{0}' is invalid.").format(address))
|
self.tr("Address '{0}' is invalid.").format(address))
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -385,11 +388,11 @@ class QubesFirewallRulesModel(QtCore.QAbstractItemModel):
|
|||||||
try:
|
try:
|
||||||
rule.dstports = service
|
rule.dstports = service
|
||||||
except ValueError:
|
except ValueError:
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
None,
|
dialog,
|
||||||
self.tr("Invalid port or service"),
|
self.tr("Invalid port or service"),
|
||||||
self.tr("Port number or service '{0}' is invalid.")
|
self.tr("Port number or service '{0}' is "
|
||||||
.format(service))
|
"invalid.").format(service))
|
||||||
return
|
return
|
||||||
elif service:
|
elif service:
|
||||||
try:
|
try:
|
||||||
@ -398,10 +401,12 @@ class QubesFirewallRulesModel(QtCore.QAbstractItemModel):
|
|||||||
if self.get_service_port(service) is not None:
|
if self.get_service_port(service) is not None:
|
||||||
rule.dstports = self.get_service_port(service)
|
rule.dstports = self.get_service_port(service)
|
||||||
else:
|
else:
|
||||||
QtGui.QMessageBox.warning(None,
|
QtWidgets.QMessageBox.warning(
|
||||||
|
dialog,
|
||||||
self.tr("Invalid port or service"),
|
self.tr("Invalid port or service"),
|
||||||
self.tr("Port number or service '{0}' is invalid.")
|
self.tr(
|
||||||
.format(service))
|
"Port number or service '{0}' is "
|
||||||
|
"invalid.".format(service)))
|
||||||
return
|
return
|
||||||
|
|
||||||
if row is not None:
|
if row is not None:
|
||||||
|
@ -24,7 +24,7 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import traceback
|
import traceback
|
||||||
from PyQt4 import QtCore, QtGui # pylint: disable=import-error
|
from PyQt5 import QtWidgets # pylint: disable=import-error
|
||||||
|
|
||||||
from qubesadmin import Qubes
|
from qubesadmin import Qubes
|
||||||
from qubesadmin.utils import parse_size
|
from qubesadmin.utils import parse_size
|
||||||
@ -36,9 +36,10 @@ from configparser import ConfigParser
|
|||||||
|
|
||||||
qmemman_config_path = '/etc/qubes/qmemman.conf'
|
qmemman_config_path = '/etc/qubes/qmemman.conf'
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-many-instance-attributes
|
# pylint: disable=too-many-instance-attributes
|
||||||
class GlobalSettingsWindow(ui_globalsettingsdlg.Ui_GlobalSettings,
|
class GlobalSettingsWindow(ui_globalsettingsdlg.Ui_GlobalSettings,
|
||||||
QtGui.QDialog):
|
QtWidgets.QDialog):
|
||||||
|
|
||||||
def __init__(self, app, qvm_collection, parent=None):
|
def __init__(self, app, qvm_collection, parent=None):
|
||||||
super(GlobalSettingsWindow, self).__init__(parent)
|
super(GlobalSettingsWindow, self).__init__(parent)
|
||||||
@ -48,11 +49,8 @@ class GlobalSettingsWindow(ui_globalsettingsdlg.Ui_GlobalSettings,
|
|||||||
|
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
self.connect(
|
self.buttonBox.accepted.connect(self.save_and_apply)
|
||||||
self.buttonBox,
|
self.buttonBox.rejected.connect(self.reject)
|
||||||
QtCore.SIGNAL("accepted()"),
|
|
||||||
self.save_and_apply)
|
|
||||||
self.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), self.reject)
|
|
||||||
|
|
||||||
self.__init_system_defaults__()
|
self.__init_system_defaults__()
|
||||||
self.__init_kernel_defaults__()
|
self.__init_kernel_defaults__()
|
||||||
@ -172,7 +170,6 @@ class GlobalSettingsWindow(ui_globalsettingsdlg.Ui_GlobalSettings,
|
|||||||
self.min_vm_mem.setValue(self.vm_min_mem_val/1024/1024)
|
self.min_vm_mem.setValue(self.vm_min_mem_val/1024/1024)
|
||||||
self.dom0_mem_boost.setValue(self.dom0_mem_boost_val/1024/1024)
|
self.dom0_mem_boost.setValue(self.dom0_mem_boost_val/1024/1024)
|
||||||
|
|
||||||
|
|
||||||
def __apply_mem_defaults__(self):
|
def __apply_mem_defaults__(self):
|
||||||
|
|
||||||
# qmemman settings
|
# qmemman settings
|
||||||
@ -252,23 +249,23 @@ class GlobalSettingsWindow(ui_globalsettingsdlg.Ui_GlobalSettings,
|
|||||||
self.disable_updates_all.clicked.connect(self.__disable_updates_all)
|
self.disable_updates_all.clicked.connect(self.__disable_updates_all)
|
||||||
|
|
||||||
def __enable_updates_all(self):
|
def __enable_updates_all(self):
|
||||||
reply = QtGui.QMessageBox.question(
|
reply = QtWidgets.QMessageBox.question(
|
||||||
self, self.tr("Change state of all qubes"),
|
self, self.tr("Change state of all qubes"),
|
||||||
self.tr("Are you sure you want to set all qubes to check "
|
self.tr("Are you sure you want to set all qubes to check "
|
||||||
"for updates?"),
|
"for updates?"),
|
||||||
QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel)
|
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel)
|
||||||
if reply == QtGui.QMessageBox.Cancel:
|
if reply == QtWidgets.QMessageBox.Cancel:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.__set_updates_all(True)
|
self.__set_updates_all(True)
|
||||||
|
|
||||||
def __disable_updates_all(self):
|
def __disable_updates_all(self):
|
||||||
reply = QtGui.QMessageBox.question(
|
reply = QtWidgets.QMessageBox.question(
|
||||||
self, self.tr("Change state of all qubes"),
|
self, self.tr("Change state of all qubes"),
|
||||||
self.tr("Are you sure you want to set all qubes to not check "
|
self.tr("Are you sure you want to set all qubes to not check "
|
||||||
"for updates?"),
|
"for updates?"),
|
||||||
QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel)
|
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel)
|
||||||
if reply == QtGui.QMessageBox.Cancel:
|
if reply == QtWidgets.QMessageBox.Cancel:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.__set_updates_all(False)
|
self.__set_updates_all(False)
|
||||||
@ -298,7 +295,6 @@ class GlobalSettingsWindow(ui_globalsettingsdlg.Ui_GlobalSettings,
|
|||||||
self.__apply_updates__()
|
self.__apply_updates__()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Bases on the original code by:
|
# Bases on the original code by:
|
||||||
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
|
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
|
||||||
|
|
||||||
@ -307,7 +303,7 @@ def handle_exception(exc_type, exc_value, exc_traceback):
|
|||||||
filename = os.path.basename(filename)
|
filename = os.path.basename(filename)
|
||||||
error = "%s: %s" % (exc_type.__name__, exc_value)
|
error = "%s: %s" % (exc_type.__name__, exc_value)
|
||||||
|
|
||||||
QtGui.QMessageBox.critical(
|
QtWidgets.QMessageBox.critical(
|
||||||
None,
|
None,
|
||||||
"Houston, we have a problem...",
|
"Houston, we have a problem...",
|
||||||
"Whoops. A critical error has occured. This is most likely a bug "
|
"Whoops. A critical error has occured. This is most likely a bug "
|
||||||
@ -317,7 +313,7 @@ def handle_exception(exc_type, exc_value, exc_traceback):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
qtapp = QtGui.QApplication(sys.argv)
|
qtapp = QtWidgets.QApplication(sys.argv)
|
||||||
qtapp.setOrganizationName("The Qubes Project")
|
qtapp.setOrganizationName("The Qubes Project")
|
||||||
qtapp.setOrganizationDomain("http://qubes-os.org")
|
qtapp.setOrganizationDomain("http://qubes-os.org")
|
||||||
qtapp.setApplicationName("Qubes Global Settings")
|
qtapp.setApplicationName("Qubes Global Settings")
|
||||||
@ -333,5 +329,6 @@ def main():
|
|||||||
qtapp.exec_()
|
qtapp.exec_()
|
||||||
qtapp.exit()
|
qtapp.exit()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
# with this program; if not, see <http://www.gnu.org/licenses/>.
|
# with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
from PyQt4.QtGui import QDialog # pylint: disable=import-error
|
from PyQt5.QtWidgets import QDialog # pylint: disable=import-error
|
||||||
|
|
||||||
from . import ui_informationnotes # pylint: disable=no-name-in-module
|
from . import ui_informationnotes # pylint: disable=no-name-in-module
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -20,8 +20,7 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
import sys
|
import sys
|
||||||
from PyQt4 import QtCore # pylint: disable=import-error
|
from PyQt5 import QtWidgets # pylint: disable=import-error
|
||||||
from PyQt4 import QtGui # pylint: disable=import-error
|
|
||||||
|
|
||||||
from . import ui_logdlg # pylint: disable=no-name-in-module
|
from . import ui_logdlg # pylint: disable=no-name-in-module
|
||||||
from . import clipboard
|
from . import clipboard
|
||||||
@ -33,7 +32,7 @@ from qubesadmin import Qubes
|
|||||||
LOG_DISPLAY_SIZE = 1024*1024
|
LOG_DISPLAY_SIZE = 1024*1024
|
||||||
|
|
||||||
|
|
||||||
class LogDialog(ui_logdlg.Ui_LogDialog, QtGui.QDialog):
|
class LogDialog(ui_logdlg.Ui_LogDialog, QtWidgets.QDialog):
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
|
|
||||||
def __init__(self, app, log_path, parent=None):
|
def __init__(self, app, log_path, parent=None):
|
||||||
@ -45,8 +44,9 @@ class LogDialog(ui_logdlg.Ui_LogDialog, QtGui.QDialog):
|
|||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.setWindowTitle(log_path)
|
self.setWindowTitle(log_path)
|
||||||
|
|
||||||
self.connect(self.copy_to_qubes_clipboard,
|
self.copy_to_qubes_clipboard.clicked.connect(
|
||||||
QtCore.SIGNAL("clicked()"),
|
self.copy_to_clipboard_triggered)
|
||||||
|
self.copy_to_qubes_clipboard.clicked.connect(
|
||||||
self.copy_to_clipboard_triggered)
|
self.copy_to_clipboard_triggered)
|
||||||
|
|
||||||
self.__init_log_text__()
|
self.__init_log_text__()
|
||||||
@ -64,6 +64,7 @@ class LogDialog(ui_logdlg.Ui_LogDialog, QtGui.QDialog):
|
|||||||
self.displayed_text += log.read()
|
self.displayed_text += log.read()
|
||||||
log.close()
|
log.close()
|
||||||
self.log_text.setPlainText(self.displayed_text)
|
self.log_text.setPlainText(self.displayed_text)
|
||||||
|
self.log_text.show()
|
||||||
|
|
||||||
def copy_to_clipboard_triggered(self):
|
def copy_to_clipboard_triggered(self):
|
||||||
clipboard.copy_text_to_qubes_clipboard(self.displayed_text)
|
clipboard.copy_text_to_qubes_clipboard(self.displayed_text)
|
||||||
@ -71,7 +72,7 @@ class LogDialog(ui_logdlg.Ui_LogDialog, QtGui.QDialog):
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
qubes_app = Qubes()
|
qubes_app = Qubes()
|
||||||
qt_app = QtGui.QApplication(sys.argv)
|
qt_app = QtWidgets.QApplication(sys.argv)
|
||||||
|
|
||||||
log_window = LogDialog(qubes_app, sys.argv[1])
|
log_window = LogDialog(qubes_app, sys.argv[1])
|
||||||
log_window.show()
|
log_window.show()
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
from PyQt4 import QtCore, QtGui # pylint: disable=import-error
|
from PyQt5 import QtCore, QtWidgets # pylint: disable=import-error
|
||||||
from . import ui_multiselectwidget # pylint: disable=no-name-in-module
|
from . import ui_multiselectwidget # pylint: disable=no-name-in-module
|
||||||
|
|
||||||
class MultiSelectWidget(
|
|
||||||
ui_multiselectwidget.Ui_MultiSelectWidget, QtGui.QWidget):
|
|
||||||
|
|
||||||
__pyqtSignals__ = ("selected_changed()",)
|
class MultiSelectWidget(
|
||||||
__pyqtSignals__ = ("items_added(PyQt_PyObject)",)
|
ui_multiselectwidget.Ui_MultiSelectWidget, QtWidgets.QWidget):
|
||||||
__pyqtSignals__ = ("items_removed(PyQt_PyObject)",)
|
|
||||||
|
selectedChanged = QtCore.pyqtSignal()
|
||||||
|
itemsAdded = QtCore.pyqtSignal(list)
|
||||||
|
itemsRemoved = QtCore.pyqtSignal(list)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super(MultiSelectWidget, self).__init__(parent)
|
super(MultiSelectWidget, self).__init__(parent)
|
||||||
@ -16,9 +17,9 @@ class MultiSelectWidget(
|
|||||||
self.remove_selected_button.clicked.connect(self.remove_selected)
|
self.remove_selected_button.clicked.connect(self.remove_selected)
|
||||||
self.remove_all_button.clicked.connect(self.remove_all)
|
self.remove_all_button.clicked.connect(self.remove_all)
|
||||||
self.available_list.setSelectionMode(
|
self.available_list.setSelectionMode(
|
||||||
QtGui.QAbstractItemView.ExtendedSelection)
|
QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||||
self.selected_list.setSelectionMode(
|
self.selected_list.setSelectionMode(
|
||||||
QtGui.QAbstractItemView.ExtendedSelection)
|
QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||||
|
|
||||||
def switch_selected(self, src, dst):
|
def switch_selected(self, src, dst):
|
||||||
selected = src.selectedItems()
|
selected = src.selectedItems()
|
||||||
@ -30,11 +31,11 @@ class MultiSelectWidget(
|
|||||||
dst.addItem(item)
|
dst.addItem(item)
|
||||||
items.append(item)
|
items.append(item)
|
||||||
dst.sortItems()
|
dst.sortItems()
|
||||||
self.emit(QtCore.SIGNAL("selected_changed()"))
|
self.selectedChanged.emit()
|
||||||
if src is self.selected_list:
|
if src is self.selected_list:
|
||||||
self.emit(QtCore.SIGNAL("items_removed(PyQt_PyObject)"), items)
|
self.itemsRemoved.emit(items)
|
||||||
else:
|
else:
|
||||||
self.emit(QtCore.SIGNAL("items_added(PyQt_PyObject)"), items)
|
self.itemsAdded.emit(items)
|
||||||
|
|
||||||
def add_selected(self):
|
def add_selected(self):
|
||||||
self.switch_selected(self.available_list, self.selected_list)
|
self.switch_selected(self.available_list, self.selected_list)
|
||||||
@ -49,12 +50,11 @@ class MultiSelectWidget(
|
|||||||
dst.addItem(item)
|
dst.addItem(item)
|
||||||
items.append(item)
|
items.append(item)
|
||||||
dst.sortItems()
|
dst.sortItems()
|
||||||
self.emit(QtCore.SIGNAL("selected_changed()"))
|
self.selectedChanged.emit()
|
||||||
if src is self.selected_list:
|
if src is self.selected_list:
|
||||||
self.emit(QtCore.SIGNAL("items_removed(PyQt_PyObject)"), items)
|
self.itemsRemoved.emit(items)
|
||||||
else:
|
else:
|
||||||
self.emit(QtCore.SIGNAL("items_added(PyQt_PyObject)"), items)
|
self.itemsAdded.emit(items)
|
||||||
|
|
||||||
|
|
||||||
def add_all(self):
|
def add_all(self):
|
||||||
self.move_all(self.available_list, self.selected_list)
|
self.move_all(self.available_list, self.selected_list)
|
||||||
|
@ -37,8 +37,7 @@ from qubesadmin import exc
|
|||||||
from qubesadmin import utils
|
from qubesadmin import utils
|
||||||
from qubesadmin import events
|
from qubesadmin import events
|
||||||
|
|
||||||
from PyQt4 import QtGui # pylint: disable=import-error
|
from PyQt5 import QtWidgets, QtCore, QtGui # pylint: disable=import-error
|
||||||
from PyQt4 import QtCore # pylint: disable=import-error
|
|
||||||
|
|
||||||
from qubesmanager.about import AboutDialog
|
from qubesmanager.about import AboutDialog
|
||||||
|
|
||||||
@ -54,7 +53,7 @@ from . import utils as manager_utils
|
|||||||
from . import common_threads
|
from . import common_threads
|
||||||
|
|
||||||
|
|
||||||
class SearchBox(QtGui.QLineEdit):
|
class SearchBox(QtWidgets.QLineEdit):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super(SearchBox, self).__init__(parent)
|
super(SearchBox, self).__init__(parent)
|
||||||
self.focusing = False
|
self.focusing = False
|
||||||
@ -229,16 +228,25 @@ class VmShutdownMonitor(QtCore.QObject):
|
|||||||
if vm_is_running and vm_start_time \
|
if vm_is_running and vm_start_time \
|
||||||
and vm_start_time < self.shutdown_started:
|
and vm_start_time < self.shutdown_started:
|
||||||
if self.timeout_reached():
|
if self.timeout_reached():
|
||||||
reply = QtGui.QMessageBox.question(
|
|
||||||
None, self.tr("Qube Shutdown"),
|
msgbox = QtWidgets.QMessageBox(self.caller)
|
||||||
self.tr(
|
msgbox.setIcon(QtWidgets.QMessageBox.Question)
|
||||||
|
msgbox.setWindowTitle(self.tr("Qube Shutdown"))
|
||||||
|
msgbox.setText(self.tr(
|
||||||
"The Qube <b>'{0}'</b> hasn't shutdown within the last "
|
"The Qube <b>'{0}'</b> hasn't shutdown within the last "
|
||||||
"{1} seconds, do you want to kill it?<br>").format(
|
"{1} seconds, do you want to kill it?<br>").format(
|
||||||
vm.name, self.shutdown_time / 1000),
|
vm.name, self.shutdown_time / 1000))
|
||||||
self.tr("Kill it!"),
|
kill_button = msgbox.addButton(
|
||||||
|
self.tr("Kill it!"), QtWidgets.QMessageBox.YesRole)
|
||||||
|
wait_button = msgbox.addButton(
|
||||||
self.tr("Wait another {0} seconds...").format(
|
self.tr("Wait another {0} seconds...").format(
|
||||||
self.shutdown_time / 1000))
|
self.shutdown_time / 1000),
|
||||||
if reply == 0:
|
QtWidgets.QMessageBox.NoRole)
|
||||||
|
msgbox.setDefaultButton(wait_button)
|
||||||
|
msgbox.exec_()
|
||||||
|
msgbox.deleteLater()
|
||||||
|
|
||||||
|
if msgbox.clickedButton() is kill_button:
|
||||||
try:
|
try:
|
||||||
vm.kill()
|
vm.kill()
|
||||||
except exc.QubesVMNotStartedError:
|
except exc.QubesVMNotStartedError:
|
||||||
@ -290,7 +298,8 @@ class UpdateVMThread(common_threads.QubesThread):
|
|||||||
user="root",
|
user="root",
|
||||||
input=dsa4371update.read())
|
input=dsa4371update.read())
|
||||||
if stdout == b'changed=yes\n':
|
if stdout == b'changed=yes\n':
|
||||||
subprocess.call(['notify-send', '-i', 'dialog-information',
|
subprocess.call(
|
||||||
|
['notify-send', '-i', 'dialog-information',
|
||||||
'Debian DSA-4371 fix installed in {}'.format(
|
'Debian DSA-4371 fix installed in {}'.format(
|
||||||
self.vm.name)])
|
self.vm.name)])
|
||||||
elif stdout == b'changed=no\n':
|
elif stdout == b'changed=no\n':
|
||||||
@ -299,7 +308,7 @@ class UpdateVMThread(common_threads.QubesThread):
|
|||||||
raise exc.QubesException(
|
raise exc.QubesException(
|
||||||
"Failed to apply DSA-4371 fix: {}".format(
|
"Failed to apply DSA-4371 fix: {}".format(
|
||||||
stderr.decode('ascii')))
|
stderr.decode('ascii')))
|
||||||
self.vm.run_service("qubes.InstallUpdatesGUI",\
|
self.vm.run_service("qubes.InstallUpdatesGUI",
|
||||||
user="root", wait=False)
|
user="root", wait=False)
|
||||||
except (ChildProcessError, exc.QubesException) as ex:
|
except (ChildProcessError, exc.QubesException) as ex:
|
||||||
self.msg = ("Error on qube update!", str(ex))
|
self.msg = ("Error on qube update!", str(ex))
|
||||||
@ -318,7 +327,7 @@ class RunCommandThread(common_threads.QubesThread):
|
|||||||
self.msg = ("Error while running command!", str(ex))
|
self.msg = ("Error while running command!", str(ex))
|
||||||
|
|
||||||
|
|
||||||
class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtWidgets.QMainWindow):
|
||||||
# pylint: disable=too-many-instance-attributes
|
# pylint: disable=too-many-instance-attributes
|
||||||
row_height = 30
|
row_height = 30
|
||||||
column_width = 200
|
column_width = 200
|
||||||
@ -337,8 +346,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
"Include in backups": 9,
|
"Include in backups": 9,
|
||||||
"Last backup": 10,
|
"Last backup": 10,
|
||||||
"Default DispVM": 11,
|
"Default DispVM": 11,
|
||||||
"Is DVM Template": 12
|
"Is DVM Template": 12}
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, qt_app, qubes_app, dispatcher, parent=None):
|
def __init__(self, qt_app, qubes_app, dispatcher, parent=None):
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
@ -355,8 +363,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
QtCore.QRegExp("[a-zA-Z0-9_-]*", QtCore.Qt.CaseInsensitive), None))
|
QtCore.QRegExp("[a-zA-Z0-9_-]*", QtCore.Qt.CaseInsensitive), None))
|
||||||
self.searchContainer.addWidget(self.searchbox)
|
self.searchContainer.addWidget(self.searchbox)
|
||||||
|
|
||||||
self.connect(self.table, QtCore.SIGNAL("itemSelectionChanged()"),
|
self.table.itemSelectionChanged.connect(self.table_selection_changed)
|
||||||
self.table_selection_changed)
|
|
||||||
|
|
||||||
self.table.setColumnWidth(0, self.column_width)
|
self.table.setColumnWidth(0, self.column_width)
|
||||||
|
|
||||||
@ -393,12 +400,12 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
self.table.setColumnWidth(self.columns_indices["Label"], 40)
|
self.table.setColumnWidth(self.columns_indices["Label"], 40)
|
||||||
self.table.setColumnWidth(self.columns_indices["Type"], 40)
|
self.table.setColumnWidth(self.columns_indices["Type"], 40)
|
||||||
|
|
||||||
self.table.horizontalHeader().setResizeMode(
|
self.table.horizontalHeader().setSectionResizeMode(
|
||||||
QtGui.QHeaderView.Interactive)
|
QtWidgets.QHeaderView.Interactive)
|
||||||
self.table.horizontalHeader().setStretchLastSection(True)
|
self.table.horizontalHeader().setStretchLastSection(True)
|
||||||
self.table.horizontalHeader().setMinimumSectionSize(40)
|
self.table.horizontalHeader().setMinimumSectionSize(40)
|
||||||
|
|
||||||
self.context_menu = QtGui.QMenu(self)
|
self.context_menu = QtWidgets.QMenu(self)
|
||||||
|
|
||||||
self.context_menu.addAction(self.action_settings)
|
self.context_menu.addAction(self.action_settings)
|
||||||
self.context_menu.addAction(self.action_editfwrules)
|
self.context_menu.addAction(self.action_editfwrules)
|
||||||
@ -423,11 +430,11 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
self.context_menu.addMenu(self.logs_menu)
|
self.context_menu.addMenu(self.logs_menu)
|
||||||
self.context_menu.addSeparator()
|
self.context_menu.addSeparator()
|
||||||
|
|
||||||
self.tools_context_menu = QtGui.QMenu(self)
|
self.tools_context_menu = QtWidgets.QMenu(self)
|
||||||
self.tools_context_menu.addAction(self.action_toolbar)
|
self.tools_context_menu.addAction(self.action_toolbar)
|
||||||
self.tools_context_menu.addAction(self.action_menubar)
|
self.tools_context_menu.addAction(self.action_menubar)
|
||||||
|
|
||||||
self.dom0_context_menu = QtGui.QMenu(self)
|
self.dom0_context_menu = QtWidgets.QMenu(self)
|
||||||
self.dom0_context_menu.addAction(self.action_global_settings)
|
self.dom0_context_menu.addAction(self.action_global_settings)
|
||||||
self.dom0_context_menu.addAction(self.action_updatevm)
|
self.dom0_context_menu.addAction(self.action_updatevm)
|
||||||
self.dom0_context_menu.addSeparator()
|
self.dom0_context_menu.addSeparator()
|
||||||
@ -435,42 +442,29 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
self.dom0_context_menu.addMenu(self.logs_menu)
|
self.dom0_context_menu.addMenu(self.logs_menu)
|
||||||
self.dom0_context_menu.addSeparator()
|
self.dom0_context_menu.addSeparator()
|
||||||
|
|
||||||
self.connect(
|
self.table.horizontalHeader().sortIndicatorChanged.connect(
|
||||||
self.table.horizontalHeader(),
|
|
||||||
QtCore.SIGNAL("sortIndicatorChanged(int, Qt::SortOrder)"),
|
|
||||||
self.sort_indicator_changed)
|
self.sort_indicator_changed)
|
||||||
self.connect(self.table,
|
self.table.customContextMenuRequested.connect(self.open_context_menu)
|
||||||
QtCore.SIGNAL("customContextMenuRequested(const QPoint&)"),
|
self.menubar.customContextMenuRequested.connect(
|
||||||
self.open_context_menu)
|
lambda pos: self.open_tools_context_menu(self.menubar, pos))
|
||||||
self.connect(self.menubar,
|
self.toolbar.customContextMenuRequested.connect(
|
||||||
QtCore.SIGNAL("customContextMenuRequested(const QPoint&)"),
|
lambda pos: self.open_tools_context_menu(self.toolbar, pos))
|
||||||
lambda pos: self.open_tools_context_menu(self.menubar,
|
self.logs_menu.triggered.connect(self.show_log)
|
||||||
pos))
|
|
||||||
self.connect(self.toolbar,
|
|
||||||
QtCore.SIGNAL("customContextMenuRequested(const QPoint&)"),
|
|
||||||
lambda pos: self.open_tools_context_menu(self.toolbar,
|
|
||||||
pos))
|
|
||||||
self.connect(self.logs_menu, QtCore.SIGNAL("triggered(QAction *)"),
|
|
||||||
self.show_log)
|
|
||||||
|
|
||||||
self.connect(self.searchbox,
|
self.searchbox.textChanged.connect(self.do_search)
|
||||||
QtCore.SIGNAL("textChanged(const QString&)"),
|
|
||||||
self.do_search)
|
|
||||||
|
|
||||||
self.table.setContentsMargins(0, 0, 0, 0)
|
self.table.setContentsMargins(0, 0, 0, 0)
|
||||||
self.centralwidget.layout().setContentsMargins(0, 0, 0, 0)
|
self.centralwidget.layout().setContentsMargins(0, 0, 0, 0)
|
||||||
self.layout().setContentsMargins(0, 0, 0, 0)
|
self.layout().setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
self.connect(self.action_menubar, QtCore.SIGNAL("toggled(bool)"),
|
self.action_menubar.toggled.connect(self.showhide_menubar)
|
||||||
self.showhide_menubar)
|
self.action_toolbar.toggled.connect(self.showhide_toolbar)
|
||||||
self.connect(self.action_toolbar, QtCore.SIGNAL("toggled(bool)"),
|
|
||||||
self.showhide_toolbar)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.load_manager_settings()
|
self.load_manager_settings()
|
||||||
except Exception as ex: # pylint: disable=broad-except
|
except Exception as ex: # pylint: disable=broad-except
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
None,
|
self,
|
||||||
self.tr("Manager settings unreadable"),
|
self.tr("Manager settings unreadable"),
|
||||||
self.tr("Qube Manager settings cannot be parsed. Previously "
|
self.tr("Qube Manager settings cannot be parsed. Previously "
|
||||||
"saved display settings may not be restored "
|
"saved display settings may not be restored "
|
||||||
@ -517,6 +511,10 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
timer.start(1000 * 30) # 30s
|
timer.start(1000 * 30) # 30s
|
||||||
self.check_updates()
|
self.check_updates()
|
||||||
|
|
||||||
|
# select the first row of the table to make sure menu actions are
|
||||||
|
# correctly initialized
|
||||||
|
self.table.selectRow(0)
|
||||||
|
|
||||||
def keyPressEvent(self, event): # pylint: disable=invalid-name
|
def keyPressEvent(self, event): # pylint: disable=invalid-name
|
||||||
if event.key() == QtCore.Qt.Key_Escape:
|
if event.key() == QtCore.Qt.Key_Escape:
|
||||||
self.searchbox.clear()
|
self.searchbox.clear()
|
||||||
@ -532,13 +530,13 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
if thread.msg:
|
if thread.msg:
|
||||||
(title, msg) = thread.msg
|
(title, msg) = thread.msg
|
||||||
if thread.msg_is_success:
|
if thread.msg_is_success:
|
||||||
QtGui.QMessageBox.information(
|
QtWidgets.QMessageBox.information(
|
||||||
None,
|
self,
|
||||||
self.tr(title),
|
self.tr(title),
|
||||||
self.tr(msg))
|
self.tr(msg))
|
||||||
else:
|
else:
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
None,
|
self,
|
||||||
self.tr(title),
|
self.tr(title),
|
||||||
self.tr(msg))
|
self.tr(msg))
|
||||||
|
|
||||||
@ -663,7 +661,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
|
|
||||||
self.table.setRowCount(len(vms_list))
|
self.table.setRowCount(len(vms_list))
|
||||||
|
|
||||||
progress = QtGui.QProgressDialog(
|
progress = QtWidgets.QProgressDialog(
|
||||||
self.tr(
|
self.tr(
|
||||||
"Loading Qube Manager..."), "", 0, len(vms_list))
|
"Loading Qube Manager..."), "", 0, len(vms_list))
|
||||||
progress.setWindowTitle(self.tr("Qube Manager"))
|
progress.setWindowTitle(self.tr("Qube Manager"))
|
||||||
@ -806,7 +804,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
manager_utils.format_dependencies_list(dependencies) + \
|
manager_utils.format_dependencies_list(dependencies) + \
|
||||||
"<br>"
|
"<br>"
|
||||||
|
|
||||||
info_dialog = QtGui.QMessageBox(self)
|
info_dialog = QtWidgets.QMessageBox(self)
|
||||||
info_dialog.setWindowTitle(self.tr("Warning!"))
|
info_dialog.setWindowTitle(self.tr("Warning!"))
|
||||||
info_dialog.setText(
|
info_dialog.setText(
|
||||||
self.tr("This qube cannot be removed. It is used as:"
|
self.tr("This qube cannot be removed. It is used as:"
|
||||||
@ -818,8 +816,8 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
(requested_name, ok) = QtGui.QInputDialog.getText(
|
(requested_name, ok) = QtWidgets.QInputDialog.getText(
|
||||||
None, self.tr("Qube Removal Confirmation"),
|
self, self.tr("Qube Removal Confirmation"),
|
||||||
self.tr("Are you sure you want to remove the Qube <b>'{0}'</b>"
|
self.tr("Are you sure you want to remove the Qube <b>'{0}'</b>"
|
||||||
"?<br> All data on this Qube's private storage will be "
|
"?<br> All data on this Qube's private storage will be "
|
||||||
"lost!<br><br>Type the name of the Qube (<b>{1}</b>) below "
|
"lost!<br><br>Type the name of the Qube (<b>{1}</b>) below "
|
||||||
@ -831,8 +829,8 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
|
|
||||||
if requested_name != vm.name:
|
if requested_name != vm.name:
|
||||||
# name did not match
|
# name did not match
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
None,
|
self,
|
||||||
self.tr("Qube removal confirmation failed"),
|
self.tr("Qube removal confirmation failed"),
|
||||||
self.tr(
|
self.tr(
|
||||||
"Entered name did not match! Not removing "
|
"Entered name did not match! Not removing "
|
||||||
@ -856,7 +854,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
while name_format % name_number in self.qubes_app.domains.keys():
|
while name_format % name_number in self.qubes_app.domains.keys():
|
||||||
name_number += 1
|
name_number += 1
|
||||||
|
|
||||||
(clone_name, ok) = QtGui.QInputDialog.getText(
|
(clone_name, ok) = QtWidgets.QInputDialog.getText(
|
||||||
self, self.tr('Qubes clone Qube'),
|
self, self.tr('Qubes clone Qube'),
|
||||||
self.tr('Enter name for Qube <b>{}</b> clone:').format(vm.name),
|
self.tr('Enter name for Qube <b>{}</b> clone:').format(vm.name),
|
||||||
text=(name_format % name_number))
|
text=(name_format % name_number))
|
||||||
@ -866,13 +864,13 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
name_in_use = clone_name in self.qubes_app.domains
|
name_in_use = clone_name in self.qubes_app.domains
|
||||||
|
|
||||||
if name_in_use:
|
if name_in_use:
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
None, self.tr("Name already in use!"),
|
self, self.tr("Name already in use!"),
|
||||||
self.tr("There already exists a qube called '{}'. "
|
self.tr("There already exists a qube called '{}'. "
|
||||||
"Cloning aborted.").format(clone_name))
|
"Cloning aborted.").format(clone_name))
|
||||||
return
|
return
|
||||||
|
|
||||||
self.progress = QtGui.QProgressDialog(
|
self.progress = QtWidgets.QProgressDialog(
|
||||||
self.tr(
|
self.tr(
|
||||||
"Cloning Qube..."), "", 0, 0)
|
"Cloning Qube..."), "", 0, 0)
|
||||||
self.progress.setCancelButton(None)
|
self.progress.setCancelButton(None)
|
||||||
@ -894,8 +892,8 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
try:
|
try:
|
||||||
vm.unpause()
|
vm.unpause()
|
||||||
except exc.QubesException as ex:
|
except exc.QubesException as ex:
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
None, self.tr("Error unpausing Qube!"),
|
self, self.tr("Error unpausing Qube!"),
|
||||||
self.tr("ERROR: {0}").format(ex))
|
self.tr("ERROR: {0}").format(ex))
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -923,8 +921,8 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
try:
|
try:
|
||||||
vm.pause()
|
vm.pause()
|
||||||
except exc.QubesException as ex:
|
except exc.QubesException as ex:
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
None,
|
self,
|
||||||
self.tr("Error pausing Qube!"),
|
self.tr("Error pausing Qube!"),
|
||||||
self.tr("ERROR: {0}").format(ex))
|
self.tr("ERROR: {0}").format(ex))
|
||||||
return
|
return
|
||||||
@ -934,14 +932,15 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
def action_shutdownvm_triggered(self):
|
def action_shutdownvm_triggered(self):
|
||||||
vm = self.get_selected_vm()
|
vm = self.get_selected_vm()
|
||||||
|
|
||||||
reply = QtGui.QMessageBox.question(
|
reply = QtWidgets.QMessageBox.question(
|
||||||
None, self.tr("Qube Shutdown Confirmation"),
|
self, self.tr("Qube Shutdown Confirmation"),
|
||||||
self.tr("Are you sure you want to power down the Qube"
|
self.tr("Are you sure you want to power down the Qube"
|
||||||
" <b>'{0}'</b>?<br><small>This will shutdown all the "
|
" <b>'{0}'</b>?<br><small>This will shutdown all the "
|
||||||
"running applications within this Qube.</small>").format(
|
"running applications within this Qube.</small>").format(
|
||||||
vm.name), QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel)
|
vm.name),
|
||||||
|
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel)
|
||||||
|
|
||||||
if reply == QtGui.QMessageBox.Yes:
|
if reply == QtWidgets.QMessageBox.Yes:
|
||||||
self.shutdown_vm(vm)
|
self.shutdown_vm(vm)
|
||||||
|
|
||||||
def shutdown_vm(self, vm, shutdown_time=vm_shutdown_timeout,
|
def shutdown_vm(self, vm, shutdown_time=vm_shutdown_timeout,
|
||||||
@ -949,8 +948,8 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
try:
|
try:
|
||||||
vm.shutdown()
|
vm.shutdown()
|
||||||
except exc.QubesException as ex:
|
except exc.QubesException as ex:
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
None,
|
self,
|
||||||
self.tr("Error shutting down Qube!"),
|
self.tr("Error shutting down Qube!"),
|
||||||
self.tr("ERROR: {0}").format(ex))
|
self.tr("ERROR: {0}").format(ex))
|
||||||
return
|
return
|
||||||
@ -967,14 +966,14 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
def action_restartvm_triggered(self):
|
def action_restartvm_triggered(self):
|
||||||
vm = self.get_selected_vm()
|
vm = self.get_selected_vm()
|
||||||
|
|
||||||
reply = QtGui.QMessageBox.question(
|
reply = QtWidgets.QMessageBox.question(
|
||||||
None, self.tr("Qube Restart Confirmation"),
|
self, self.tr("Qube Restart Confirmation"),
|
||||||
self.tr("Are you sure you want to restart the Qube <b>'{0}'</b>?"
|
self.tr("Are you sure you want to restart the Qube <b>'{0}'</b>?"
|
||||||
"<br><small>This will shutdown all the running "
|
"<br><small>This will shutdown all the running "
|
||||||
"applications within this Qube.</small>").format(vm.name),
|
"applications within this Qube.</small>").format(vm.name),
|
||||||
QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel)
|
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel)
|
||||||
|
|
||||||
if reply == QtGui.QMessageBox.Yes:
|
if reply == QtWidgets.QMessageBox.Yes:
|
||||||
# in case the user shut down the VM in the meantime
|
# in case the user shut down the VM in the meantime
|
||||||
if vm.is_running():
|
if vm.is_running():
|
||||||
self.shutdown_vm(vm, and_restart=True)
|
self.shutdown_vm(vm, and_restart=True)
|
||||||
@ -997,17 +996,17 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
"shutdown!)</b> all the running applications within "
|
"shutdown!)</b> all the running applications within "
|
||||||
"this Qube.</small>").format(vm.name)
|
"this Qube.</small>").format(vm.name)
|
||||||
|
|
||||||
reply = QtGui.QMessageBox.question(
|
reply = QtWidgets.QMessageBox.question(
|
||||||
None, self.tr("Qube Kill Confirmation"), info,
|
self, self.tr("Qube Kill Confirmation"), info,
|
||||||
QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel,
|
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel,
|
||||||
QtGui.QMessageBox.Cancel)
|
QtWidgets.QMessageBox.Cancel)
|
||||||
|
|
||||||
if reply == QtGui.QMessageBox.Yes:
|
if reply == QtWidgets.QMessageBox.Yes:
|
||||||
try:
|
try:
|
||||||
vm.kill()
|
vm.kill()
|
||||||
except exc.QubesException as ex:
|
except exc.QubesException as ex:
|
||||||
QtGui.QMessageBox.critical(
|
QtWidgets.QMessageBox.critical(
|
||||||
None, self.tr("Error while killing Qube!"),
|
self, self.tr("Error while killing Qube!"),
|
||||||
self.tr(
|
self.tr(
|
||||||
"<b>An exception ocurred while killing {0}.</b><br>"
|
"<b>An exception ocurred while killing {0}.</b><br>"
|
||||||
"ERROR: {1}").format(vm.name, ex))
|
"ERROR: {1}").format(vm.name, ex))
|
||||||
@ -1057,13 +1056,13 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
vm = self.get_selected_vm()
|
vm = self.get_selected_vm()
|
||||||
|
|
||||||
if not vm.is_running():
|
if not vm.is_running():
|
||||||
reply = QtGui.QMessageBox.question(
|
reply = QtWidgets.QMessageBox.question(
|
||||||
None, self.tr("Qube Update Confirmation"),
|
self, self.tr("Qube Update Confirmation"),
|
||||||
self.tr(
|
self.tr(
|
||||||
"<b>{0}</b><br>The Qube has to be running to be updated."
|
"<b>{0}</b><br>The Qube has to be running to be updated."
|
||||||
"<br>Do you want to start it?<br>").format(vm.name),
|
"<br>Do you want to start it?<br>").format(vm.name),
|
||||||
QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel)
|
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel)
|
||||||
if reply != QtGui.QMessageBox.Yes:
|
if reply != QtWidgets.QMessageBox.Yes:
|
||||||
return
|
return
|
||||||
|
|
||||||
thread = UpdateVMThread(vm)
|
thread = UpdateVMThread(vm)
|
||||||
@ -1071,14 +1070,13 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
thread.finished.connect(self.clear_threads)
|
thread.finished.connect(self.clear_threads)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyArgumentList
|
# noinspection PyArgumentList
|
||||||
@QtCore.pyqtSlot(name='on_action_run_command_in_vm_triggered')
|
@QtCore.pyqtSlot(name='on_action_run_command_in_vm_triggered')
|
||||||
def action_run_command_in_vm_triggered(self):
|
def action_run_command_in_vm_triggered(self):
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
vm = self.get_selected_vm()
|
vm = self.get_selected_vm()
|
||||||
|
|
||||||
(command_to_run, ok) = QtGui.QInputDialog.getText(
|
(command_to_run, ok) = QtWidgets.QInputDialog.getText(
|
||||||
self, self.tr('Qubes command entry'),
|
self, self.tr('Qubes command entry'),
|
||||||
self.tr('Run command in <b>{}</b>:').format(vm.name))
|
self.tr('Run command in <b>{}</b>:').format(vm.name))
|
||||||
if not ok or command_to_run == "":
|
if not ok or command_to_run == "":
|
||||||
@ -1101,7 +1099,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
def action_editfwrules_triggered(self):
|
def action_editfwrules_triggered(self):
|
||||||
with common_threads.busy_cursor():
|
with common_threads.busy_cursor():
|
||||||
vm = self.get_selected_vm()
|
vm = self.get_selected_vm()
|
||||||
settings_window = settings.VMSettingsWindow(vm, self.qt_app,\
|
settings_window = settings.VMSettingsWindow(vm, self.qt_app,
|
||||||
"firewall")
|
"firewall")
|
||||||
settings_window.exec_()
|
settings_window.exec_()
|
||||||
|
|
||||||
@ -1132,7 +1130,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
@QtCore.pyqtSlot(name='on_action_restore_triggered')
|
@QtCore.pyqtSlot(name='on_action_restore_triggered')
|
||||||
def action_restore_triggered(self):
|
def action_restore_triggered(self):
|
||||||
with common_threads.busy_cursor():
|
with common_threads.busy_cursor():
|
||||||
restore_window = restore.RestoreVMsWindow(self.qt_app,\
|
restore_window = restore.RestoreVMsWindow(self.qt_app,
|
||||||
self.qubes_app)
|
self.qubes_app)
|
||||||
restore_window.exec_()
|
restore_window.exec_()
|
||||||
|
|
||||||
@ -1140,8 +1138,8 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
@QtCore.pyqtSlot(name='on_action_backup_triggered')
|
@QtCore.pyqtSlot(name='on_action_backup_triggered')
|
||||||
def action_backup_triggered(self):
|
def action_backup_triggered(self):
|
||||||
with common_threads.busy_cursor():
|
with common_threads.busy_cursor():
|
||||||
backup_window = backup.BackupVMsWindow(self.qt_app, self.qubes_app,
|
backup_window = backup.BackupVMsWindow(
|
||||||
self.dispatcher, self)
|
self.qt_app, self.qubes_app, self.dispatcher, self)
|
||||||
backup_window.show()
|
backup_window.show()
|
||||||
|
|
||||||
# noinspection PyArgumentList
|
# noinspection PyArgumentList
|
||||||
@ -1227,7 +1225,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow):
|
|||||||
about.exec_()
|
about.exec_()
|
||||||
|
|
||||||
def createPopupMenu(self): # pylint: disable=invalid-name
|
def createPopupMenu(self): # pylint: disable=invalid-name
|
||||||
menu = QtGui.QMenu()
|
menu = QtWidgets.QMenu()
|
||||||
menu.addAction(self.action_toolbar)
|
menu.addAction(self.action_toolbar)
|
||||||
menu.addAction(self.action_menubar)
|
menu.addAction(self.action_menubar)
|
||||||
return menu
|
return menu
|
||||||
@ -1302,9 +1300,9 @@ def handle_exception(exc_type, exc_value, exc_traceback):
|
|||||||
strace += "line no.: %d\n" % line
|
strace += "line no.: %d\n" % line
|
||||||
strace += "file: %s\n" % filename
|
strace += "file: %s\n" % filename
|
||||||
|
|
||||||
msg_box = QtGui.QMessageBox()
|
msg_box = QtWidgets.QMessageBox()
|
||||||
msg_box.setDetailedText(strace)
|
msg_box.setDetailedText(strace)
|
||||||
msg_box.setIcon(QtGui.QMessageBox.Critical)
|
msg_box.setIcon(QtWidgets.QMessageBox.Critical)
|
||||||
msg_box.setWindowTitle("Houston, we have a problem...")
|
msg_box.setWindowTitle("Houston, we have a problem...")
|
||||||
msg_box.setText("Whoops. A critical error has occured. "
|
msg_box.setText("Whoops. A critical error has occured. "
|
||||||
"This is most likely a bug in Qubes Manager.<br><br>"
|
"This is most likely a bug in Qubes Manager.<br><br>"
|
||||||
@ -1323,7 +1321,7 @@ def loop_shutdown():
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
qt_app = QtGui.QApplication(sys.argv)
|
qt_app = QtWidgets.QApplication(sys.argv)
|
||||||
qt_app.setOrganizationName("The Qubes Project")
|
qt_app.setOrganizationName("The Qubes Project")
|
||||||
qt_app.setOrganizationDomain("http://qubes-os.org")
|
qt_app.setOrganizationDomain("http://qubes-os.org")
|
||||||
qt_app.setApplicationName("Qube Manager")
|
qt_app.setApplicationName("Qube Manager")
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
# with this program; if not, see <http://www.gnu.org/licenses/>.
|
# with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
from PyQt4.QtGui import QDialog # pylint: disable=import-error
|
from PyQt5.QtWidgets import QDialog # pylint: disable=import-error
|
||||||
|
|
||||||
from . import ui_releasenotes # pylint: disable=no-name-in-module
|
from . import ui_releasenotes # pylint: disable=no-name-in-module
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/python2
|
#!/usr/bin/python3
|
||||||
#
|
#
|
||||||
# The Qubes OS Project, http://www.qubes-os.org
|
# The Qubes OS Project, http://www.qubes-os.org
|
||||||
#
|
#
|
||||||
@ -21,8 +21,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from PyQt4 import QtCore # pylint: disable=import-error
|
from PyQt5 import QtCore, QtWidgets # pylint: disable=import-error
|
||||||
from PyQt4 import QtGui # pylint: disable=import-error
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import traceback
|
import traceback
|
||||||
@ -36,7 +35,7 @@ from . import multiselectwidget
|
|||||||
from . import backup_utils
|
from . import backup_utils
|
||||||
|
|
||||||
from multiprocessing import Queue
|
from multiprocessing import Queue
|
||||||
from multiprocessing.queues import Empty
|
from queue import Empty
|
||||||
from qubesadmin import Qubes, exc
|
from qubesadmin import Qubes, exc
|
||||||
from qubesadmin.backup import restore
|
from qubesadmin.backup import restore
|
||||||
|
|
||||||
@ -72,7 +71,7 @@ class RestoreThread(QtCore.QThread):
|
|||||||
self.tr("Finished successfully!"))
|
self.tr("Finished successfully!"))
|
||||||
|
|
||||||
|
|
||||||
class RestoreVMsWindow(ui_restoredlg.Ui_Restore, QtGui.QWizard):
|
class RestoreVMsWindow(ui_restoredlg.Ui_Restore, QtWidgets.QWizard):
|
||||||
def __init__(self, qt_app, qubes_app, parent=None):
|
def __init__(self, qt_app, qubes_app, parent=None):
|
||||||
super(RestoreVMsWindow, self).__init__(parent)
|
super(RestoreVMsWindow, self).__init__(parent)
|
||||||
|
|
||||||
@ -101,22 +100,16 @@ class RestoreVMsWindow(ui_restoredlg.Ui_Restore, QtGui.QWizard):
|
|||||||
self.select_vms_widget = multiselectwidget.MultiSelectWidget(self)
|
self.select_vms_widget = multiselectwidget.MultiSelectWidget(self)
|
||||||
self.select_vms_layout.insertWidget(1, self.select_vms_widget)
|
self.select_vms_layout.insertWidget(1, self.select_vms_widget)
|
||||||
|
|
||||||
self.connect(self,
|
self.currentIdChanged.connect(self.current_page_changed)
|
||||||
QtCore.SIGNAL("currentIdChanged(int)"),
|
self.dir_line_edit.textChanged.connect(self.backup_location_changed)
|
||||||
self.current_page_changed)
|
|
||||||
self.dir_line_edit.connect(self.dir_line_edit,
|
|
||||||
QtCore.SIGNAL("textChanged(QString)"),
|
|
||||||
self.backup_location_changed)
|
|
||||||
|
|
||||||
self.select_dir_page.isComplete = self.has_selected_dir
|
self.select_dir_page.isComplete = self.has_selected_dir
|
||||||
self.select_vms_page.isComplete = self.has_selected_vms
|
self.select_vms_page.isComplete = self.has_selected_vms
|
||||||
self.confirm_page.isComplete = self.all_vms_good
|
self.confirm_page.isComplete = self.all_vms_good
|
||||||
# FIXME
|
# FIXME
|
||||||
# this causes to run isComplete() twice, I don't know why
|
# this causes to run isComplete() twice, I don't know why
|
||||||
self.select_vms_page.connect(
|
self.select_vms_widget.selectedChanged.connect(
|
||||||
self.select_vms_widget,
|
self.select_vms_page.completeChanged.emit)
|
||||||
QtCore.SIGNAL("selected_changed()"),
|
|
||||||
QtCore.SIGNAL("completeChanged()"))
|
|
||||||
|
|
||||||
backup_utils.fill_appvms_list(self)
|
backup_utils.fill_appvms_list(self)
|
||||||
|
|
||||||
@ -169,7 +162,8 @@ class RestoreVMsWindow(ui_restoredlg.Ui_Restore, QtGui.QWizard):
|
|||||||
continue
|
continue
|
||||||
self.select_vms_widget.available_list.addItem(vmname)
|
self.select_vms_widget.available_list.addItem(vmname)
|
||||||
except exc.QubesException as ex:
|
except exc.QubesException as ex:
|
||||||
QtGui.QMessageBox.warning(None, self.tr("Restore error!"), str(ex))
|
QtWidgets.QMessageBox.warning(
|
||||||
|
self, self.tr("Restore error!"), str(ex))
|
||||||
self.restart()
|
self.restart()
|
||||||
|
|
||||||
def append_output(self, text):
|
def append_output(self, text):
|
||||||
@ -201,7 +195,7 @@ class RestoreVMsWindow(ui_restoredlg.Ui_Restore, QtGui.QWizard):
|
|||||||
self.confirm_text_edit.setFontFamily("Monospace")
|
self.confirm_text_edit.setFontFamily("Monospace")
|
||||||
self.confirm_text_edit.setText(self.func_output)
|
self.confirm_text_edit.setText(self.func_output)
|
||||||
|
|
||||||
self.confirm_page.emit(QtCore.SIGNAL("completeChanged()"))
|
self.confirm_page.completeChanged.emit()
|
||||||
|
|
||||||
elif self.currentPage() is self.commit_page:
|
elif self.currentPage() is self.commit_page:
|
||||||
self.button(self.FinishButton).setDisabled(True)
|
self.button(self.FinishButton).setDisabled(True)
|
||||||
@ -226,8 +220,8 @@ class RestoreVMsWindow(ui_restoredlg.Ui_Restore, QtGui.QWizard):
|
|||||||
self.progress_bar.setValue(100)
|
self.progress_bar.setValue(100)
|
||||||
|
|
||||||
if self.thread.msg:
|
if self.thread.msg:
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
None,
|
self,
|
||||||
self.tr("Restore qubes"),
|
self.tr("Restore qubes"),
|
||||||
self.tr(self.thread.msg))
|
self.tr(self.thread.msg))
|
||||||
|
|
||||||
@ -260,7 +254,6 @@ class RestoreVMsWindow(ui_restoredlg.Ui_Restore, QtGui.QWizard):
|
|||||||
except Empty:
|
except Empty:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def all_vms_good(self):
|
def all_vms_good(self):
|
||||||
for vm_info in self.vms_to_restore.values():
|
for vm_info in self.vms_to_restore.values():
|
||||||
if not vm_info.vm:
|
if not vm_info.vm:
|
||||||
@ -296,7 +289,7 @@ class RestoreVMsWindow(ui_restoredlg.Ui_Restore, QtGui.QWizard):
|
|||||||
|
|
||||||
def backup_location_changed(self, new_dir=None):
|
def backup_location_changed(self, new_dir=None):
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
self.select_dir_page.emit(QtCore.SIGNAL("completeChanged()"))
|
self.select_dir_page.completeChanged.emit()
|
||||||
|
|
||||||
|
|
||||||
# Bases on the original code by:
|
# Bases on the original code by:
|
||||||
@ -308,18 +301,16 @@ def handle_exception(exc_type, exc_value, exc_traceback):
|
|||||||
filename = os.path.basename(filename)
|
filename = os.path.basename(filename)
|
||||||
error = "%s: %s" % (exc_type.__name__, exc_value)
|
error = "%s: %s" % (exc_type.__name__, exc_value)
|
||||||
|
|
||||||
QtGui.QMessageBox.critical(None, "Houston, we have a problem...",
|
QtWidgets.QMessageBox.critical(
|
||||||
"Whoops. A critical error has occured. "
|
None, "Houston, we have a problem...",
|
||||||
"This is most likely a bug "
|
"Whoops. A critical error has occured. This is most likely a bug "
|
||||||
"in Qubes Restore VMs application.<br><br>"
|
"in Qubes Restore VMs application.<br><br><b><i>%s</i></b>" % error +
|
||||||
"<b><i>%s</i></b>" % error +
|
"at <b>line %d</b> of file <b>%s</b>.<br/><br/>" % (line, filename))
|
||||||
"at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
|
|
||||||
% (line, filename))
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
qt_app = QtGui.QApplication(sys.argv)
|
qt_app = QtWidgets.QApplication(sys.argv)
|
||||||
qt_app.setOrganizationName("The Qubes Project")
|
qt_app.setOrganizationName("The Qubes Project")
|
||||||
qt_app.setOrganizationDomain("http://qubes-os.org")
|
qt_app.setOrganizationDomain("http://qubes-os.org")
|
||||||
qt_app.setApplicationName("Qubes Restore VMs")
|
qt_app.setApplicationName("Qubes Restore VMs")
|
||||||
|
@ -41,10 +41,11 @@ from . import device_list
|
|||||||
|
|
||||||
from .appmenu_select import AppmenuSelectManager
|
from .appmenu_select import AppmenuSelectManager
|
||||||
from . import firewall
|
from . import firewall
|
||||||
from PyQt4 import QtCore, QtGui # pylint: disable=import-error
|
from PyQt5 import QtCore, QtWidgets, QtGui # pylint: disable=import-error
|
||||||
|
|
||||||
from . import ui_settingsdlg # pylint: disable=no-name-in-module
|
from . import ui_settingsdlg # pylint: disable=no-name-in-module
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
class RenameVMThread(QtCore.QThread):
|
class RenameVMThread(QtCore.QThread):
|
||||||
def __init__(self, vm, new_vm_name, dependencies):
|
def __init__(self, vm, new_vm_name, dependencies):
|
||||||
@ -121,7 +122,7 @@ class RefreshAppsVMThread(QtCore.QThread):
|
|||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-many-instance-attributes
|
# pylint: disable=too-many-instance-attributes
|
||||||
class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
|
||||||
tabs_indices = collections.OrderedDict((
|
tabs_indices = collections.OrderedDict((
|
||||||
('basic', 0),
|
('basic', 0),
|
||||||
('advanced', 1),
|
('advanced', 1),
|
||||||
@ -151,7 +152,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
assert idx in range(self.tabWidget.count())
|
assert idx in range(self.tabWidget.count())
|
||||||
self.tabWidget.setCurrentIndex(idx)
|
self.tabWidget.setCurrentIndex(idx)
|
||||||
|
|
||||||
self.buttonBox.button(QtGui.QDialogButtonBox.Apply).clicked.connect(
|
self.buttonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(
|
||||||
self.apply)
|
self.apply)
|
||||||
|
|
||||||
self.tabWidget.currentChanged.connect(self.current_tab_changed)
|
self.tabWidget.currentChanged.connect(self.current_tab_changed)
|
||||||
@ -177,12 +178,8 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
self.__init_advanced_tab__()
|
self.__init_advanced_tab__()
|
||||||
self.include_in_balancing.stateChanged.connect(
|
self.include_in_balancing.stateChanged.connect(
|
||||||
self.include_in_balancing_changed)
|
self.include_in_balancing_changed)
|
||||||
self.connect(self.init_mem,
|
self.init_mem.editingFinished.connect(self.check_mem_changes)
|
||||||
QtCore.SIGNAL("editingFinished()"),
|
self.max_mem_size.editingFinished.connect(self.check_mem_changes)
|
||||||
self.check_mem_changes)
|
|
||||||
self.connect(self.max_mem_size,
|
|
||||||
QtCore.SIGNAL("editingFinished()"),
|
|
||||||
self.check_mem_changes)
|
|
||||||
self.boot_from_device_button.clicked.connect(
|
self.boot_from_device_button.clicked.connect(
|
||||||
self.boot_from_cdrom_button_pressed)
|
self.boot_from_cdrom_button_pressed)
|
||||||
|
|
||||||
@ -207,9 +204,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
|
|
||||||
####### devices tab
|
####### devices tab
|
||||||
self.__init_devices_tab__()
|
self.__init_devices_tab__()
|
||||||
self.connect(self.dev_list,
|
self.dev_list.selectedChanged.connect(self.devices_selection_changed)
|
||||||
QtCore.SIGNAL("selected_changed()"),
|
|
||||||
self.devices_selection_changed)
|
|
||||||
self.no_strict_reset_button.clicked.connect(
|
self.no_strict_reset_button.clicked.connect(
|
||||||
self.strict_reset_button_pressed)
|
self.strict_reset_button_pressed)
|
||||||
self.current_strict_reset_list = []
|
self.current_strict_reset_list = []
|
||||||
@ -240,8 +235,8 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
|
|
||||||
if thread.msg:
|
if thread.msg:
|
||||||
(title, msg) = thread.msg
|
(title, msg) = thread.msg
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
None,
|
self,
|
||||||
self.tr(title),
|
self.tr(title),
|
||||||
self.tr(msg))
|
self.tr(msg))
|
||||||
|
|
||||||
@ -268,10 +263,10 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
error = self.__save_changes__()
|
error = self.__save_changes__()
|
||||||
|
|
||||||
if error:
|
if error:
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
self,
|
self,
|
||||||
self.tr("Error while changing settings for {0}!"\
|
self.tr("Error while changing settings for {0}!"
|
||||||
).format(self.vm.name),\
|
).format(self.vm.name),
|
||||||
self.tr("ERROR: {0}").format('\n'.join(error)))
|
self.tr("ERROR: {0}").format('\n'.join(error)))
|
||||||
|
|
||||||
def apply(self):
|
def apply(self):
|
||||||
@ -331,7 +326,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
netvm is not None and
|
netvm is not None and
|
||||||
not netvm.features.check_with_template('qubes-firewall', False))
|
not netvm.features.check_with_template('qubes-firewall', False))
|
||||||
if netvm is None:
|
if netvm is None:
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
self,
|
self,
|
||||||
self.tr("Qube configuration problem!"),
|
self.tr("Qube configuration problem!"),
|
||||||
self.tr('This qube has networking disabled '
|
self.tr('This qube has networking disabled '
|
||||||
@ -340,16 +335,16 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
'please enable networking.')
|
'please enable networking.')
|
||||||
)
|
)
|
||||||
if netvm is not None and \
|
if netvm is not None and \
|
||||||
not netvm.features.check_with_template(\
|
not netvm.features.check_with_template(
|
||||||
'qubes-firewall', False):
|
'qubes-firewall', False):
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
self,
|
self,
|
||||||
self.tr("Qube configuration problem!"),
|
self.tr("Qube configuration problem!"),
|
||||||
self.tr("The '{vm}' qube is network connected to "\
|
self.tr("The '{vm}' qube is network connected to "
|
||||||
"'{netvm}', which does not support firewall!<br/>"\
|
"'{netvm}', which does not support firewall!<br/>"
|
||||||
"You may edit the '{vm}' qube firewall rules, but "\
|
"You may edit the '{vm}' qube firewall rules, but "
|
||||||
"these will not take any effect until you connect it "\
|
"these will not take any effect until you connect it "
|
||||||
"to a working Firewall qube.").format(\
|
"to a working Firewall qube.").format(
|
||||||
vm=self.vm.name, netvm=netvm.name))
|
vm=self.vm.name, netvm=netvm.name))
|
||||||
|
|
||||||
def current_tab_changed(self, idx):
|
def current_tab_changed(self, idx):
|
||||||
@ -536,7 +531,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
|
|
||||||
def check_mem_changes(self):
|
def check_mem_changes(self):
|
||||||
if self.max_mem_size.value() < self.init_mem.value():
|
if self.max_mem_size.value() < self.init_mem.value():
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
self,
|
self,
|
||||||
self.tr("Warning!"),
|
self.tr("Warning!"),
|
||||||
self.tr("Max memory can not be less than initial memory.<br>"
|
self.tr("Max memory can not be less than initial memory.<br>"
|
||||||
@ -546,7 +541,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
# max_mem_size/10.79 in order to allow scaling up to
|
# max_mem_size/10.79 in order to allow scaling up to
|
||||||
# max_mem_size (or else "add_memory() failed: -17" problem)
|
# max_mem_size (or else "add_memory() failed: -17" problem)
|
||||||
if self.init_mem.value() * 10 < self.max_mem_size.value():
|
if self.init_mem.value() * 10 < self.max_mem_size.value():
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
self,
|
self,
|
||||||
self.tr("Warning!"),
|
self.tr("Warning!"),
|
||||||
self.tr("Initial memory can not be less than one tenth "
|
self.tr("Initial memory can not be less than one tenth "
|
||||||
@ -579,7 +574,6 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
else:
|
else:
|
||||||
self.warn_netvm_dispvm.setVisible(False)
|
self.warn_netvm_dispvm.setVisible(False)
|
||||||
|
|
||||||
|
|
||||||
def rename_vm(self):
|
def rename_vm(self):
|
||||||
|
|
||||||
dependencies = admin_utils.vm_dependencies(self.vm.app, self.vm)
|
dependencies = admin_utils.vm_dependencies(self.vm.app, self.vm)
|
||||||
@ -589,7 +583,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
and vm.is_running()]
|
and vm.is_running()]
|
||||||
|
|
||||||
if running_dependencies:
|
if running_dependencies:
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
self,
|
self,
|
||||||
self.tr("Qube cannot be renamed!"),
|
self.tr("Qube cannot be renamed!"),
|
||||||
self.tr(
|
self.tr(
|
||||||
@ -599,7 +593,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
", ".join(running_dependencies)))
|
", ".join(running_dependencies)))
|
||||||
return
|
return
|
||||||
|
|
||||||
new_vm_name, ok = QtGui.QInputDialog.getText(
|
new_vm_name, ok = QtWidgets.QInputDialog.getText(
|
||||||
self,
|
self,
|
||||||
self.tr('Rename qube'),
|
self.tr('Rename qube'),
|
||||||
self.tr('New name: (WARNING: all other changes will be discarded)'))
|
self.tr('New name: (WARNING: all other changes will be discarded)'))
|
||||||
@ -609,7 +603,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
self.threads_list.append(thread)
|
self.threads_list.append(thread)
|
||||||
thread.finished.connect(self.clear_threads)
|
thread.finished.connect(self.clear_threads)
|
||||||
|
|
||||||
self.progress = QtGui.QProgressDialog(
|
self.progress = QtWidgets.QProgressDialog(
|
||||||
self.tr(
|
self.tr(
|
||||||
"Renaming Qube..."), "", 0, 0)
|
"Renaming Qube..."), "", 0, 0)
|
||||||
self.progress.setCancelButton(None)
|
self.progress.setCancelButton(None)
|
||||||
@ -625,7 +619,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
|
|
||||||
if dependencies:
|
if dependencies:
|
||||||
list_text = utils.format_dependencies_list(dependencies)
|
list_text = utils.format_dependencies_list(dependencies)
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
self,
|
self,
|
||||||
self.tr("Qube cannot be removed!"),
|
self.tr("Qube cannot be removed!"),
|
||||||
self.tr("This qube cannot be removed. It is used as:"
|
self.tr("This qube cannot be removed. It is used as:"
|
||||||
@ -635,8 +629,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
answer, ok = QtWidgets.QInputDialog.getText(
|
||||||
answer, ok = QtGui.QInputDialog.getText(
|
|
||||||
self,
|
self,
|
||||||
self.tr('Delete qube'),
|
self.tr('Delete qube'),
|
||||||
self.tr('Are you absolutely sure you want to delete this qube? '
|
self.tr('Are you absolutely sure you want to delete this qube? '
|
||||||
@ -650,14 +643,14 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
self.done(0)
|
self.done(0)
|
||||||
|
|
||||||
elif ok:
|
elif ok:
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
self,
|
self,
|
||||||
self.tr("Removal cancelled"),
|
self.tr("Removal cancelled"),
|
||||||
self.tr("The qube will not be removed."))
|
self.tr("The qube will not be removed."))
|
||||||
|
|
||||||
def clone_vm(self):
|
def clone_vm(self):
|
||||||
|
|
||||||
cloned_vm_name, ok = QtGui.QInputDialog.getText(
|
cloned_vm_name, ok = QtWidgets.QInputDialog.getText(
|
||||||
self,
|
self,
|
||||||
self.tr('Clone qube'),
|
self.tr('Clone qube'),
|
||||||
self.tr('Name for the cloned qube:'))
|
self.tr('Name for the cloned qube:'))
|
||||||
@ -667,7 +660,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
thread.finished.connect(self.clear_threads)
|
thread.finished.connect(self.clear_threads)
|
||||||
self.threads_list.append(thread)
|
self.threads_list.append(thread)
|
||||||
|
|
||||||
self.progress = QtGui.QProgressDialog(
|
self.progress = QtWidgets.QProgressDialog(
|
||||||
self.tr(
|
self.tr(
|
||||||
"Cloning Qube..."), "", 0, 0)
|
"Cloning Qube..."), "", 0, 0)
|
||||||
self.progress.setCancelButton(None)
|
self.progress.setCancelButton(None)
|
||||||
@ -867,8 +860,8 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
|
|
||||||
self.virt_mode.clear()
|
self.virt_mode.clear()
|
||||||
|
|
||||||
self.virt_mode_list, self.virt_mode_idx = utils.prepare_choice(\
|
self.virt_mode_list, self.virt_mode_idx = utils.prepare_choice(
|
||||||
self.virt_mode, self.vm, 'virt_mode', choices, None,\
|
self.virt_mode, self.vm, 'virt_mode', choices, None,
|
||||||
allow_default=True, transform=(lambda x: str(x).upper()))
|
allow_default=True, transform=(lambda x: str(x).upper()))
|
||||||
|
|
||||||
if old_mode is not None:
|
if old_mode is not None:
|
||||||
@ -924,7 +917,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
attached_devs = list(self.vm.devices['pci'].persistent())
|
attached_devs = list(self.vm.devices['pci'].persistent())
|
||||||
|
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
class DevListWidgetItem(QtGui.QListWidgetItem):
|
class DevListWidgetItem(QtWidgets.QListWidgetItem):
|
||||||
def __init__(self, dev, unknown=False, parent=None):
|
def __init__(self, dev, unknown=False, parent=None):
|
||||||
super(DevListWidgetItem, self).__init__(parent)
|
super(DevListWidgetItem, self).__init__(parent)
|
||||||
name = dev.ident.replace('_', ":") + ' ' + dev.description
|
name = dev.ident.replace('_', ":") + ' ' + dev.description
|
||||||
@ -1070,7 +1063,7 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
if not feature.startswith('service.'):
|
if not feature.startswith('service.'):
|
||||||
continue
|
continue
|
||||||
service = feature[len('service.'):]
|
service = feature[len('service.'):]
|
||||||
item = QtGui.QListWidgetItem(service)
|
item = QtWidgets.QListWidgetItem(service)
|
||||||
item.setCheckState(ui_settingsdlg.QtCore.Qt.Checked
|
item.setCheckState(ui_settingsdlg.QtCore.Qt.Checked
|
||||||
if self.vm.features[feature]
|
if self.vm.features[feature]
|
||||||
else ui_settingsdlg.QtCore.Qt.Unchecked)
|
else ui_settingsdlg.QtCore.Qt.Unchecked)
|
||||||
@ -1097,12 +1090,12 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
srv = str(self.service_line_edit.currentText()).strip()
|
srv = str(self.service_line_edit.currentText()).strip()
|
||||||
if srv != "":
|
if srv != "":
|
||||||
if srv in self.new_srv_dict:
|
if srv in self.new_srv_dict:
|
||||||
QtGui.QMessageBox.information(
|
QtWidgets.QMessageBox.information(
|
||||||
self,
|
self,
|
||||||
'',
|
'',
|
||||||
self.tr('Service already on the list!'))
|
self.tr('Service already on the list!'))
|
||||||
else:
|
else:
|
||||||
item = QtGui.QListWidgetItem(srv)
|
item = QtWidgets.QListWidgetItem(srv)
|
||||||
item.setCheckState(ui_settingsdlg.QtCore.Qt.Checked)
|
item.setCheckState(ui_settingsdlg.QtCore.Qt.Checked)
|
||||||
self.services_list.addItem(item)
|
self.services_list.addItem(item)
|
||||||
self.new_srv_dict[srv] = True
|
self.new_srv_dict[srv] = True
|
||||||
@ -1146,9 +1139,10 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtGui.QDialog):
|
|||||||
def set_fw_model(self, model):
|
def set_fw_model(self, model):
|
||||||
self.fw_model = model
|
self.fw_model = model
|
||||||
self.rulesTreeView.setModel(model)
|
self.rulesTreeView.setModel(model)
|
||||||
self.rulesTreeView.header().setResizeMode(
|
self.rulesTreeView.header().setSectionResizeMode(
|
||||||
QtGui.QHeaderView.ResizeToContents)
|
QtWidgets.QHeaderView.ResizeToContents)
|
||||||
self.rulesTreeView.header().setResizeMode(0, QtGui.QHeaderView.Stretch)
|
self.rulesTreeView.header().setSectionResizeMode(
|
||||||
|
0, QtWidgets.QHeaderView.Stretch)
|
||||||
self.set_allow(model.allow)
|
self.set_allow(model.allow)
|
||||||
if model.temp_full_access_expire_time:
|
if model.temp_full_access_expire_time:
|
||||||
self.temp_full_access.setChecked(True)
|
self.temp_full_access.setChecked(True)
|
||||||
@ -1226,9 +1220,9 @@ def handle_exception(exc_type, exc_value, exc_traceback):
|
|||||||
strace += "line no.: %d\n" % line
|
strace += "line no.: %d\n" % line
|
||||||
strace += "file: %s\n" % filename
|
strace += "file: %s\n" % filename
|
||||||
|
|
||||||
msg_box = QtGui.QMessageBox()
|
msg_box = QtWidgets.QMessageBox()
|
||||||
msg_box.setDetailedText(strace)
|
msg_box.setDetailedText(strace)
|
||||||
msg_box.setIcon(QtGui.QMessageBox.Critical)
|
msg_box.setIcon(QtWidgets.QMessageBox.Critical)
|
||||||
msg_box.setWindowTitle("Houston, we have a problem...")
|
msg_box.setWindowTitle("Houston, we have a problem...")
|
||||||
msg_box.setText("Whoops. A critical error has occured. "
|
msg_box.setText("Whoops. A critical error has occured. "
|
||||||
"This is most likely a bug in Qubes Manager.<br><br>"
|
"This is most likely a bug in Qubes Manager.<br><br>"
|
||||||
@ -1254,7 +1248,7 @@ def main(args=None):
|
|||||||
args = parser.parse_args(args)
|
args = parser.parse_args(args)
|
||||||
vm = args.domains.pop()
|
vm = args.domains.pop()
|
||||||
|
|
||||||
qapp = QtGui.QApplication(sys.argv)
|
qapp = QtWidgets.QApplication(sys.argv)
|
||||||
qapp.setOrganizationName('Invisible Things Lab')
|
qapp.setOrganizationName('Invisible Things Lab')
|
||||||
qapp.setOrganizationDomain("https://www.qubes-os.org/")
|
qapp.setOrganizationDomain("https://www.qubes-os.org/")
|
||||||
qapp.setApplicationName("Qube Settings")
|
qapp.setApplicationName("Qube Settings")
|
||||||
|
@ -20,8 +20,7 @@
|
|||||||
# with this program; if not, see <http://www.gnu.org/licenses/>.
|
# with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from PyQt4 import QtGui # pylint: disable=import-error
|
from PyQt5 import QtWidgets, QtCore, QtGui # pylint: disable=import-error
|
||||||
from PyQt4 import QtCore # pylint: disable=import-error
|
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
|
|
||||||
power_order = QtCore.Qt.DescendingOrder
|
power_order = QtCore.Qt.DescendingOrder
|
||||||
@ -31,7 +30,7 @@ update_order = QtCore.Qt.AscendingOrder
|
|||||||
row_height = 30
|
row_height = 30
|
||||||
|
|
||||||
|
|
||||||
class VmIconWidget(QtGui.QWidget):
|
class VmIconWidget(QtWidgets.QWidget):
|
||||||
def __init__(self, icon_path, enabled=True, size_multiplier=0.7,
|
def __init__(self, icon_path, enabled=True, size_multiplier=0.7,
|
||||||
tooltip=None, parent=None,
|
tooltip=None, parent=None,
|
||||||
icon_sz=(32, 32)): # pylint: disable=unused-argument
|
icon_sz=(32, 32)): # pylint: disable=unused-argument
|
||||||
@ -39,13 +38,13 @@ class VmIconWidget(QtGui.QWidget):
|
|||||||
|
|
||||||
self.enabled = enabled
|
self.enabled = enabled
|
||||||
self.size_multiplier = size_multiplier
|
self.size_multiplier = size_multiplier
|
||||||
self.label_icon = QtGui.QLabel()
|
self.label_icon = QtWidgets.QLabel()
|
||||||
self.set_icon(icon_path)
|
self.set_icon(icon_path)
|
||||||
|
|
||||||
if tooltip is not None:
|
if tooltip is not None:
|
||||||
self.label_icon.setToolTip(tooltip)
|
self.label_icon.setToolTip(tooltip)
|
||||||
|
|
||||||
layout = QtGui.QHBoxLayout()
|
layout = QtWidgets.QHBoxLayout()
|
||||||
layout.addWidget(self.label_icon)
|
layout.addWidget(self.label_icon)
|
||||||
layout.setContentsMargins(0, 0, 0, 0)
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
@ -72,7 +71,7 @@ class VmIconWidget(QtGui.QWidget):
|
|||||||
|
|
||||||
|
|
||||||
class VmTypeWidget(VmIconWidget):
|
class VmTypeWidget(VmIconWidget):
|
||||||
class VmTypeItem(QtGui.QTableWidgetItem):
|
class VmTypeItem(QtWidgets.QTableWidgetItem):
|
||||||
def __init__(self, value, vm):
|
def __init__(self, value, vm):
|
||||||
super(VmTypeWidget.VmTypeItem, self).__init__()
|
super(VmTypeWidget.VmTypeItem, self).__init__()
|
||||||
self.value = value
|
self.value = value
|
||||||
@ -120,7 +119,7 @@ class VmTypeWidget(VmIconWidget):
|
|||||||
|
|
||||||
|
|
||||||
class VmLabelWidget(VmIconWidget):
|
class VmLabelWidget(VmIconWidget):
|
||||||
class VmLabelItem(QtGui.QTableWidgetItem):
|
class VmLabelItem(QtWidgets.QTableWidgetItem):
|
||||||
def __init__(self, value, vm):
|
def __init__(self, value, vm):
|
||||||
super(VmLabelWidget.VmLabelItem, self).__init__()
|
super(VmLabelWidget.VmLabelItem, self).__init__()
|
||||||
self.value = value
|
self.value = value
|
||||||
@ -159,10 +158,11 @@ class VmLabelWidget(VmIconWidget):
|
|||||||
self.set_icon(icon_path)
|
self.set_icon(icon_path)
|
||||||
|
|
||||||
|
|
||||||
class VmStatusIcon(QtGui.QLabel):
|
class VmStatusIcon(QtWidgets.QLabel):
|
||||||
def __init__(self, vm, parent=None):
|
def __init__(self, vm, parent=None):
|
||||||
super(VmStatusIcon, self).__init__(parent)
|
super(VmStatusIcon, self).__init__(parent)
|
||||||
self.vm = vm
|
self.vm = vm
|
||||||
|
self.status = None
|
||||||
self.set_on_icon()
|
self.set_on_icon()
|
||||||
self.previous_power_state = self.vm.get_power_state()
|
self.previous_power_state = self.vm.get_power_state()
|
||||||
|
|
||||||
@ -191,8 +191,8 @@ class VmStatusIcon(QtGui.QLabel):
|
|||||||
self.setFixedSize(icon_sz)
|
self.setFixedSize(icon_sz)
|
||||||
|
|
||||||
|
|
||||||
class VmInfoWidget(QtGui.QWidget):
|
class VmInfoWidget(QtWidgets.QWidget):
|
||||||
class VmInfoItem(QtGui.QTableWidgetItem):
|
class VmInfoItem(QtWidgets.QTableWidgetItem):
|
||||||
def __init__(self, on_icon, upd_info_item, vm):
|
def __init__(self, on_icon, upd_info_item, vm):
|
||||||
super(VmInfoWidget.VmInfoItem, self).__init__()
|
super(VmInfoWidget.VmInfoItem, self).__init__()
|
||||||
self.on_icon = on_icon
|
self.on_icon = on_icon
|
||||||
@ -232,7 +232,7 @@ class VmInfoWidget(QtGui.QWidget):
|
|||||||
def __init__(self, vm, parent=None):
|
def __init__(self, vm, parent=None):
|
||||||
super(VmInfoWidget, self).__init__(parent)
|
super(VmInfoWidget, self).__init__(parent)
|
||||||
self.vm = vm
|
self.vm = vm
|
||||||
layout = QtGui.QHBoxLayout()
|
layout = QtWidgets.QHBoxLayout()
|
||||||
|
|
||||||
self.on_icon = VmStatusIcon(vm)
|
self.on_icon = VmStatusIcon(vm)
|
||||||
self.upd_info = VmUpdateInfoWidget(vm, show_text=False)
|
self.upd_info = VmUpdateInfoWidget(vm, show_text=False)
|
||||||
@ -243,9 +243,9 @@ class VmInfoWidget(QtGui.QWidget):
|
|||||||
layout.addWidget(self.on_icon)
|
layout.addWidget(self.on_icon)
|
||||||
layout.addWidget(self.upd_info)
|
layout.addWidget(self.upd_info)
|
||||||
layout.addWidget(self.error_icon)
|
layout.addWidget(self.error_icon)
|
||||||
layout.addItem(QtGui.QSpacerItem(0, 10,
|
layout.addItem(QtWidgets.QSpacerItem(0, 10,
|
||||||
QtGui.QSizePolicy.Expanding,
|
QtWidgets.QSizePolicy.Expanding,
|
||||||
QtGui.QSizePolicy.Expanding))
|
QtWidgets.QSizePolicy.Expanding))
|
||||||
layout.addWidget(self.blk_icon)
|
layout.addWidget(self.blk_icon)
|
||||||
layout.addWidget(self.rec_icon)
|
layout.addWidget(self.rec_icon)
|
||||||
|
|
||||||
@ -256,7 +256,7 @@ class VmInfoWidget(QtGui.QWidget):
|
|||||||
self.blk_icon.setVisible(False)
|
self.blk_icon.setVisible(False)
|
||||||
self.error_icon.setVisible(False)
|
self.error_icon.setVisible(False)
|
||||||
|
|
||||||
self.table_item = self.VmInfoItem(self.on_icon,\
|
self.table_item = self.VmInfoItem(self.on_icon,
|
||||||
self.upd_info.table_item, vm)
|
self.upd_info.table_item, vm)
|
||||||
|
|
||||||
def update_vm_state(self):
|
def update_vm_state(self):
|
||||||
@ -264,7 +264,7 @@ class VmInfoWidget(QtGui.QWidget):
|
|||||||
self.upd_info.update_outdated()
|
self.upd_info.update_outdated()
|
||||||
|
|
||||||
|
|
||||||
class VMPropertyItem(QtGui.QTableWidgetItem):
|
class VMPropertyItem(QtWidgets.QTableWidgetItem):
|
||||||
def __init__(self, vm, property_name, empty_function=(lambda x: False),
|
def __init__(self, vm, property_name, empty_function=(lambda x: False),
|
||||||
check_default=False):
|
check_default=False):
|
||||||
"""
|
"""
|
||||||
@ -327,7 +327,7 @@ class VmTemplateItem(VMPropertyItem):
|
|||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setStyle(QtGui.QFont.StyleItalic)
|
font.setStyle(QtGui.QFont.StyleItalic)
|
||||||
self.setFont(font)
|
self.setFont(font)
|
||||||
self.setTextColor(QtGui.QColor("gray"))
|
self.setForeground(QtGui.QBrush(QtGui.QColor("gray")))
|
||||||
|
|
||||||
self.setText(self.vm.klass)
|
self.setText(self.vm.klass)
|
||||||
|
|
||||||
@ -342,8 +342,8 @@ class VmInternalItem(VMPropertyItem):
|
|||||||
|
|
||||||
|
|
||||||
# features man qvm-features
|
# features man qvm-features
|
||||||
class VmUpdateInfoWidget(QtGui.QWidget):
|
class VmUpdateInfoWidget(QtWidgets.QWidget):
|
||||||
class VmUpdateInfoItem(QtGui.QTableWidgetItem):
|
class VmUpdateInfoItem(QtWidgets.QTableWidgetItem):
|
||||||
def __init__(self, value, vm):
|
def __init__(self, value, vm):
|
||||||
super(VmUpdateInfoWidget.VmUpdateInfoItem, self).__init__()
|
super(VmUpdateInfoWidget.VmUpdateInfoItem, self).__init__()
|
||||||
self.value = 0
|
self.value = 0
|
||||||
@ -371,13 +371,13 @@ class VmUpdateInfoWidget(QtGui.QWidget):
|
|||||||
|
|
||||||
def __init__(self, vm, show_text=True, parent=None):
|
def __init__(self, vm, show_text=True, parent=None):
|
||||||
super(VmUpdateInfoWidget, self).__init__(parent)
|
super(VmUpdateInfoWidget, self).__init__(parent)
|
||||||
layout = QtGui.QHBoxLayout()
|
layout = QtWidgets.QHBoxLayout()
|
||||||
self.show_text = show_text
|
self.show_text = show_text
|
||||||
if self.show_text:
|
if self.show_text:
|
||||||
self.label = QtGui.QLabel("")
|
self.label = QtWidgets.QLabel("")
|
||||||
layout.addWidget(self.label, alignment=QtCore.Qt.AlignCenter)
|
layout.addWidget(self.label, alignment=QtCore.Qt.AlignCenter)
|
||||||
else:
|
else:
|
||||||
self.icon = QtGui.QLabel("")
|
self.icon = QtWidgets.QLabel("")
|
||||||
layout.addWidget(self.icon, alignment=QtCore.Qt.AlignCenter)
|
layout.addWidget(self.icon, alignment=QtCore.Qt.AlignCenter)
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
@ -432,6 +432,8 @@ class VmUpdateInfoWidget(QtGui.QWidget):
|
|||||||
"The Template must be stopped before changes from its "
|
"The Template must be stopped before changes from its "
|
||||||
"current session can be picked up by this qube.")
|
"current session can be picked up by this qube.")
|
||||||
else:
|
else:
|
||||||
|
label_text = None
|
||||||
|
tooltip_text = None
|
||||||
icon_path = None
|
icon_path = None
|
||||||
|
|
||||||
if hasattr(self, 'icon'):
|
if hasattr(self, 'icon'):
|
||||||
@ -445,12 +447,12 @@ class VmUpdateInfoWidget(QtGui.QWidget):
|
|||||||
if icon_path is not None:
|
if icon_path is not None:
|
||||||
self.icon = VmIconWidget(icon_path, True, 0.7)
|
self.icon = VmIconWidget(icon_path, True, 0.7)
|
||||||
self.icon.setToolTip(tooltip_text)
|
self.icon.setToolTip(tooltip_text)
|
||||||
self.layout().addWidget(self.icon,\
|
self.layout().addWidget(self.icon,
|
||||||
alignment=QtCore.Qt.AlignCenter)
|
alignment=QtCore.Qt.AlignCenter)
|
||||||
self.icon.setVisible(True)
|
self.icon.setVisible(True)
|
||||||
|
|
||||||
|
|
||||||
class VmSizeOnDiskItem(QtGui.QTableWidgetItem):
|
class VmSizeOnDiskItem(QtWidgets.QTableWidgetItem):
|
||||||
def __init__(self, vm):
|
def __init__(self, vm):
|
||||||
super(VmSizeOnDiskItem, self).__init__()
|
super(VmSizeOnDiskItem, self).__init__()
|
||||||
self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
|
self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
|
||||||
|
@ -32,10 +32,7 @@ from qubesadmin import Qubes
|
|||||||
from qubesadmin import exc
|
from qubesadmin import exc
|
||||||
from qubesadmin import events
|
from qubesadmin import events
|
||||||
|
|
||||||
from PyQt4 import QtGui # pylint: disable=import-error
|
from PyQt5 import QtWidgets, QtGui, QtCore # pylint: disable=import-error
|
||||||
from PyQt4 import QtCore # pylint: disable=import-error
|
|
||||||
from PyQt4 import Qt # pylint: disable=import-error
|
|
||||||
|
|
||||||
|
|
||||||
from . import ui_templatemanager # pylint: disable=no-name-in-module
|
from . import ui_templatemanager # pylint: disable=no-name-in-module
|
||||||
|
|
||||||
@ -43,7 +40,7 @@ column_names = ['State', 'Qube', 'Current template', 'New template']
|
|||||||
|
|
||||||
|
|
||||||
class TemplateManagerWindow(
|
class TemplateManagerWindow(
|
||||||
ui_templatemanager.Ui_MainWindow, QtGui.QMainWindow):
|
ui_templatemanager.Ui_MainWindow, QtWidgets.QMainWindow):
|
||||||
|
|
||||||
def __init__(self, qt_app, qubes_app, dispatcher, parent=None):
|
def __init__(self, qt_app, qubes_app, dispatcher, parent=None):
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
@ -61,11 +58,11 @@ class TemplateManagerWindow(
|
|||||||
self.prepare_lists()
|
self.prepare_lists()
|
||||||
self.initialize_table_events()
|
self.initialize_table_events()
|
||||||
|
|
||||||
self.buttonBox.button(QtGui.QDialogButtonBox.Ok).clicked.connect(
|
self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect(
|
||||||
self.apply)
|
self.apply)
|
||||||
self.buttonBox.button(QtGui.QDialogButtonBox.Cancel).clicked.connect(
|
self.buttonBox.button(
|
||||||
self.cancel)
|
QtWidgets.QDialogButtonBox.Cancel).clicked.connect(self.cancel)
|
||||||
self.buttonBox.button(QtGui.QDialogButtonBox.Reset).clicked.connect(
|
self.buttonBox.button(QtWidgets.QDialogButtonBox.Reset).clicked.connect(
|
||||||
self.reset)
|
self.reset)
|
||||||
|
|
||||||
self.change_all_combobox.currentIndexChanged.connect(
|
self.change_all_combobox.currentIndexChanged.connect(
|
||||||
@ -118,7 +115,7 @@ class TemplateManagerWindow(
|
|||||||
def vm_added(self, _submitter, _event, vm, **_kwargs):
|
def vm_added(self, _submitter, _event, vm, **_kwargs):
|
||||||
# unfortunately, a VM just in the moment of creation may not have
|
# unfortunately, a VM just in the moment of creation may not have
|
||||||
# a template it will have in a second - e.g., when cloning
|
# a template it will have in a second - e.g., when cloning
|
||||||
timer = Qt.QTimer()
|
timer = QtCore.QTimer()
|
||||||
timer.setSingleShot(True)
|
timer.setSingleShot(True)
|
||||||
timer.timeout.connect(lambda: self._vm_added(vm, timer))
|
timer.timeout.connect(lambda: self._vm_added(vm, timer))
|
||||||
self.timers.append(timer)
|
self.timers.append(timer)
|
||||||
@ -239,7 +236,7 @@ class TemplateManagerWindow(
|
|||||||
errors[vm] = str(ex)
|
errors[vm] = str(ex)
|
||||||
if errors:
|
if errors:
|
||||||
error_messages = [vm + ": " + errors[vm] for vm in errors]
|
error_messages = [vm + ": " + errors[vm] for vm in errors]
|
||||||
QtGui.QMessageBox.warning(
|
QtWidgets.QMessageBox.warning(
|
||||||
self,
|
self,
|
||||||
self.tr("Errors encountered!"),
|
self.tr("Errors encountered!"),
|
||||||
self.tr(
|
self.tr(
|
||||||
@ -248,7 +245,7 @@ class TemplateManagerWindow(
|
|||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
|
||||||
class VMNameItem(QtGui.QTableWidgetItem):
|
class VMNameItem(QtWidgets.QTableWidgetItem):
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
def __init__(self, vm):
|
def __init__(self, vm):
|
||||||
super(VMNameItem, self).__init__()
|
super(VMNameItem, self).__init__()
|
||||||
@ -258,7 +255,7 @@ class VMNameItem(QtGui.QTableWidgetItem):
|
|||||||
self.setIcon(QtGui.QIcon.fromTheme(vm.label.icon))
|
self.setIcon(QtGui.QIcon.fromTheme(vm.label.icon))
|
||||||
|
|
||||||
|
|
||||||
class StatusItem(QtGui.QTableWidgetItem):
|
class StatusItem(QtWidgets.QTableWidgetItem):
|
||||||
def __init__(self, vm):
|
def __init__(self, vm):
|
||||||
super(StatusItem, self).__init__()
|
super(StatusItem, self).__init__()
|
||||||
self.vm = vm
|
self.vm = vm
|
||||||
@ -281,7 +278,7 @@ class StatusItem(QtGui.QTableWidgetItem):
|
|||||||
return self.state < other.state
|
return self.state < other.state
|
||||||
|
|
||||||
|
|
||||||
class CurrentTemplateItem(QtGui.QTableWidgetItem):
|
class CurrentTemplateItem(QtWidgets.QTableWidgetItem):
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
def __init__(self, vm):
|
def __init__(self, vm):
|
||||||
super(CurrentTemplateItem, self).__init__()
|
super(CurrentTemplateItem, self).__init__()
|
||||||
@ -295,7 +292,7 @@ class CurrentTemplateItem(QtGui.QTableWidgetItem):
|
|||||||
return self.text() < other.text()
|
return self.text() < other.text()
|
||||||
|
|
||||||
|
|
||||||
class NewTemplateItem(QtGui.QComboBox):
|
class NewTemplateItem(QtWidgets.QComboBox):
|
||||||
def __init__(self, vm, templates, table_widget):
|
def __init__(self, vm, templates, table_widget):
|
||||||
super(NewTemplateItem, self).__init__()
|
super(NewTemplateItem, self).__init__()
|
||||||
self.vm = vm
|
self.vm = vm
|
||||||
@ -331,7 +328,7 @@ class VMRow:
|
|||||||
# state
|
# state
|
||||||
self.state_item = StatusItem(self.vm)
|
self.state_item = StatusItem(self.vm)
|
||||||
table_widget.setItem(row_no, columns.index('State'), self.state_item)
|
table_widget.setItem(row_no, columns.index('State'), self.state_item)
|
||||||
self.checkbox = QtGui.QCheckBox()
|
self.checkbox = QtWidgets.QCheckBox()
|
||||||
|
|
||||||
# icon and name
|
# icon and name
|
||||||
self.name_item = VMNameItem(self.vm)
|
self.name_item = VMNameItem(self.vm)
|
||||||
@ -343,7 +340,7 @@ class VMRow:
|
|||||||
self.current_item)
|
self.current_item)
|
||||||
|
|
||||||
# new template
|
# new template
|
||||||
self.dummy_new_item = QtGui.QTableWidgetItem("qube is running")
|
self.dummy_new_item = QtWidgets.QTableWidgetItem("qube is running")
|
||||||
self.new_item = NewTemplateItem(self.vm, templates, table_widget)
|
self.new_item = NewTemplateItem(self.vm, templates, table_widget)
|
||||||
|
|
||||||
table_widget.setItem(row_no, columns.index('New template'),
|
table_widget.setItem(row_no, columns.index('New template'),
|
||||||
@ -367,7 +364,7 @@ class VMRow:
|
|||||||
if not is_running:
|
if not is_running:
|
||||||
self.new_item = NewTemplateItem(self.vm, self.templates,
|
self.new_item = NewTemplateItem(self.vm, self.templates,
|
||||||
self.table_widget)
|
self.table_widget)
|
||||||
self.checkbox = QtGui.QCheckBox()
|
self.checkbox = QtWidgets.QCheckBox()
|
||||||
|
|
||||||
self.table_widget.setCellWidget(
|
self.table_widget.setCellWidget(
|
||||||
row, column_names.index('New template'), self.new_item)
|
row, column_names.index('New template'), self.new_item)
|
||||||
@ -408,9 +405,9 @@ def handle_exception(exc_type, exc_value, exc_traceback):
|
|||||||
strace += "line no.: %d\n" % line
|
strace += "line no.: %d\n" % line
|
||||||
strace += "file: %s\n" % filename
|
strace += "file: %s\n" % filename
|
||||||
|
|
||||||
msg_box = QtGui.QMessageBox()
|
msg_box = QtWidgets.QMessageBox()
|
||||||
msg_box.setDetailedText(strace)
|
msg_box.setDetailedText(strace)
|
||||||
msg_box.setIcon(QtGui.QMessageBox.Critical)
|
msg_box.setIcon(QtWidgets.QMessageBox.Critical)
|
||||||
msg_box.setWindowTitle("Houston, we have a problem...")
|
msg_box.setWindowTitle("Houston, we have a problem...")
|
||||||
msg_box.setText("Whoops. A critical error has occured. "
|
msg_box.setText("Whoops. A critical error has occured. "
|
||||||
"This is most likely a bug in Qubes Manager.<br><br>"
|
"This is most likely a bug in Qubes Manager.<br><br>"
|
||||||
@ -429,7 +426,7 @@ def loop_shutdown():
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
qt_app = QtGui.QApplication(sys.argv)
|
qt_app = QtWidgets.QApplication(sys.argv)
|
||||||
qt_app.setOrganizationName("The Qubes Project")
|
qt_app.setOrganizationName("The Qubes Project")
|
||||||
qt_app.setOrganizationDomain("http://qubes-os.org")
|
qt_app.setOrganizationDomain("http://qubes-os.org")
|
||||||
qt_app.setApplicationName("Qube Manager")
|
qt_app.setApplicationName("Qube Manager")
|
||||||
|
@ -24,12 +24,14 @@ import os
|
|||||||
import re
|
import re
|
||||||
import qubesadmin
|
import qubesadmin
|
||||||
|
|
||||||
from PyQt4.QtGui import QIcon # pylint: disable=import-error
|
from PyQt5.QtGui import QIcon # pylint: disable=import-error
|
||||||
|
|
||||||
|
|
||||||
def _filter_internal(vm):
|
def _filter_internal(vm):
|
||||||
return (not vm.klass == 'AdminVM'
|
return (not vm.klass == 'AdminVM'
|
||||||
and not vm.features.get('internal', False))
|
and not vm.features.get('internal', False))
|
||||||
|
|
||||||
|
|
||||||
def prepare_choice(widget, holder, propname, choice, default,
|
def prepare_choice(widget, holder, propname, choice, default,
|
||||||
filter_function=None, *,
|
filter_function=None, *,
|
||||||
icon_getter=None, allow_internal=None, allow_default=False,
|
icon_getter=None, allow_internal=None, allow_default=False,
|
||||||
@ -112,10 +114,13 @@ def prepare_choice(widget, holder, propname, choice, default,
|
|||||||
|
|
||||||
return choice_list, idx
|
return choice_list, idx
|
||||||
|
|
||||||
|
|
||||||
def prepare_kernel_choice(widget, holder, propname, default, *args, **kwargs):
|
def prepare_kernel_choice(widget, holder, propname, default, *args, **kwargs):
|
||||||
# TODO get from storage API (pool 'linux-kernel') (suggested by @marmarta)
|
# TODO get from storage API (pool 'linux-kernel') (suggested by @marmarta)
|
||||||
return prepare_choice(widget, holder, propname,
|
return prepare_choice(widget, holder, propname,
|
||||||
os.listdir('/var/lib/qubes/vm-kernels'), default, *args, **kwargs)
|
os.listdir('/var/lib/qubes/vm-kernels'),
|
||||||
|
default, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def prepare_label_choice(widget, holder, propname, default, *args, **kwargs):
|
def prepare_label_choice(widget, holder, propname, default, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
@ -126,9 +131,11 @@ def prepare_label_choice(widget, holder, propname, default, *args, **kwargs):
|
|||||||
return prepare_choice(widget, holder, propname,
|
return prepare_choice(widget, holder, propname,
|
||||||
sorted(app.labels.values(), key=lambda l: l.index),
|
sorted(app.labels.values(), key=lambda l: l.index),
|
||||||
default, *args,
|
default, *args,
|
||||||
icon_getter=(lambda label: QIcon.fromTheme(label.icon)),
|
icon_getter=(lambda label:
|
||||||
|
QIcon.fromTheme(label.icon)),
|
||||||
**kwargs)
|
**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def prepare_vm_choice(widget, holder, propname, default, *args, **kwargs):
|
def prepare_vm_choice(widget, holder, propname, default, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
app = holder.app
|
app = holder.app
|
||||||
@ -138,9 +145,11 @@ def prepare_vm_choice(widget, holder, propname, default, *args, **kwargs):
|
|||||||
return prepare_choice(widget, holder, propname, app.domains, default,
|
return prepare_choice(widget, holder, propname, app.domains, default,
|
||||||
*args, **kwargs)
|
*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def is_debug():
|
def is_debug():
|
||||||
return os.getenv('QUBES_MANAGER_DEBUG', '') not in ('', '0')
|
return os.getenv('QUBES_MANAGER_DEBUG', '') not in ('', '0')
|
||||||
|
|
||||||
|
|
||||||
def debug(*args, **kwargs):
|
def debug(*args, **kwargs):
|
||||||
if not is_debug():
|
if not is_debug():
|
||||||
return
|
return
|
||||||
|
@ -8,7 +8,7 @@ Vendor: Invisible Things Lab
|
|||||||
License: GPL
|
License: GPL
|
||||||
URL: http://fixme
|
URL: http://fixme
|
||||||
Requires: python3
|
Requires: python3
|
||||||
Requires: python3-PyQt4
|
Requires: python3-PyQt5
|
||||||
Requires: python3-inotify
|
Requires: python3-inotify
|
||||||
Requires: python3-qubesadmin >= 4.0.19
|
Requires: python3-qubesadmin >= 4.0.19
|
||||||
Requires: python3-Quamash
|
Requires: python3-Quamash
|
||||||
@ -17,9 +17,10 @@ Requires: qubes-artwork
|
|||||||
Requires: pmount
|
Requires: pmount
|
||||||
Requires: cryptsetup
|
Requires: cryptsetup
|
||||||
Requires: wmctrl
|
Requires: wmctrl
|
||||||
BuildRequires: python3-PyQt4-devel
|
BuildRequires: python3-PyQt5-devel
|
||||||
BuildRequires: python3-devel
|
BuildRequires: python3-devel
|
||||||
BuildRequires: qt-devel
|
BuildRequires: qt5-devel
|
||||||
|
BuildRequires: qt5-linguist
|
||||||
AutoReq: 0
|
AutoReq: 0
|
||||||
|
|
||||||
Source0: %{name}-%{version}.tar.gz
|
Source0: %{name}-%{version}.tar.gz
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>700</width>
|
<width>756</width>
|
||||||
<height>399</height>
|
<height>440</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -214,7 +214,7 @@
|
|||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
<string><!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" /><style type="text/css">
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
p, li { white-space: pre-wrap; }
|
p, li { white-space: pre-wrap; }
|
||||||
</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;">
|
</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></string>
|
<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></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
Loading…
Reference in New Issue
Block a user