Merge branch 'master' of https://github.com/QubesOS/qubes-manager into log_dialog

# Conflicts:
#	qubesmanager/qube_manager.py
#	ui/qubemanager.ui
This commit is contained in:
donoban 2020-12-10 23:39:34 +01:00
commit ebe777c5a1
No known key found for this signature in database
GPG Key ID: 141310D8E3ED08A5
2 changed files with 216 additions and 48 deletions

View File

@ -35,7 +35,7 @@ from PyQt5.QtCore import (Qt, QAbstractTableModel, QObject, pyqtSlot, QEvent,
# pylint: disable=import-error
from PyQt5.QtWidgets import (QLineEdit, QStyledItemDelegate, QToolTip,
QMenu, QInputDialog, QMainWindow, QProgressDialog, QStyleOptionViewItem,
QAbstractItemView, QMessageBox)
QMessageBox)
# pylint: disable=import-error
from PyQt5.QtGui import (QIcon, QPixmap, QRegExpValidator, QFont, QColor)
@ -628,8 +628,11 @@ class RunCommandThread(common_threads.QubesThread):
except (ChildProcessError, exc.QubesException) as ex:
self.msg = (self.tr("Error while running command!"), str(ex))
class QubesProxyModel(QSortFilterProxyModel):
def __init__(self, window):
super().__init__()
self.window = window
def lessThan(self, left, right):
if left.data(self.sortRole()) != right.data(self.sortRole()):
return super().lessThan(left, right)
@ -639,6 +642,31 @@ class QubesProxyModel(QSortFilterProxyModel):
return left_vm.name.lower() < right_vm.name.lower()
# pylint: disable=too-many-return-statements
def filterAcceptsRow(self, sourceRow, sourceParent):
if self.window.show_all.isChecked():
return super().filterAcceptsRow(sourceRow, sourceParent)
index = self.sourceModel().index(sourceRow, 0, sourceParent)
vm = self.sourceModel().data(index, Qt.UserRole)
if self.window.show_running.isChecked() and \
vm.state['power'] == 'Running':
return super().filterAcceptsRow(sourceRow, sourceParent)
if self.window.show_halted.isChecked() and \
vm.state['power'] == 'Halted':
return super().filterAcceptsRow(sourceRow, sourceParent)
if self.window.show_network.isChecked() and \
getattr(vm.vm, 'provides_network', False):
return super().filterAcceptsRow(sourceRow, sourceParent)
if self.window.show_templates.isChecked() and vm.klass == 'TemplateVM':
return super().filterAcceptsRow(sourceRow, sourceParent)
if self.window.show_standalone.isChecked() \
and vm.klass == 'StandaloneVM':
return super().filterAcceptsRow(sourceRow, sourceParent)
return False
class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QMainWindow):
# suppress saving settings while initializing widgets
@ -657,38 +685,14 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QMainWindow):
self.searchbox.setValidator(QRegExpValidator(
QRegExp("[a-zA-Z0-9_-]*", Qt.CaseInsensitive), None))
self.searchbox.textChanged.connect(self.do_search)
self.searchContainer.addWidget(self.searchbox)
self.searchContainer.insertWidget(1, self.searchbox)
self.settings_windows = {}
self.frame_width = 0
self.frame_height = 0
self.context_menu = QMenu(self)
self.context_menu.addAction(self.action_settings)
self.context_menu.addAction(self.action_editfwrules)
self.context_menu.addAction(self.action_appmenus)
self.context_menu.addAction(self.action_set_keyboard_layout)
self.context_menu.addSeparator()
self.context_menu.addAction(self.action_updatevm)
self.context_menu.addAction(self.action_run_command_in_vm)
self.context_menu.addAction(self.action_open_console)
self.context_menu.addAction(self.action_resumevm)
self.context_menu.addAction(self.action_startvm_tools_install)
self.context_menu.addAction(self.action_pausevm)
self.context_menu.addAction(self.action_shutdownvm)
self.context_menu.addAction(self.action_restartvm)
self.context_menu.addAction(self.action_killvm)
self.context_menu.addSeparator()
self.context_menu.addAction(self.action_clonevm)
self.context_menu.addAction(self.action_removevm)
self.context_menu.addSeparator()
self.context_menu.addAction(self.action_show_logs)
self.context_menu.addSeparator()
self.__init_context_menu()
self.tools_context_menu = QMenu(self)
self.tools_context_menu.addAction(self.action_toolbar)
@ -701,6 +705,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QMainWindow):
self.action_menubar.toggled.connect(self.showhide_menubar)
self.action_toolbar.toggled.connect(self.showhide_toolbar)
self.action_show_logs.triggered.connect(self.show_log)
self.action_compact_view.toggled.connect(self.set_compactview)
self.table.resizeColumnsToContents()
@ -711,7 +716,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QMainWindow):
self.fill_cache()
self.qubes_model = QubesTableModel(self.qubes_cache)
self.proxy = QubesProxyModel()
self.proxy = QubesProxyModel(self)
self.proxy.setSourceModel(self.qubes_model)
self.proxy.setSortRole(Qt.UserRole + 1)
self.proxy.setSortCaseSensitivity(Qt.CaseInsensitive)
@ -719,10 +724,16 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QMainWindow):
self.proxy.setFilterCaseSensitivity(Qt.CaseInsensitive)
self.proxy.layoutChanged.connect(self.save_sorting)
self.show_running.stateChanged.connect(self.invalidate)
self.show_halted.stateChanged.connect(self.invalidate)
self.show_network.stateChanged.connect(self.invalidate)
self.show_templates.stateChanged.connect(self.invalidate)
self.show_standalone.stateChanged.connect(self.invalidate)
self.show_all.stateChanged.connect(self.invalidate)
self.table.setModel(self.proxy)
self.table.setItemDelegateForColumn(3, StateIconDelegate())
self.table.resizeColumnsToContents()
self.table.setSelectionMode(QAbstractItemView.ExtendedSelection)
selection_model = self.table.selectionModel()
selection_model.selectionChanged.connect(self.table_selection_changed)
@ -740,6 +751,8 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QMainWindow):
self.menu_view.addSeparator()
self.menu_view.addAction(self.action_toolbar)
self.menu_view.addAction(self.action_menubar)
self.menu_view.addSeparator()
self.menu_view.addAction(self.action_compact_view)
try:
self.load_manager_settings()
@ -792,12 +805,51 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QMainWindow):
self.check_updates()
def __init_context_menu(self):
self.context_menu = QMenu(self)
self.context_menu.addAction(self.action_settings)
self.context_menu.addAction(self.action_editfwrules)
self.context_menu.addAction(self.action_appmenus)
self.context_menu.addAction(self.action_set_keyboard_layout)
self.context_menu.addSeparator()
self.context_menu.addAction(self.action_updatevm)
self.context_menu.addAction(self.action_run_command_in_vm)
self.context_menu.addAction(self.action_open_console)
self.context_menu.addAction(self.action_resumevm)
self.context_menu.addAction(self.action_startvm_tools_install)
self.context_menu.addAction(self.action_pausevm)
self.context_menu.addAction(self.action_shutdownvm)
self.context_menu.addAction(self.action_restartvm)
self.context_menu.addAction(self.action_killvm)
self.context_menu.addSeparator()
self.context_menu.addAction(self.action_clonevm)
self.context_menu.addAction(self.action_removevm)
self.context_menu.addSeparator()
self.context_menu.addAction(self.action_show_logs)
def save_showing(self):
self.manager_settings.setValue('show/running',
self.show_running.isChecked())
self.manager_settings.setValue('show/halted',
self.show_halted.isChecked())
self.manager_settings.setValue('show/network',
self.show_network.isChecked())
self.manager_settings.setValue('show/templates',
self.show_templates.isChecked())
self.manager_settings.setValue('show/standalone',
self.show_standalone.isChecked())
self.manager_settings.setValue('show/all', self.show_all.isChecked())
def save_sorting(self):
self.manager_settings.setValue('view/sort_column',
self.proxy.sortColumn())
self.manager_settings.setValue('view/sort_order',
self.proxy.sortOrder())
def invalidate(self):
self.proxy.invalidate()
self.table.resizeColumnsToContents()
def fill_cache(self):
progress = QProgressDialog(
self.tr(
@ -945,6 +997,23 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QMainWindow):
if not self.manager_settings.value("view/toolbar_visible",
defaultValue=True):
self.action_toolbar.setChecked(False)
if self.manager_settings.value("view/compactview",
defaultValue="false") != "false":
self.action_compact_view.setChecked(True)
# Restore show checkboxes
self.show_running.setChecked(self.manager_settings.value(
'show/running', "true") == "true")
self.show_halted.setChecked(self.manager_settings.value(
'show/halted', "true") == "true")
self.show_network.setChecked(self.manager_settings.value(
'show/network', "true") == "true")
self.show_templates.setChecked(self.manager_settings.value(
'show/templates', "true") == "true")
self.show_standalone.setChecked(self.manager_settings.value(
'show/standalone', "true") == "true")
self.show_all.setChecked(self.manager_settings.value(
'show/all', "true") == "true")
# load last window size
self.resize(self.manager_settings.value("window_size",
@ -1260,6 +1329,9 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QMainWindow):
"\nError: {}".format(str(ex))))
return
def closeEvent(self, _):
self.save_showing()
# noinspection PyArgumentList
@pyqtSlot(name='on_action_settings_triggered')
def action_settings_triggered(self):
@ -1386,6 +1458,14 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QMainWindow):
def action_exit_triggered(self):
self.close()
def set_compactview(self, checked):
if checked:
self.toolbar.setToolButtonStyle(Qt.ToolButtonIconOnly)
else:
self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
if self.settings_loaded:
self.manager_settings.setValue('view/compactview', checked)
def showhide_menubar(self, checked):
self.menubar.setVisible(checked)
if not checked:

View File

@ -52,23 +52,6 @@
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item row="0" column="0">
<layout class="QHBoxLayout" name="searchContainer">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Search:</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QTableView" name="table">
<property name="minimumSize">
@ -108,7 +91,7 @@
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
@ -236,6 +219,103 @@ Template</string>
</column>
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="searchContainer">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Search:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="show_label">
<property name="text">
<string>Show:</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="show_running">
<property name="text">
<string>Running</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="show_halted">
<property name="text">
<string>Halted</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="show_network">
<property name="text">
<string>Network</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="show_templates">
<property name="text">
<string>Templates</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="show_standalone">
<property name="text">
<string>Standalone</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="show_all">
<property name="text">
<string>All</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
@ -878,6 +958,14 @@ Template</string>
<string>Logs</string>
</property>
</action>
<action name="action_compact_view">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Compact View</string>
</property>
</action>
</widget>
<resources>
<include location="../resources.qrc"/>