From 9633f6e9c63b4d667957a4751b00afefb0084682 Mon Sep 17 00:00:00 2001 From: donoban Date: Thu, 3 May 2018 11:34:11 +0200 Subject: [PATCH 01/27] Removed progress wait when updating template --- qubesmanager/qube_manager.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 502a569..c8f5cf4 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -919,20 +919,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): thread.daemon = True thread.start() - progress = QtGui.QProgressDialog( - self.tr( - "{0}
Please wait for the updater to " - "launch...").format(vm.name), "", 0, 0) - progress.setCancelButton(None) - progress.setModal(True) - progress.show() - - while not t_monitor.is_finished(): - self.qt_app.processEvents() - time.sleep(0.2) - - progress.hide() - if vm.qid != 0: if not t_monitor.success: QtGui.QMessageBox.warning( From 07d36a914922593c63c9b9a222c6778ed0871a62 Mon Sep 17 00:00:00 2001 From: donoban Date: Mon, 7 May 2018 13:17:43 +0200 Subject: [PATCH 02/27] Added update() methods on some widgets for update them without recreating Fixed some problems with update/status notifications, probably need some additional tunning --- qubesmanager/table_widgets.py | 61 +++++++++++++++++------------------ 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/qubesmanager/table_widgets.py b/qubesmanager/table_widgets.py index 27a2b15..d92ec0e 100644 --- a/qubesmanager/table_widgets.py +++ b/qubesmanager/table_widgets.py @@ -110,7 +110,6 @@ class VmTypeWidget(VmIconWidget): class VmLabelWidget(VmIconWidget): - class VmLabelItem(QtGui.QTableWidgetItem): def __init__(self, value, vm): super(VmLabelWidget.VmLabelItem, self).__init__() @@ -256,7 +255,7 @@ class VmInfoWidget(QtGui.QWidget): def update_vm_state(self, vm): self.on_icon.update() - self.upd_info.update_outdated(vm) + self.upd_info.update_outdated() class VmTemplateItem(QtGui.QTableWidgetItem): @@ -264,18 +263,19 @@ class VmTemplateItem(QtGui.QTableWidgetItem): super(VmTemplateItem, self).__init__() self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) self.vm = vm + self.setTextAlignment(QtCore.Qt.AlignVCenter) + self.update() - if getattr(vm, 'template', None) is not None: - self.setText(vm.template.name) + def update(self): + if getattr(self.vm, 'template', None) is not None: + self.setText(self.vm.template.name) else: font = QtGui.QFont() font.setStyle(QtGui.QFont.StyleItalic) self.setFont(font) self.setTextColor(QtGui.QColor("gray")) - self.setText(vm.klass) - - self.setTextAlignment(QtCore.Qt.AlignVCenter) + self.setText(self.vm.klass) def __lt__(self, other): if self.vm.qid == 0: @@ -292,13 +292,14 @@ class VmNetvmItem(QtGui.QTableWidgetItem): super(VmNetvmItem, self).__init__() self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) self.vm = vm + self.setTextAlignment(QtCore.Qt.AlignVCenter) + self.update() - if getattr(vm, 'netvm', None) is None: + def update(self): + if getattr(self.vm, 'netvm', None) is None: self.setText("n/a") else: - self.setText(vm.netvm.name) - - self.setTextAlignment(QtCore.Qt.AlignVCenter) + self.setText(self.vm.netvm.name) def __lt__(self, other): if self.vm.qid == 0: @@ -330,7 +331,6 @@ class VmInternalItem(QtGui.QTableWidgetItem): # features man qvm-features class VmUpdateInfoWidget(QtGui.QWidget): - class VmUpdateInfoItem(QtGui.QTableWidgetItem): def __init__(self, value, vm): super(VmUpdateInfoWidget.VmUpdateInfoItem, self).__init__() @@ -367,32 +367,31 @@ class VmUpdateInfoWidget(QtGui.QWidget): layout.addWidget(self.icon, alignment=QtCore.Qt.AlignCenter) self.setLayout(layout) + self.vm = vm + self.previous_outdated_state = None self.previous_update_recommended = None self.value = None self.table_item = VmUpdateInfoWidget.VmUpdateInfoItem(self.value, vm) - self.update_outdated(vm) + self.update_outdated() - def update_outdated(self, vm): + def update_outdated(self): + if self.vm.is_running(): + outdated_state = False - outdated_state = False + for vol in self.vm.volumes.values(): + if vol.is_outdated(): + outdated_state = "outdated" + break - for vol in vm.volumes.values(): - if vol.is_outdated(): - outdated_state = "outdated" - break - - if not outdated_state and getattr(vm, 'template', None)\ - and vm.template.is_running(): - outdated_state = "to-be-outdated" - if outdated_state != self.previous_outdated_state: - self.update_status_widget(outdated_state) - self.previous_outdated_state = outdated_state - - updates_available = vm.features.get('updates-available', False) - if updates_available != self.previous_update_recommended: - self.update_status_widget("update" if updates_available else None) - self.previous_update_recommended = updates_available + if not outdated_state and getattr(self.vm, 'template', None)\ + and self.vm.template.is_running(): + outdated_state = "to-be-outdated" + if outdated_state != self.previous_outdated_state: + self.update_status_widget(outdated_state) + self.previous_outdated_state = outdated_state + else: + outdated_state = False def update_status_widget(self, state): self.value = state From be055d8b41c7911785c3efcd6223965cc89c5b5b Mon Sep 17 00:00:00 2001 From: donoban Date: Mon, 7 May 2018 13:30:03 +0200 Subject: [PATCH 03/27] Revert order of fill_table() and show() and removed the timer This does not seem to have any problem and the manager window appears already filled which seems more user friendly --- qubesmanager/qube_manager.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index c8f5cf4..2346ac7 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -1200,9 +1200,8 @@ def main(): manager_window = VmManagerWindow(qt_app, qubes_app) + manager_window.fill_table() manager_window.show() - timer = QtCore.QTimer() - timer.singleShot(1, manager_window.update_table) qt_app.exec_() From ddf2e73f20018a984a8163e27f3e20f468aee006 Mon Sep 17 00:00:00 2001 From: donoban Date: Mon, 7 May 2018 20:50:20 +0200 Subject: [PATCH 04/27] - Remove some stuff on fill_table since its only called once on startup - Removed table.setEnabled/Disabled tweak since I dont see any improvement, maybe because fill_table() is only called without the window shown - Removed unneeded update_table() calls, dbus events will handle them --- qubesmanager/qube_manager.py | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 2346ac7..09c746d 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -68,10 +68,8 @@ class SearchBox(QtGui.QLineEdit): class VmRowInTable(object): # pylint: disable=too-few-public-methods - def __init__(self, vm, row_no, table): self.vm = vm - self.row_no = row_no # TODO: replace a various different widgets with a more generic # VmFeatureWidget or VMPropertyWidget @@ -363,12 +361,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.load_manager_settings() - # disabling the table for the duration of filling speeds up the process - # immensely. Yes, really. - - self.table.setDisabled(True) self.fill_table() - self.table.setEnabled(True) self.update_size_on_disk = False self.shutdown_monitor = {} @@ -413,14 +406,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.update_table() def fill_table(self): - # save current selection - row_index = self.table.currentRow() - selected_qid = -1 - if row_index != -1: - vm_item = self.table.item(row_index, self.columns_indices["Name"]) - if vm_item: - selected_qid = vm_item.qid - self.table.setSortingEnabled(False) self.table.clearContents() vms_list = self.get_vms_list() @@ -434,18 +419,11 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): vm_row = VmRowInTable(vm, row_no, self.table) vms_in_table[vm.qid] = vm_row row_no += 1 - if row_no % 5 == 0: - self.qt_app.processEvents() self.vms_list = vms_list self.vms_in_table = vms_in_table - if selected_qid in vms_in_table.keys(): - self.table.setCurrentItem( - self.vms_in_table[selected_qid].name_widget) self.table.setSortingEnabled(True) - self.showhide_vms() - def showhide_vms(self): if not self.search: for row_no in range(self.table.rowCount()): @@ -468,10 +446,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.searchbox.setFocus() def update_table(self): - # disabling the table speeds up the process of filling it - self.table.setDisabled(True) self.fill_table() - self.table.setEnabled(True) # TODO: instead of manually refreshing the entire table, use dbus events # reapply sorting @@ -640,7 +615,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.tr("ERROR: {0}").format( t_monitor.error_msg)) - self.update_table() @staticmethod def do_remove_vm(vm, qubes_app, t_monitor): @@ -695,7 +669,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.tr("Exception while cloning:
{0}").format( t_monitor.error_msg)) - self.update_table() @staticmethod def do_clone_vm(src_vm, qubes_app, dst_name, t_monitor): @@ -890,11 +863,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): vm, self.qt_app, "applications") settings_window.exec_() - # noinspection PyArgumentList - @QtCore.pyqtSlot(name='on_action_refresh_list_triggered') - def action_refresh_list_triggered(self): - self.qubes_app.domains.clear_cache() - self.update_table() # noinspection PyArgumentList @QtCore.pyqtSlot(name='on_action_updatevm_triggered') @@ -1200,7 +1168,6 @@ def main(): manager_window = VmManagerWindow(qt_app, qubes_app) - manager_window.fill_table() manager_window.show() qt_app.exec_() From 875311932783695336e0a81dbcee620d3a53bab0 Mon Sep 17 00:00:00 2001 From: donoban Date: Mon, 7 May 2018 21:10:15 +0200 Subject: [PATCH 05/27] Initial version with dbus - Added connections for PropertiesChanged for each VM in VmRowInTable - DomainAdded/Removed handled in VmManager --- qubesmanager/qube_manager.py | 62 +++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 09c746d..e5b6690 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -29,6 +29,7 @@ import subprocess import time from datetime import datetime, timedelta import traceback +from pydbus import SessionBus from qubesadmin import Qubes from qubesadmin import exc @@ -73,6 +74,7 @@ class VmRowInTable(object): # TODO: replace a various different widgets with a more generic # VmFeatureWidget or VMPropertyWidget + table_widgets.row_height = VmManagerWindow.row_height table.setRowHeight(row_no, VmManagerWindow.row_height) @@ -127,6 +129,19 @@ class VmRowInTable(object): table.setItem(row_no, VmManagerWindow.columns_indices[ 'Last backup'], self.last_backup_widget) + self.table = table + + #Connect dbus events + bus = SessionBus() + self.dbus = bus.get("org.qubes.DomainManager1" , "/org/qubes/DomainManager1/domains/" + str(vm.qid)) + self.dbus.PropertiesChanged.connect(self.OnPropertiesChanged) + + def OnPropertiesChanged(self, dbus, properties, dump): + for key in properties: + if key == 'state': + self.update() + self.table.update() + def update(self, update_size_on_disk=False): """ Update info in a single VM row @@ -135,6 +150,8 @@ class VmRowInTable(object): :return: None """ self.info_widget.update_vm_state(self.vm) + self.template_widget.update() + self.netvm_widget.update() if update_size_on_disk: self.size_widget.update() @@ -366,6 +383,49 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.update_size_on_disk = False self.shutdown_monitor = {} + bus = SessionBus() + manager = bus.get("org.qubes.DomainManager1") + manager.DomainAdded.connect(self.OnDomainAdded) + manager.DomainRemoved.connect(self.OnDomainRemoved) + + def OnDomainAdded(self, manager, domain): + #needs to clear cache + self.qubes_app.domains.clear_cache() + qid = int(domain.split('/')[-1]) + + self.table.setSortingEnabled(False) + + row_no = self.table.rowCount() + self.table.setRowCount(row_no + 1) + + + for vm in self.qubes_app.domains: + if vm.qid == qid: + vm_row = VmRowInTable(vm, row_no, self.table) + self.vms_in_table[vm.qid] = vm_row + break + + self.table.setSortingEnabled(True) + self.table.update() + + def OnDomainRemoved(self, manager, domain): + #needs to clear cache + self.qubes_app.domains.clear_cache() + + qid = int(domain.split('/')[-1]) + + # Find row and remove + row_index = 0 + vm_item = self.table.item(row_index, self.columns_indices["Name"]) + while vm_item.qid != qid: + row_index += 1 + vm_item = self.table.item(row_index, self.columns_indices["Name"]) + + + self.table.removeRow(row_index) + self.table.update() + del self.vms_in_table[qid] + def load_manager_settings(self): # visible columns self.visible_columns_count = 0 @@ -402,12 +462,12 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): # whole table needs to be redrawn (and sorted) if vm in self.qubes_app.domains: self.vms_in_table[vm.qid].update() + self.table.update() else: self.update_table() def fill_table(self): self.table.setSortingEnabled(False) - self.table.clearContents() vms_list = self.get_vms_list() vms_in_table = {} From 3a5a314d057af76de10b910136c9ee37add97635 Mon Sep 17 00:00:00 2001 From: donoban Date: Mon, 7 May 2018 21:58:22 +0200 Subject: [PATCH 06/27] Removed 'Refresh' button :) --- ui/qubemanager.ui | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/ui/qubemanager.ui b/ui/qubemanager.ui index 9a0b4ec..3adb210 100644 --- a/ui/qubemanager.ui +++ b/ui/qubemanager.ui @@ -281,7 +281,6 @@ - @@ -369,7 +368,6 @@ - @@ -818,18 +816,6 @@ Ctrl+F - - - - :/outdated.png:/outdated.png - - - Refresh qube list - - - Refresh qube list - - &Exit Qube Manager From 5b846a73cc45e222f6c46af51d2f6a4458ff41e1 Mon Sep 17 00:00:00 2001 From: donoban Date: Mon, 7 May 2018 22:21:17 +0200 Subject: [PATCH 07/27] Removed unneeded calls to table.update() --- qubesmanager/qube_manager.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index e5b6690..a572d47 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -140,7 +140,6 @@ class VmRowInTable(object): for key in properties: if key == 'state': self.update() - self.table.update() def update(self, update_size_on_disk=False): """ @@ -406,7 +405,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): break self.table.setSortingEnabled(True) - self.table.update() def OnDomainRemoved(self, manager, domain): #needs to clear cache @@ -423,7 +421,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.table.removeRow(row_index) - self.table.update() del self.vms_in_table[qid] def load_manager_settings(self): @@ -462,7 +459,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): # whole table needs to be redrawn (and sorted) if vm in self.qubes_app.domains: self.vms_in_table[vm.qid].update() - self.table.update() else: self.update_table() From 5e6c0539c2095c6ff104698cbfc92fb9e010cbe4 Mon Sep 17 00:00:00 2001 From: donoban Date: Mon, 7 May 2018 22:26:39 +0200 Subject: [PATCH 08/27] - Removed update_single_row() and add direct calls to update() (Some of them could be deleted since dbus events will handle them) - Removed update_table() and TODO refering dbus events --- qubesmanager/qube_manager.py | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index a572d47..19ddbd3 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -453,15 +453,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): def get_vms_list(self): return [vm for vm in self.qubes_app.domains] - def update_single_row(self, vm): - # this fuction should be used to update a row that already exists - # to add a row, one needs to use the update_table function - the - # whole table needs to be redrawn (and sorted) - if vm in self.qubes_app.domains: - self.vms_in_table[vm.qid].update() - else: - self.update_table() - def fill_table(self): self.table.setSortingEnabled(False) vms_list = self.get_vms_list() @@ -501,16 +492,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): def action_search_triggered(self): self.searchbox.setFocus() - def update_table(self): - self.fill_table() - # TODO: instead of manually refreshing the entire table, use dbus events - - # reapply sorting - if self.sort_by_column: - self.table.sortByColumn(self.columns_indices[self.sort_by_column]) - - self.table_selection_changed() - # noinspection PyPep8Naming def sort_indicator_changed(self, column, order): self.sort_by_column = [name for name in self.columns_indices if @@ -562,7 +543,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): vm.qid != 0 and vm.get_power_state() != "Paused" and vm.is_running()) - self.update_single_row(vm) + self.vms_in_table[vm.qid].update() else: self.action_settings.setEnabled(False) self.action_removevm.setEnabled(False) @@ -752,7 +733,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): return self.start_vm(vm) - self.update_single_row(vm) + self.vms_in_table[vm.qid].update() def start_vm(self, vm): if vm.is_running(): @@ -773,7 +754,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.tr("Error starting Qube!"), self.tr("ERROR: {0}").format(t_monitor.error_msg)) - self.update_single_row(vm) + self.vms_in_table[vm.qid].update() @staticmethod def do_start_vm(vm, t_monitor): @@ -798,7 +779,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): vm = self.get_selected_vm() try: vm.pause() - self.update_single_row(vm) + self.vms_in_table[vm.qid].update() except exc.QubesException as ex: QtGui.QMessageBox.warning( None, @@ -823,7 +804,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): if reply == QtGui.QMessageBox.Yes: self.shutdown_vm(vm) - self.update_single_row(vm) + self.vms_in_table[vm.qid].update() def shutdown_vm(self, vm, shutdown_time=vm_shutdown_timeout, check_time=vm_restart_check_timeout, and_restart=False): @@ -864,7 +845,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): else: self.start_vm(vm) - self.update_single_row(vm) + self.vms_in_table[vm.qid].update() # noinspection PyArgumentList @QtCore.pyqtSlot(name='on_action_killvm_triggered') @@ -908,7 +889,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): settings_window = settings.VMSettingsWindow( vm, self.qt_app, "basic") settings_window.exec_() - self.update_single_row(vm) + self.vms_in_table[vm.qid].update() # noinspection PyArgumentList @QtCore.pyqtSlot(name='on_action_appmenus_triggered') @@ -950,7 +931,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.tr("Error on Qube update!"), self.tr("ERROR: {0}").format(t_monitor.error_msg)) - self.update_single_row(vm) + self.vms_in_table[vm.qid].update() @staticmethod def do_update_vm(vm, t_monitor): From bfc54b779fdf2017b1f2c8bdf5cea9f83ac1a926 Mon Sep 17 00:00:00 2001 From: donoban Date: Mon, 7 May 2018 22:50:13 +0200 Subject: [PATCH 09/27] - Removed unnedeed calls to vms_in_table[vm.qid].update() - Fixed unpause case where it was not properly updated --- qubesmanager/qube_manager.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 19ddbd3..e4e9e29 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -542,8 +542,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.action_set_keyboard_layout.setEnabled( vm.qid != 0 and vm.get_power_state() != "Paused" and vm.is_running()) - - self.vms_in_table[vm.qid].update() else: self.action_settings.setEnabled(False) self.action_removevm.setEnabled(False) @@ -726,6 +724,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): if vm.get_power_state() in ["Paused", "Suspended"]: try: vm.unpause() + self.vms_in_table[vm.qid].update() except exc.QubesException as ex: QtGui.QMessageBox.warning( None, self.tr("Error unpausing Qube!"), @@ -733,7 +732,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): return self.start_vm(vm) - self.vms_in_table[vm.qid].update() def start_vm(self, vm): if vm.is_running(): @@ -754,7 +752,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.tr("Error starting Qube!"), self.tr("ERROR: {0}").format(t_monitor.error_msg)) - self.vms_in_table[vm.qid].update() @staticmethod def do_start_vm(vm, t_monitor): @@ -804,7 +801,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): if reply == QtGui.QMessageBox.Yes: self.shutdown_vm(vm) - self.vms_in_table[vm.qid].update() def shutdown_vm(self, vm, shutdown_time=vm_shutdown_timeout, check_time=vm_restart_check_timeout, and_restart=False): @@ -845,8 +841,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): else: self.start_vm(vm) - self.vms_in_table[vm.qid].update() - # noinspection PyArgumentList @QtCore.pyqtSlot(name='on_action_killvm_triggered') def action_killvm_triggered(self): @@ -931,7 +925,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.tr("Error on Qube update!"), self.tr("ERROR: {0}").format(t_monitor.error_msg)) - self.vms_in_table[vm.qid].update() @staticmethod def do_update_vm(vm, t_monitor): From 5440384142df3caed9f9f0550b72b3f725d472e8 Mon Sep 17 00:00:00 2001 From: donoban Date: Mon, 7 May 2018 23:19:15 +0200 Subject: [PATCH 10/27] Set settings dialog to minimun size, it gets adjusted properly to good view fix https://github.com/QubesOS/qubes-issues/issues/3825 --- ui/settingsdlg.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/settingsdlg.ui b/ui/settingsdlg.ui index 61cfa0f..f676cad 100644 --- a/ui/settingsdlg.ui +++ b/ui/settingsdlg.ui @@ -6,8 +6,8 @@ 0 0 - 1587 - 861 + 100 + 100 From 027d106507380733d26e4152ff21f91d0925903a Mon Sep 17 00:00:00 2001 From: donoban Date: Wed, 9 May 2018 11:31:44 +0200 Subject: [PATCH 11/27] VmRowInTable dbus events moved to VmManagerWindow Since we need to do some updates affecting all vms or the Window itself, this is a better place for handling this. --- qubesmanager/qube_manager.py | 50 ++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index e4e9e29..2e2b6ea 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -131,16 +131,6 @@ class VmRowInTable(object): self.table = table - #Connect dbus events - bus = SessionBus() - self.dbus = bus.get("org.qubes.DomainManager1" , "/org/qubes/DomainManager1/domains/" + str(vm.qid)) - self.dbus.PropertiesChanged.connect(self.OnPropertiesChanged) - - def OnPropertiesChanged(self, dbus, properties, dump): - for key in properties: - if key == 'state': - self.update() - def update(self, update_size_on_disk=False): """ Update info in a single VM row @@ -382,10 +372,16 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.update_size_on_disk = False self.shutdown_monitor = {} + # Connect dbus events bus = SessionBus() manager = bus.get("org.qubes.DomainManager1") manager.DomainAdded.connect(self.OnDomainAdded) manager.DomainRemoved.connect(self.OnDomainRemoved) + manager.Failed.connect(self.OnFailed) + manager.Halted.connect(self.OnHalted) + manager.Halting.connect(self.OnHalting) + manager.Starting.connect(self.OnStarting) + manager.Started.connect(self.OnStarted) def OnDomainAdded(self, manager, domain): #needs to clear cache @@ -423,6 +419,40 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.table.removeRow(row_index) del self.vms_in_table[qid] + def OnFailed(self, manager, domain): + qid = int(domain.split('/')[-1]) + self.vms_in_table[qid].update() + + def OnHalted(self, manager, domain): + qid = int(domain.split('/')[-1]) + self.vms_in_table[qid].update() + + # Check if is TemplatVM and update related AppVMs + starting_vm = self.vms_in_table[qid] + if starting_vm.vm.klass == 'TemplateVM': + for vm in starting_vm.vm.appvms: + if vm.klass == 'AppVM': + self.vms_in_table[vm.qid].update() + + def OnHalting(self, manager, domain): + qid = int(domain.split('/')[-1]) + self.vms_in_table[qid].update() + + def OnStarted(self, manager, domain): + qid = int(domain.split('/')[-1]) + self.vms_in_table[qid].update() + + def OnStarting(self, manager, domain): + qid = int(domain.split('/')[-1]) + self.vms_in_table[qid].update() + + # Check if is TemplatVM and update related AppVMs + starting_vm = self.vms_in_table[qid] + if starting_vm.vm.klass == 'TemplateVM': + for vm in starting_vm.vm.appvms: + if vm.klass == 'AppVM': + self.vms_in_table[vm.qid].update() + def load_manager_settings(self): # visible columns self.visible_columns_count = 0 From e2e66cbccba4fca25470db2d930c95937fb43915 Mon Sep 17 00:00:00 2001 From: donoban Date: Wed, 9 May 2018 11:48:19 +0200 Subject: [PATCH 12/27] Added calls to table_selection_changed() If row updated is the selected row we need to update start/pause/stop buttons --- qubesmanager/qube_manager.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 2e2b6ea..648aead 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -423,10 +423,16 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() + if self.vms_in_table[qid].vm == self.get_selected_vm(): + self.table_selection_changed() + def OnHalted(self, manager, domain): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() + if self.vms_in_table[qid].vm == self.get_selected_vm(): + self.table_selection_changed() + # Check if is TemplatVM and update related AppVMs starting_vm = self.vms_in_table[qid] if starting_vm.vm.klass == 'TemplateVM': @@ -438,14 +444,23 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() + if self.vms_in_table[qid].vm == self.get_selected_vm(): + self.table_selection_changed() + def OnStarted(self, manager, domain): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() + if self.vms_in_table[qid].vm == self.get_selected_vm(): + self.table_selection_changed() + def OnStarting(self, manager, domain): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() + if self.vms_in_table[qid].vm == self.get_selected_vm(): + self.table_selection_changed() + # Check if is TemplatVM and update related AppVMs starting_vm = self.vms_in_table[qid] if starting_vm.vm.klass == 'TemplateVM': From bc07e3726635f08e0576e61b3dd8399ef50497f7 Mon Sep 17 00:00:00 2001 From: donoban Date: Wed, 9 May 2018 12:05:07 +0200 Subject: [PATCH 13/27] Refresh table selection when pause/resume Since them dont have dbus events we need to manually update the selection --- qubesmanager/qube_manager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 648aead..32fd841 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -770,6 +770,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): try: vm.unpause() self.vms_in_table[vm.qid].update() + self.table_selection_changed() except exc.QubesException as ex: QtGui.QMessageBox.warning( None, self.tr("Error unpausing Qube!"), @@ -822,6 +823,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): try: vm.pause() self.vms_in_table[vm.qid].update() + self.table_selection_changed() except exc.QubesException as ex: QtGui.QMessageBox.warning( None, From 806915f83454951444d2bcad91b9073d6be56b53 Mon Sep 17 00:00:00 2001 From: donoban Date: Wed, 9 May 2018 14:36:39 +0200 Subject: [PATCH 14/27] Added Timer for template updates Since there is no template updates dbus events, we need to check it periodically --- qubesmanager/qube_manager.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 32fd841..33c542a 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -383,6 +383,17 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): manager.Starting.connect(self.OnStarting) manager.Started.connect(self.OnStarted) + # Check Updates Timer + timer = QtCore.QTimer(self) + timer.timeout.connect(self.CheckUpdates) + timer.start(1000 * 60 * 5) # 5mins + + def CheckUpdates(self): + print("Checking updates") + for vm in self.qubes_app.domains: + if vm.klass == 'TempateVM': + self.vms_in_table[vm.qid].update() + def OnDomainAdded(self, manager, domain): #needs to clear cache self.qubes_app.domains.clear_cache() From ce07b9dcb1739526768554e684bebb967a01422d Mon Sep 17 00:00:00 2001 From: donoban Date: Wed, 9 May 2018 14:37:46 +0200 Subject: [PATCH 15/27] This tries to fix some rare case when it stops receieving dbus events --- qubesmanager/qube_manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 33c542a..b5aa125 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -373,8 +373,8 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.shutdown_monitor = {} # Connect dbus events - bus = SessionBus() - manager = bus.get("org.qubes.DomainManager1") + self.bus = SessionBus() + manager = self.bus.get("org.qubes.DomainManager1") manager.DomainAdded.connect(self.OnDomainAdded) manager.DomainRemoved.connect(self.OnDomainRemoved) manager.Failed.connect(self.OnFailed) From e2fccf592a1a42b1db18814a620c77dec215093d Mon Sep 17 00:00:00 2001 From: donoban Date: Wed, 9 May 2018 15:50:39 +0200 Subject: [PATCH 16/27] Revert "Removed progress wait when updating template" This reverts commit 9633f6e9c63b4d667957a4751b00afefb0084682. --- qubesmanager/qube_manager.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index b5aa125..ed73ee0 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -976,6 +976,20 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): thread.daemon = True thread.start() + progress = QtGui.QProgressDialog( + self.tr( + "{0}
Please wait for the updater to " + "launch...").format(vm.name), "", 0, 0) + progress.setCancelButton(None) + progress.setModal(True) + progress.show() + + while not t_monitor.is_finished(): + self.qt_app.processEvents() + time.sleep(0.2) + + progress.hide() + if vm.qid != 0: if not t_monitor.success: QtGui.QMessageBox.warning( From 224c8708fcb8662576368306e62bc877607951bb Mon Sep 17 00:00:00 2001 From: donoban Date: Wed, 9 May 2018 19:39:41 +0200 Subject: [PATCH 17/27] Outdated state cleanup Fixes problems showing 'outdated' instead 'to-be-outdated' when template is running Fixes the removal of the icon calling setVisible(False) before removeWidget() --- qubesmanager/table_widgets.py | 49 ++++++++++++++++------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/qubesmanager/table_widgets.py b/qubesmanager/table_widgets.py index d92ec0e..f2b7bc6 100644 --- a/qubesmanager/table_widgets.py +++ b/qubesmanager/table_widgets.py @@ -376,24 +376,25 @@ class VmUpdateInfoWidget(QtGui.QWidget): self.update_outdated() def update_outdated(self): + outdated_state = False + if self.vm.is_running(): - outdated_state = False - - for vol in self.vm.volumes.values(): - if vol.is_outdated(): - outdated_state = "outdated" - break - - if not outdated_state and getattr(self.vm, 'template', None)\ - and self.vm.template.is_running(): + if hasattr(self.vm, 'template') and self.vm.template.is_running(): outdated_state = "to-be-outdated" - if outdated_state != self.previous_outdated_state: - self.update_status_widget(outdated_state) - self.previous_outdated_state = outdated_state - else: - outdated_state = False + + if not outdated_state: + for vol in self.vm.volumes.values(): + if vol.is_outdated(): + outdated_state = "outdated" + break + + self.update_status_widget(outdated_state) def update_status_widget(self, state): + if state == self.previous_outdated_state: + return + + self.previous_outdated_state = state self.value = state self.table_item.set_value(state) if state == "update": @@ -413,22 +414,18 @@ class VmUpdateInfoWidget(QtGui.QWidget): "The Template must be stopped before changes from its " "current session can be picked up by this qube.") else: - label_text = "" icon_path = None - tooltip_text = None - if self.show_text: - self.label.setText(label_text) - else: + if hasattr(self, 'icon'): + self.icon.setVisible(False) self.layout().removeWidget(self.icon) - self.icon.deleteLater() - if icon_path is not None: - self.icon = VmIconWidget(icon_path, True, 0.7) - self.icon.setToolTip(tooltip_text) - else: - self.icon = QtGui.QLabel(label_text) - self.layout().addWidget(self.icon, alignment=QtCore.Qt.AlignCenter) + del self.icon + if icon_path is not None: + self.icon = VmIconWidget(icon_path, True, 0.7) + self.icon.setToolTip(tooltip_text) + self.layout().addWidget(self.icon, alignment=QtCore.Qt.AlignCenter) + self.icon.setVisible(True) class VmSizeOnDiskItem(QtGui.QTableWidgetItem): def __init__(self, vm): From 1dcfc6e634e1669ad2fa399bb70f31e6eedf08e8 Mon Sep 17 00:00:00 2001 From: donoban Date: Wed, 9 May 2018 19:42:45 +0200 Subject: [PATCH 18/27] Removed debug print --- qubesmanager/qube_manager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index ed73ee0..20a8f8c 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -389,7 +389,6 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): timer.start(1000 * 60 * 5) # 5mins def CheckUpdates(self): - print("Checking updates") for vm in self.qubes_app.domains: if vm.klass == 'TempateVM': self.vms_in_table[vm.qid].update() From d54ba5b8cf1091d81424c25b461e817d3bac1d12 Mon Sep 17 00:00:00 2001 From: donoban Date: Wed, 9 May 2018 19:56:43 +0200 Subject: [PATCH 19/27] More elegant fix for settings size Is the exact minimum size it can get --- ui/settingsdlg.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/settingsdlg.ui b/ui/settingsdlg.ui index f676cad..b9ea296 100644 --- a/ui/settingsdlg.ui +++ b/ui/settingsdlg.ui @@ -6,8 +6,8 @@ 0 0 - 100 - 100 + 680 + 656
From 78ba3057eb2f59e7f17233c4378e842ba888cbb1 Mon Sep 17 00:00:00 2001 From: donoban Date: Thu, 10 May 2018 09:49:22 +0200 Subject: [PATCH 20/27] Added startup progress dialog --- qubesmanager/qube_manager.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 20a8f8c..75790ee 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -509,6 +509,14 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): return [vm for vm in self.qubes_app.domains] def fill_table(self): + progress = QtGui.QProgressDialog( + self.tr( + "Loading Qube Manager..."), "", 0, 0) + progress.setWindowTitle(self.tr("Qube Manager")) + progress.setCancelButton(None) + progress.setModal(True) + progress.show() + self.table.setSortingEnabled(False) vms_list = self.get_vms_list() @@ -521,11 +529,15 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): vm_row = VmRowInTable(vm, row_no, self.table) vms_in_table[vm.qid] = vm_row row_no += 1 + if row_no % 5 == 0: + self.qt_app.processEvents() self.vms_list = vms_list self.vms_in_table = vms_in_table self.table.setSortingEnabled(True) + progress.hide() + def showhide_vms(self): if not self.search: for row_no in range(self.table.rowCount()): @@ -1268,7 +1280,6 @@ def main(): qubes_app = Qubes() manager_window = VmManagerWindow(qt_app, qubes_app) - manager_window.show() qt_app.exec_() From a77cc5172dc94e5d06862a89529ce60f5df93bd5 Mon Sep 17 00:00:00 2001 From: donoban Date: Thu, 10 May 2018 10:04:17 +0200 Subject: [PATCH 21/27] Fix missing template updates-available --- qubesmanager/table_widgets.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qubesmanager/table_widgets.py b/qubesmanager/table_widgets.py index f2b7bc6..48a2f43 100644 --- a/qubesmanager/table_widgets.py +++ b/qubesmanager/table_widgets.py @@ -388,6 +388,9 @@ class VmUpdateInfoWidget(QtGui.QWidget): outdated_state = "outdated" break + elif self.vm.klass == 'TemplateVM' and self.vm.features.get('updates-available', False): + outdated_state = 'update' + self.update_status_widget(outdated_state) def update_status_widget(self, state): From c43a47019ebdf8c48964c59dfe58f85548b14e12 Mon Sep 17 00:00:00 2001 From: donoban Date: Thu, 10 May 2018 17:59:07 +0200 Subject: [PATCH 22/27] Added missing updates() method for some widget internal, ip, include_in_backups and last_backup --- qubesmanager/qube_manager.py | 4 ++++ qubesmanager/table_widgets.py | 14 +++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 75790ee..d47ff09 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -141,6 +141,10 @@ class VmRowInTable(object): self.info_widget.update_vm_state(self.vm) self.template_widget.update() self.netvm_widget.update() + self.internal_widget.update() + self.ip_widget.update() + self.include_in_backups_widget.update() + self.last_backup_widget.update() if update_size_on_disk: self.size_widget.update() diff --git a/qubesmanager/table_widgets.py b/qubesmanager/table_widgets.py index 48a2f43..a131d83 100644 --- a/qubesmanager/table_widgets.py +++ b/qubesmanager/table_widgets.py @@ -317,10 +317,13 @@ class VmInternalItem(QtGui.QTableWidgetItem): self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) self.vm = vm - self.internal = vm.features.get('internal', False) + self.update() + def update(self): + self.internal = self.vm.features.get('internal', False) self.setText("Yes" if self.internal else "") + def __lt__(self, other): if self.vm.qid == 0: return True @@ -464,6 +467,9 @@ class VmIPItem(QtGui.QTableWidgetItem): self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) self.vm = vm + self.update() + + def update(self): self.ip = getattr(self.vm, 'ip', None) self.setText(self.ip if self.ip is not None else 'n/a') @@ -481,6 +487,9 @@ class VmIncludeInBackupsItem(QtGui.QTableWidgetItem): self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) self.vm = vm + self.update() + + def update(self): if getattr(self.vm, 'include_in_backups', None): self.setText("Yes") else: @@ -502,6 +511,9 @@ class VmLastBackupItem(QtGui.QTableWidgetItem): self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) self.vm = vm + self.update() + + def update(self): self.backup_timestamp = getattr(self.vm, 'backup_timestamp', None) if self.backup_timestamp: From edbc4c44699295c81fac1cdc617ae0ea469e4cf2 Mon Sep 17 00:00:00 2001 From: donoban Date: Fri, 11 May 2018 10:27:19 +0200 Subject: [PATCH 23/27] Fix misspelling on Updates Timer() and better timeout This func is pretty cheap, less than 0.1ms adding two calls to print(time) so I think 30s is a reasonable timeout and better for user experience --- qubesmanager/qube_manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index d47ff09..6e75bcb 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -390,11 +390,11 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): # Check Updates Timer timer = QtCore.QTimer(self) timer.timeout.connect(self.CheckUpdates) - timer.start(1000 * 60 * 5) # 5mins + timer.start(1000 * 30) # 30s def CheckUpdates(self): for vm in self.qubes_app.domains: - if vm.klass == 'TempateVM': + if vm.klass == 'TemplateVM': self.vms_in_table[vm.qid].update() def OnDomainAdded(self, manager, domain): From 8327e32e1f8674bc8ca9f2e653c365a23ea1206f Mon Sep 17 00:00:00 2001 From: donoban Date: Sun, 20 May 2018 21:30:50 +0200 Subject: [PATCH 24/27] Fix pylint and travis errors --- qubesmanager/qube_manager.py | 41 ++++++++++++++++++----------------- qubesmanager/table_widgets.py | 20 ++++++++++------- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 6e75bcb..3eaed7f 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -29,6 +29,8 @@ import subprocess import time from datetime import datetime, timedelta import traceback +import threading + from pydbus import SessionBus from qubesadmin import Qubes @@ -37,6 +39,8 @@ from qubesadmin import exc from PyQt4 import QtGui # pylint: disable=import-error from PyQt4 import QtCore # pylint: disable=import-error +from qubesmanager.about import AboutDialog + from . import ui_qubemanager # pylint: disable=no-name-in-module from . import thread_monitor from . import table_widgets @@ -45,9 +49,6 @@ from . import global_settings from . import restore from . import backup from . import log_dialog -import threading - -from qubesmanager.about import AboutDialog class SearchBox(QtGui.QLineEdit): @@ -138,7 +139,7 @@ class VmRowInTable(object): widget will extract the data from VM object :return: None """ - self.info_widget.update_vm_state(self.vm) + self.info_widget.update_vm_state() self.template_widget.update() self.netvm_widget.update() self.internal_widget.update() @@ -379,25 +380,25 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): # Connect dbus events self.bus = SessionBus() manager = self.bus.get("org.qubes.DomainManager1") - manager.DomainAdded.connect(self.OnDomainAdded) - manager.DomainRemoved.connect(self.OnDomainRemoved) - manager.Failed.connect(self.OnFailed) - manager.Halted.connect(self.OnHalted) - manager.Halting.connect(self.OnHalting) - manager.Starting.connect(self.OnStarting) - manager.Started.connect(self.OnStarted) + manager.DomainAdded.connect(self.onDomainAdded) + manager.DomainRemoved.connect(self.onDomainRemoved) + manager.Failed.connect(self.onFailed) + manager.Halted.connect(self.onHalted) + manager.Halting.connect(self.onHalting) + manager.Starting.connect(self.onStarting) + manager.Started.connect(self.onStarted) # Check Updates Timer timer = QtCore.QTimer(self) - timer.timeout.connect(self.CheckUpdates) + timer.timeout.connect(self.checkUpdates) timer.start(1000 * 30) # 30s - def CheckUpdates(self): + def checkUpdates(self): for vm in self.qubes_app.domains: if vm.klass == 'TemplateVM': self.vms_in_table[vm.qid].update() - def OnDomainAdded(self, manager, domain): + def onDomainAdded(self, _, domain): #needs to clear cache self.qubes_app.domains.clear_cache() qid = int(domain.split('/')[-1]) @@ -416,7 +417,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.table.setSortingEnabled(True) - def OnDomainRemoved(self, manager, domain): + def onDomainRemoved(self, _, domain): #needs to clear cache self.qubes_app.domains.clear_cache() @@ -433,14 +434,14 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.table.removeRow(row_index) del self.vms_in_table[qid] - def OnFailed(self, manager, domain): + def onFailed(self, _, domain): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() if self.vms_in_table[qid].vm == self.get_selected_vm(): self.table_selection_changed() - def OnHalted(self, manager, domain): + def onHalted(self, _, domain): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() @@ -454,21 +455,21 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): if vm.klass == 'AppVM': self.vms_in_table[vm.qid].update() - def OnHalting(self, manager, domain): + def onHalting(self, _, domain): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() if self.vms_in_table[qid].vm == self.get_selected_vm(): self.table_selection_changed() - def OnStarted(self, manager, domain): + def onStarted(self, _, domain): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() if self.vms_in_table[qid].vm == self.get_selected_vm(): self.table_selection_changed() - def OnStarting(self, manager, domain): + def onStarting(self, _, domain): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() diff --git a/qubesmanager/table_widgets.py b/qubesmanager/table_widgets.py index a131d83..9567901 100644 --- a/qubesmanager/table_widgets.py +++ b/qubesmanager/table_widgets.py @@ -18,10 +18,10 @@ # # You should have received a copy of the GNU Lesser General Public License along # with this program; if not, see . +import datetime from PyQt4 import QtGui # pylint: disable=import-error from PyQt4 import QtCore # pylint: disable=import-error -import datetime # pylint: disable=too-few-public-methods power_order = QtCore.Qt.DescendingOrder @@ -253,7 +253,7 @@ class VmInfoWidget(QtGui.QWidget): self.table_item = self.VmInfoItem(self.upd_info.table_item, vm) - def update_vm_state(self, vm): + def update_vm_state(self): self.on_icon.update() self.upd_info.update_outdated() @@ -391,7 +391,8 @@ class VmUpdateInfoWidget(QtGui.QWidget): outdated_state = "outdated" break - elif self.vm.klass == 'TemplateVM' and self.vm.features.get('updates-available', False): + elif self.vm.klass == 'TemplateVM' and \ + self.vm.features.get('updates-available', False): outdated_state = 'update' self.update_status_widget(outdated_state) @@ -427,11 +428,14 @@ class VmUpdateInfoWidget(QtGui.QWidget): self.layout().removeWidget(self.icon) del self.icon - if icon_path is not None: - self.icon = VmIconWidget(icon_path, True, 0.7) - self.icon.setToolTip(tooltip_text) - self.layout().addWidget(self.icon, alignment=QtCore.Qt.AlignCenter) - self.icon.setVisible(True) + if self.show_text: + self.label.setText(label_text) + else: + if icon_path is not None: + self.icon = VmIconWidget(icon_path, True, 0.7) + self.icon.setToolTip(tooltip_text) + self.layout().addWidget(self.icon, alignment=QtCore.Qt.AlignCenter) + self.icon.setVisible(True) class VmSizeOnDiskItem(QtGui.QTableWidgetItem): def __init__(self, vm): From b5808296bff4786b412c8bb1e2503d1a5694dac6 Mon Sep 17 00:00:00 2001 From: donoban Date: Sun, 20 May 2018 21:50:40 +0200 Subject: [PATCH 25/27] Added exceptions for domain add and remove --- qubesmanager/qube_manager.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 3eaed7f..8de2fac 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -408,28 +408,30 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): row_no = self.table.rowCount() self.table.setRowCount(row_no + 1) - for vm in self.qubes_app.domains: if vm.qid == qid: vm_row = VmRowInTable(vm, row_no, self.table) self.vms_in_table[vm.qid] = vm_row - break + self.table.setSortingEnabled(True) + return - self.table.setSortingEnabled(True) + # Never should reach here + raise RuntimeError('Added domain not found') def onDomainRemoved(self, _, domain): #needs to clear cache self.qubes_app.domains.clear_cache() - qid = int(domain.split('/')[-1]) # Find row and remove - row_index = 0 - vm_item = self.table.item(row_index, self.columns_indices["Name"]) - while vm_item.qid != qid: - row_index += 1 + try: + row_index = 0 vm_item = self.table.item(row_index, self.columns_indices["Name"]) - + while vm_item.qid != qid: + row_index += 1 + vm_item = self.table.item(row_index, self.columns_indices["Name"]) + except: + raise RuntimeError('Deleted domain not found') self.table.removeRow(row_index) del self.vms_in_table[qid] From fe6a47707465a8be28359bdde4dea8bbb99d0d6f Mon Sep 17 00:00:00 2001 From: donoban Date: Sun, 20 May 2018 22:00:34 +0200 Subject: [PATCH 26/27] Pretty confusion with regex trying to make travis happy --- qubesmanager/qube_manager.py | 33 +++++++++++++++++---------------- qubesmanager/table_widgets.py | 3 ++- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 8de2fac..9cde770 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -380,25 +380,25 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): # Connect dbus events self.bus = SessionBus() manager = self.bus.get("org.qubes.DomainManager1") - manager.DomainAdded.connect(self.onDomainAdded) - manager.DomainRemoved.connect(self.onDomainRemoved) - manager.Failed.connect(self.onFailed) - manager.Halted.connect(self.onHalted) - manager.Halting.connect(self.onHalting) - manager.Starting.connect(self.onStarting) - manager.Started.connect(self.onStarted) + manager.DomainAdded.connect(self.on_domain_added) + manager.DomainRemoved.connect(self.on_domain_removed) + manager.Failed.connect(self.on_failed) + manager.Halted.connect(self.on_halted) + manager.Halting.connect(self.on_halting) + manager.Starting.connect(self.on_starting) + manager.Started.connect(self.on_started) # Check Updates Timer timer = QtCore.QTimer(self) - timer.timeout.connect(self.checkUpdates) + timer.timeout.connect(self.check_updates) timer.start(1000 * 30) # 30s - def checkUpdates(self): + def check_updates(self): for vm in self.qubes_app.domains: if vm.klass == 'TemplateVM': self.vms_in_table[vm.qid].update() - def onDomainAdded(self, _, domain): + def on_domain_added(self, _, domain): #needs to clear cache self.qubes_app.domains.clear_cache() qid = int(domain.split('/')[-1]) @@ -408,6 +408,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): row_no = self.table.rowCount() self.table.setRowCount(row_no + 1) + for vm in self.qubes_app.domains: if vm.qid == qid: vm_row = VmRowInTable(vm, row_no, self.table) @@ -418,7 +419,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): # Never should reach here raise RuntimeError('Added domain not found') - def onDomainRemoved(self, _, domain): + def on_domain_removed(self, _, domain): #needs to clear cache self.qubes_app.domains.clear_cache() qid = int(domain.split('/')[-1]) @@ -436,14 +437,14 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): self.table.removeRow(row_index) del self.vms_in_table[qid] - def onFailed(self, _, domain): + def on_failed(self, _, domain): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() if self.vms_in_table[qid].vm == self.get_selected_vm(): self.table_selection_changed() - def onHalted(self, _, domain): + def on_halted(self, _, domain): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() @@ -457,21 +458,21 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): if vm.klass == 'AppVM': self.vms_in_table[vm.qid].update() - def onHalting(self, _, domain): + def on_halting(self, _, domain): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() if self.vms_in_table[qid].vm == self.get_selected_vm(): self.table_selection_changed() - def onStarted(self, _, domain): + def on_started(self, _, domain): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() if self.vms_in_table[qid].vm == self.get_selected_vm(): self.table_selection_changed() - def onStarting(self, _, domain): + def on_starting(self, _, domain): qid = int(domain.split('/')[-1]) self.vms_in_table[qid].update() diff --git a/qubesmanager/table_widgets.py b/qubesmanager/table_widgets.py index 9567901..5ccdb49 100644 --- a/qubesmanager/table_widgets.py +++ b/qubesmanager/table_widgets.py @@ -434,7 +434,8 @@ class VmUpdateInfoWidget(QtGui.QWidget): if icon_path is not None: self.icon = VmIconWidget(icon_path, True, 0.7) self.icon.setToolTip(tooltip_text) - self.layout().addWidget(self.icon, alignment=QtCore.Qt.AlignCenter) + self.layout().addWidget(self.icon,\ + alignment=QtCore.Qt.AlignCenter) self.icon.setVisible(True) class VmSizeOnDiskItem(QtGui.QTableWidgetItem): From 045c3bf98e3dea13a561545c390d608a8efd9f3b Mon Sep 17 00:00:00 2001 From: donoban Date: Sun, 20 May 2018 22:14:31 +0200 Subject: [PATCH 27/27] Fix long line warning --- qubesmanager/qube_manager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py index 9cde770..807311e 100644 --- a/qubesmanager/qube_manager.py +++ b/qubesmanager/qube_manager.py @@ -430,7 +430,8 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtGui.QMainWindow): vm_item = self.table.item(row_index, self.columns_indices["Name"]) while vm_item.qid != qid: row_index += 1 - vm_item = self.table.item(row_index, self.columns_indices["Name"]) + vm_item = self.table.item(row_index,\ + self.columns_indices["Name"]) except: raise RuntimeError('Deleted domain not found')