Browse Source

Merge remote-tracking branch 'origin/pr/270'

* origin/pr/270:
  Restored removed lines by accident (although I think that are useless at this moment)
  Fix pylint warnings
  Added saving and restore settings for showing checkboxes
  Removed unused import
  Enable 'Show' checkboxes by default
  Added filterAcceptsRow() to QubesProxyModel
  Added 'Show' Checkboxes to .ui
  Fix SelectionMode on ui file
Marek Marczykowski-Górecki 3 years ago
parent
commit
c44880f9f5
2 changed files with 195 additions and 48 deletions
  1. 97 30
      qubesmanager/qube_manager.py
  2. 98 18
      ui/qubemanager.ui

+ 97 - 30
qubesmanager/qube_manager.py

@@ -37,7 +37,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)
@@ -630,8 +630,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)
@@ -641,6 +644,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
@@ -659,38 +687,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.addMenu(self.logs_menu)
-        self.context_menu.addSeparator()
+        self.__init_context_menu()
 
         self.tools_context_menu = QMenu(self)
         self.tools_context_menu.addAction(self.action_toolbar)
@@ -713,7 +717,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)
@@ -721,10 +725,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)
 
@@ -794,12 +804,52 @@ 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.addMenu(self.logs_menu)
+        self.context_menu.addSeparator()
+
+    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(
@@ -948,6 +998,20 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QMainWindow):
                                            defaultValue=True):
             self.action_toolbar.setChecked(False)
 
+        # 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",
                                                 QSize(1100, 600)))
@@ -1264,6 +1328,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):

+ 98 - 18
ui/qubemanager.ui

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