Qubes Manager with more tabular layout

This commit is contained in:
Agnieszka Kostrzewa 2012-01-22 18:45:41 +01:00
parent cfd0c6a991
commit 5600056d44
3 changed files with 737 additions and 270 deletions

View File

@ -1,36 +1,10 @@
RPMS_DIR=rpm/
VERSION := $(shell cat version)
help:
@echo "make rpms -- generate binary rpm packages"
@echo "make res -- compile resources"
@echo "make update-repo-current -- copy newly generated rpms to qubes yum repo"
@echo "make update-repo-unstable -- same, but to -testing repo"
@echo "make update-repo-installer -- copy dom0 rpms to installer repo"
rpms:
rpmbuild --define "_rpmdir $(RPMS_DIR)" -bb rpm_spec/qmgr.spec
rpm --addsign $(RPMS_DIR)/x86_64/qubes-manager*$(VERSION)*.rpm
res:
pyrcc4 -o qubesmanager/qrc_resources.py resources.qrc
pyrcc4 -o qubesmanager/resources_rc.py resources.qrc
pyuic4 -o qubesmanager/ui_mainwindow.py mainwindow.ui
pyuic4 -o qubesmanager/ui_newappvmdlg.py newappvmdlg.ui
pyuic4 -o qubesmanager/ui_editfwrulesdlg.py editfwrulesdlg.ui
pyuic4 -o qubesmanager/ui_newfwruledlg.py newfwruledlg.ui
update-repo-current:
ln -f $(RPMS_DIR)/x86_64/qubes-manager-*$(VERSION)*.rpm ../yum/current-release/current/dom0/rpm/
cd ../yum && ./update_repo.sh
update-repo-current-testing:
ln -f $(RPMS_DIR)/x86_64/qubes-manager-*$(VERSION)*.rpm ../yum/current-release/current-testing/dom0/rpm/
cd ../yum && ./update_repo.sh
update-repo-unstable:
ln -f $(RPMS_DIR)/x86_64/qubes-manager-*$(VERSION)*.rpm ../yum/current-release/unstable/dom0/rpm/
cd ../yum && ./update_repo.sh
update-repo-installer:
ln -f $(RPMS_DIR)/x86_64/qubes-manager-*$(VERSION)*.rpm ../installer/yum/qubes-dom0/rpm/
clean:

494
mainwindow.ui Normal file
View File

@ -0,0 +1,494 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>VmManagerWindow</class>
<widget class="QMainWindow" name="VmManagerWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>821</width>
<height>600</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QTableWidget" name="table">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>150</width>
<height>50</height>
</size>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="showGrid">
<bool>true</bool>
</property>
<property name="gridStyle">
<enum>Qt::DashLine</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<property name="rowCount">
<number>4</number>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>150</number>
</attribute>
<attribute name="horizontalHeaderMinimumSectionSize">
<number>150</number>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<row>
<property name="text">
<string>Nowy wiersz</string>
</property>
</row>
<row/>
<row/>
<row/>
<column>
<property name="text">
<string>Name</string>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="background">
<color>
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</property>
</column>
<column>
<property name="text">
<string>Template</string>
</property>
</column>
<column>
<property name="text">
<string>NetVM</string>
</property>
</column>
<column>
<property name="text">
<string>CPU</string>
</property>
</column>
<column>
<property name="text">
<string>CPU Graph</string>
</property>
</column>
<column>
<property name="text">
<string>MEM</string>
</property>
</column>
<column>
<property name="text">
<string>MEM Graph</string>
</property>
</column>
<column>
<property name="text">
<string>Update Info</string>
</property>
</column>
<column>
<property name="text">
<string>Block Devices</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>821</width>
<height>23</height>
</rect>
</property>
<widget class="QMenu" name="menuOptions">
<property name="title">
<string>Options</string>
</property>
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>View</string>
</property>
<widget class="QMenu" name="menuColumns_visibility">
<property name="title">
<string>Columns visibility</string>
</property>
<addaction name="actionTemplate"/>
<addaction name="actionNetVM"/>
<addaction name="actionCPU"/>
<addaction name="actionCPU_Graph"/>
<addaction name="actionMEM"/>
<addaction name="actionMEM_Graph"/>
<addaction name="actionUpdate_Info"/>
<addaction name="actionBlock_Devices"/>
</widget>
<addaction name="menuColumns_visibility"/>
</widget>
<addaction name="menuOptions"/>
<addaction name="menuView"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<property name="floatable">
<bool>false</bool>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="action_createvm"/>
<addaction name="separator"/>
<addaction name="action_removevm"/>
<addaction name="action_resumevm"/>
<addaction name="action_pausevm"/>
<addaction name="action_shutdownvm"/>
<addaction name="action_editfwrules"/>
<addaction name="action_appmenus"/>
<addaction name="action_updatevm"/>
<addaction name="separator"/>
<addaction name="action_showallvms"/>
<addaction name="action_showgraphs"/>
</widget>
<action name="action_createvm">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/createvm.png</normaloff>:/createvm.png</iconset>
</property>
<property name="text">
<string>Create AppVM</string>
</property>
<property name="toolTip">
<string>Create a new AppVM</string>
</property>
</action>
<action name="action_removevm">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/removevm.png</normaloff>:/removevm.png</iconset>
</property>
<property name="text">
<string>remove AppVM</string>
</property>
<property name="toolTip">
<string>Remove an existing AppVM (must be stopped first)</string>
</property>
</action>
<action name="action_resumevm">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/resumevm.png</normaloff>:/resumevm.png</iconset>
</property>
<property name="text">
<string>Start/Resume VM</string>
</property>
<property name="toolTip">
<string>Start/Resume a VM</string>
</property>
</action>
<action name="action_pausevm">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/pausevm.png</normaloff>:/pausevm.png</iconset>
</property>
<property name="text">
<string>Pause VM</string>
</property>
<property name="toolTip">
<string>Pause a running VM</string>
</property>
</action>
<action name="action_shutdownvm">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/shutdownvm.png</normaloff>:/shutdownvm.png</iconset>
</property>
<property name="text">
<string>Shutdown VM</string>
</property>
<property name="toolTip">
<string>Shutdown a running VM</string>
</property>
</action>
<action name="action_appmenus">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/root.png</normaloff>:/root.png</iconset>
</property>
<property name="text">
<string>Select VM applications</string>
</property>
<property name="toolTip">
<string>Select applications present in menu for this VM</string>
</property>
</action>
<action name="action_updatevm">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/updateable.png</normaloff>:/updateable.png</iconset>
</property>
<property name="text">
<string>Update VM</string>
</property>
<property name="toolTip">
<string>Update VM system</string>
</property>
</action>
<action name="action_showallvms">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="icon">
<iconset>
<selectedoff>:/showallvms.png</selectedoff>
</iconset>
</property>
<property name="text">
<string>Show/Hide inactive VMs</string>
</property>
<property name="toolTip">
<string>Show/Hide inactive VMs</string>
</property>
</action>
<action name="action_editfwrules">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/firewall.png</normaloff>:/firewall.png</iconset>
</property>
<property name="text">
<string>Edit VM Firewall rules</string>
</property>
<property name="toolTip">
<string>Edit VM Firewall rules</string>
</property>
</action>
<action name="action_showgraphs">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/showcpuload.png</normaloff>:/showcpuload.png</iconset>
</property>
<property name="text">
<string>Show graphs</string>
</property>
<property name="toolTip">
<string>Show Graphs</string>
</property>
</action>
<action name="actionOptions">
<property name="text">
<string>Options</string>
</property>
</action>
<action name="actionView">
<property name="text">
<string>View</string>
</property>
</action>
<action name="actionCPU">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>CPU</string>
</property>
</action>
<action name="actionCPU_Graph">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>CPU Graph</string>
</property>
</action>
<action name="actionMEM">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>MEM</string>
</property>
</action>
<action name="actionMEM_Graph">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>MEM Graph</string>
</property>
</action>
<action name="actionTemplate">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Template</string>
</property>
</action>
<action name="actionNetVM">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>NetVM</string>
</property>
</action>
<action name="actionBlock_Devices">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Block Devices</string>
</property>
</action>
<action name="actionUpdate_Info">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Update Info</string>
</property>
</action>
</widget>
<resources>
<include location="resources.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -37,6 +37,7 @@ from qubes import qubesutils
import qubesmanager.qrc_resources
import ui_newappvmdlg
from ui_mainwindow import *
from appmenu_select import AppmenuSelectWindow
from firewall import EditFwRulesDlg, QubesFirewallRulesModel
@ -102,132 +103,114 @@ class VmInfoWidget (QWidget):
def __init__(self, vm, parent = None):
super (VmInfoWidget, self).__init__(parent)
layout0 = QHBoxLayout()
layout = QHBoxLayout ()
self.label_name = QLabel (vm.name)
self.vm_running = vm.last_power_state
layout0.addWidget(self.label_name, alignment=Qt.AlignLeft)
layout1 = QHBoxLayout()
if vm.template_vm is not None:
self.label_tmpl = QLabel ("<i><font color=\"gray\">" + (vm.template_vm.name) + "</i></font>")
elif vm.is_appvm(): # and vm.template_vm is None
self.label_tmpl = QLabel ("<i><font color=\"gray\">StandaloneVM</i></font>")
elif vm.is_template():
self.label_tmpl = QLabel ("<i><font color=\"gray\">TemplateVM</i></font>")
elif vm.qid == 0:
self.label_tmpl = QLabel ("<i><font color=\"gray\">AdminVM</i></font>")
elif vm.is_netvm():
self.label_tmpl = QLabel ("<i><font color=\"gray\">NetVM</i></font>")
else:
self.label_tmpl = QLabel ("")
label_icon_networked = self.set_icon(":/networking.png", vm.is_networked())
layout1.addWidget(label_icon_networked, alignment=Qt.AlignLeft)
if vm.is_updateable():
label_icon_updtbl = self.set_icon(":/updateable.png", True)
layout1.addWidget(label_icon_updtbl, alignment=Qt.AlignLeft)
layout1.addWidget(self.label_tmpl, alignment=Qt.AlignLeft)
layout1.addStretch()
layout2 = QVBoxLayout ()
layout2.addLayout(layout0)
layout2.addLayout(layout1)
layout3 = QHBoxLayout ()
self.vm_icon = VmStatusIcon(vm)
layout3.addWidget(self.vm_icon)
layout3.addSpacing (10)
layout3.addLayout(layout2)
self.setLayout(layout3)
layout.addWidget(self.vm_icon)
layout.addSpacing (10)
layout.addWidget(self.label_name, alignment=Qt.AlignLeft)
self.previous_outdated = False
self.previous_update_recommended = False
def set_icon(self, icon_path, enabled = True):
label_icon = QLabel()
icon = QIcon (icon_path)
icon_sz = QSize (VmManagerWindow.row_height * 0.3, VmManagerWindow.row_height * 0.3)
icon_pixmap = icon.pixmap(icon_sz, QIcon.Disabled if not enabled else QIcon.Normal)
label_icon.setPixmap (icon_pixmap)
label_icon.setFixedSize (icon_sz)
return label_icon
self.setLayout(layout)
def update_vm_state (self, vm):
self.vm_icon.update()
def update_outdated(self, vm):
outdated = vm.is_outdated()
if outdated != self.previous_outdated:
if outdated:
self.label_name.setText(vm.name + "<small><font color=\"red\"> (outdated)</font></small>")
else:
self.label_name.setText(vm.name)
self.previous_outdated = outdated
if vm.is_updateable():
update_recommended = self.previous_update_recommended
stat_file = vm.dir_path + '/' + updates_stat_file
if not os.path.exists(stat_file) or \
time.time() - os.path.getmtime(stat_file) > \
update_suggestion_interval * 24 * 3600:
update_recommended = True
else:
update_recommended = False
if update_recommended != self.previous_update_recommended:
if update_recommended:
self.label_name.setText(vm.name + "<small><font color=\"#CCCC00\"> (check updates)</font></small>")
else:
self.label_name.setText(vm.name)
self.previous_update_recommended = update_recommended
class VmUsageWidget (QWidget):
def __init__(self, vm, cpu_load = 0, parent = None):
super (VmUsageWidget, self).__init__(parent)
self.cpu_widget = QProgressBar()
self.mem_widget = QProgressBar()
self.cpu_widget.setMinimum(0)
self.cpu_widget.setMaximum(100)
self.mem_widget.setMinimum(0)
self.mem_widget.setMaximum(qubes_host.memory_total/1024)
self.mem_widget.setFormat ("%v MB");
self.cpu_label = QLabel("CPU")
self.mem_label = QLabel("MEM")
layout_cpu = QHBoxLayout()
layout_cpu.addWidget(self.cpu_label)
layout_cpu.addWidget(self.cpu_widget)
layout_mem = QHBoxLayout()
layout_mem.addWidget(self.mem_label)
layout_mem.addWidget(self.mem_widget)
class VmTemplateWidget (QWidget):
def __init__(self, vm, parent=None):
super(VmTemplateWidget, self).__init__(parent)
layout = QVBoxLayout()
layout.addLayout(layout_cpu)
layout.addLayout(layout_mem)
self.info_label = None
if vm.template_vm is not None:
self.label_tmpl = QLabel ("<font color=\"black\">" + (vm.template_vm.name) + "</font>")
else:
self.label_tmpl = QLabel ("<font color=\"black\">None</font>")
if vm.is_appvm(): # and vm.template_vm is None
self.info_label = QLabel ("<i><font color=\"gray\">StandaloneVM</i></font>")
elif vm.is_template():
self.info_label = QLabel ("<i><font color=\"gray\">TemplateVM</i></font>")
elif vm.qid == 0:
self.info_label = QLabel ("<i><font color=\"gray\">AdminVM</i></font>")
elif vm.is_netvm():
self.info_label = QLabel ("<i><font color=\"gray\">NetVM</i></font>")
else:
self.info_label = QLabel ("<i><font color=\"gray\">---</i></font>")
layout.addWidget(self.label_tmpl, alignment=Qt.AlignHCenter)
if self.info_label != None:
layout.addWidget(self.info_label, alignment=Qt.AlignHCenter)
self.setLayout(layout)
self.update_load(vm, cpu_load)
def update_load(self, vm, cpu_load):
self.cpu_load = cpu_load if vm.last_power_state else 0
self.mem_load = vm.get_mem()/1024 if vm.last_power_state else 0
self.cpu_widget.setValue(self.cpu_load)
self.mem_widget.setValue(self.mem_load)
class VmIconWidget (QWidget):
def __init__(self, icon_path, enabled=True, parent=None):
super(VmIconWidget, self).__init__(parent)
label_icon = QLabel()
icon = QIcon (icon_path)
icon_sz = QSize (VmManagerWindow.row_height * 0.8, VmManagerWindow.row_height * 0.3)
icon_pixmap = icon.pixmap(icon_sz, QIcon.Disabled if not enabled else QIcon.Normal)
label_icon.setPixmap (icon_pixmap)
label_icon.setFixedSize (icon_sz)
layout = QVBoxLayout()
layout.addWidget(label_icon)
self.setLayout(layout)
class VmNetvmWidget (QWidget):
def __init__(self, vm, parent=None):
super(VmNetvmWidget, self).__init__(parent)
layout = QHBoxLayout()
self.icon = VmIconWidget(":/networking.png", vm.is_networked())
if vm.is_netvm():
self.label_nvm = QLabel ("<font color=\"black\">self</font>")
elif vm.netvm_vm is not None:
self.label_nvm = QLabel ("<font color=\"black\">" + (vm.netvm_vm.name) + "</font>")
else:
self.label_nvm = QLabel ("<font color=\"black\">None</font>")
layout.addWidget(self.icon, alignment=Qt.AlignLeft)
layout.addWidget(self.label_nvm, alignment=Qt.AlignHCenter)
self.setLayout(layout)
class VmUsageBarWidget (QWidget):
def __init__(self, min, max, format, label, update_func, vm, load, parent = None):
super (VmUsageBarWidget, self).__init__(parent)
self.min = min
self.max = max
self.update_func = update_func
self.widget = QProgressBar()
self.widget.setMinimum(min)
self.widget.setMaximum(max)
self.widget.setFormat(format);
self.label = QLabel(label)
layout = QHBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.widget)
self.setLayout(layout)
self.update_load(vm, load)
def update_load(self, vm, load):
self.widget.setValue(self.update_func(vm, load))
def resizeEvent(self, Event = None):
label_width = max(self.mem_label.width(), self.cpu_label.width())
self.mem_label.setMinimumWidth(label_width)
self.cpu_label.setMinimumWidth(label_width)
super (VmUsageWidget, self).resizeEvent(Event)
class LoadChartWidget (QWidget):
@ -313,6 +296,54 @@ class MemChartWidget (QWidget):
p.drawLine (W - i*dx - dx, H , W - i*dx - dx, H - (H - 5) * val/100)
class VmUpdateInfoWidget(QWidget):
def __init__(self, vm, parent = None):
super (VmUpdateInfoWidget, self).__init__(parent)
layout = QVBoxLayout ()
self.label = QLabel("")
layout.addWidget(self.label)
if vm.is_updateable():
self.updateable_widget = VmIconWidget(":/updateable.png", True)
layout.addWidget(self.updateable_widget, alignment=Qt.AlignHCenter)
self.setLayout(layout)
self.previous_outdated = False
self.previous_update_recommended = False
def update_outdated(self, vm):
outdated = vm.is_outdated()
if outdated and not self.previous_outdated:
self.label.setText("<b><font color=\"red\"> (outdated)</font></b>")
self.previous_outdated = outdated
if vm.is_updateable():
update_recommended = self.previous_update_recommended
stat_file = vm.dir_path + '/' + updates_stat_file
if not os.path.exists(stat_file) or \
time.time() - os.path.getmtime(stat_file) > \
update_suggestion_interval * 24 * 3600:
update_recommended = True
else:
update_recommended = False
if update_recommended and not self.previous_update_recommended:
self.label.setText("<b><font color=\"#CCCC00\"> (check updates)</font></b>")
self.previous_update_recommended = update_recommended
class VmBlockDevicesWidget(QWidget):
def __init__(self, vm, parent=None):
super(VmBlockDevicesWidget, self).__init__(parent)
combo = QComboBox()
combo.addItem("USB dummy1")
combo.addItem("USB dummy2")
combo.addItem("USB dummy3")
layout = QVBoxLayout()
layout.addWidget(combo)
self.setLayout(layout)
class VmRowInTable(object):
def __init__(self, vm, row_no, table):
@ -324,23 +355,41 @@ class VmRowInTable(object):
self.info_widget = VmInfoWidget(vm)
table.setCellWidget(row_no, 0, self.info_widget)
self.usage_widget = VmUsageWidget(vm)
table.setCellWidget(row_no, 1, self.usage_widget)
self.template_widget = VmTemplateWidget(vm)
table.setCellWidget(row_no, 1, self.template_widget)
self.netvm_widget = VmNetvmWidget(vm)
table.setCellWidget(row_no, 2, self.netvm_widget)
self.cpu_usage_widget = VmUsageBarWidget(0, 100, "", "CPU",
lambda vm, val: val if vm.last_power_state else 0, vm, 0)
table.setCellWidget(row_no, 3, self.cpu_usage_widget)
self.load_widget = LoadChartWidget(vm)
table.setCellWidget(row_no, 2, self.load_widget)
table.setCellWidget(row_no, 4, self.load_widget)
self.mem_usage_widget = VmUsageBarWidget(0, qubes_host.memory_total/1024, "%v MB", "MEM",
lambda vm, val: vm.get_mem()/1024 if vm.last_power_state else 0, vm, 0)
table.setCellWidget(row_no, 5, self.mem_usage_widget)
self.mem_widget = MemChartWidget(vm)
table.setCellWidget(row_no, 3, self.mem_widget)
table.setCellWidget(row_no, 6, self.mem_widget)
self.updateinfo_widget = VmUpdateInfoWidget(vm)
table.setCellWidget(row_no, 7, self.updateinfo_widget)
self.blockdevices_widget = VmBlockDevicesWidget(vm)
table.setCellWidget(row_no, 8, self.blockdevices_widget)
def update(self, counter, cpu_load = None):
self.info_widget.update_vm_state(self.vm)
if cpu_load is not None:
self.usage_widget.update_load(self.vm, cpu_load)
self.cpu_usage_widget.update_load(self.vm, cpu_load)
self.mem_usage_widget.update_load(self.vm, None)
self.load_widget.update_load(self.vm, cpu_load)
self.mem_widget.update_load(self.vm)
self.info_widget.update_outdated(self.vm)
self.updateinfo_widget.update_outdated(self.vm)
class NewAppVmDlg (QDialog, ui_newappvmdlg.Ui_NewAppVMDlg):
def __init__(self, parent = None):
@ -388,100 +437,40 @@ class ThreadMonitor(QObject):
self.event_finished.set()
class VmManagerWindow(QMainWindow):
columns_widths = [250, 200, 150, 150]
class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
row_height = 50
max_visible_rows = 14
update_interval = 1000 # in msec
show_inactive_vms = True
columns_states = { 0: [0, 1], 1: [0, 2, 3] }
columns_indices = { "Name": 0,
"Template": 1,
"NetVM": 2,
"CPU": 3,
"CPU Graph": 4,
"MEM": 5,
"MEM Graph": 6,
"Update Info": 7,
"Block Device": 8 }
def __init__(self, parent=None):
super(VmManagerWindow, self).__init__(parent)
self.action_createvm = self.createAction ("Create AppVM", slot=self.create_appvm,
icon="createvm", tip="Create a new AppVM")
self.action_removevm = self.createAction ("Remove AppVM", slot=self.remove_appvm,
icon="removevm", tip="Remove an existing AppVM (must be stopped first)")
self.action_resumevm = self.createAction ("Start/Resume VM", slot=self.resume_vm,
icon="resumevm", tip="Start/Resume a VM")
self.action_pausevm = self.createAction ("Pause VM", slot=self.pause_vm,
icon="pausevm", tip="Pause a running VM")
self.action_shutdownvm = self.createAction ("Shutdown VM", slot=self.shutdown_vm,
icon="shutdownvm", tip="Shutdown a running VM")
self.action_appmenus = self.createAction ("Select VM applications", slot=self.appmenus_select,
icon="root", tip="Select applications present in menu for this VM")
self.action_updatevm = self.createAction ("Update VM", slot=self.update_vm,
icon="updateable", tip="Update VM system")
self.action_showallvms = self.createAction ("Show/Hide Inactive VMs", slot=self.toggle_inactive_view, checkable=True,
icon="showallvms", tip="Show/Hide Inactive VMs")
self.action_showcpuload = self.createAction ("Show/Hide CPU Load chart", slot=self.showcpuload, checkable=True,
icon="showcpuload", tip="Show/Hide CPU Load chart")
self.action_editfwrules = self.createAction ("Edit VM Firewall rules", slot=self.edit_fw_rules,
icon="firewall", tip="Edit VM Firewall rules")
self.action_removevm.setDisabled(True)
self.action_resumevm.setDisabled(True)
self.action_pausevm.setDisabled(True)
self.action_shutdownvm.setDisabled(True)
self.action_appmenus.setDisabled(True)
self.action_updatevm.setDisabled(True)
self.action_showallvms.setChecked(self.show_inactive_vms)
self.toolbar = self.addToolBar ("Toolbar")
self.toolbar.setFloatable(False)
self.addActions (self.toolbar, (self.action_createvm, self.action_removevm,
None,
self.action_resumevm, self.action_shutdownvm,
self.action_editfwrules, self.action_appmenus,
self.action_updatevm,
None,
self.action_showcpuload,
self.action_showallvms,
))
self.table = QTableWidget()
self.setCentralWidget(self.table)
self.table.clear()
self.table.setColumnCount(len(VmManagerWindow.columns_widths))
for (col, width) in enumerate (VmManagerWindow.columns_widths):
self.table.setColumnWidth (col, width)
self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch)
self.table.horizontalHeader().setResizeMode(0, QHeaderView.Fixed)
self.table.setAlternatingRowColors(True)
self.table.verticalHeader().hide()
self.table.horizontalHeader().hide()
self.table.setGridStyle(Qt.NoPen)
self.table.setSortingEnabled(False)
self.table.setSelectionBehavior(QTableWidget.SelectRows)
self.table.setSelectionMode(QTableWidget.SingleSelection)
self.__cpugraphs = self.action_showcpuload.isChecked()
self.update_table_columns()
super(VmManagerWindow, self).__init__()
self.setupUi(self)
self.toolbar = self.toolBar
self.qvm_collection = QubesVmCollection()
self.setWindowTitle("Qubes VM Manager")
self.connect(self.table, SIGNAL("itemSelectionChanged()"), self.table_selection_changed)
cur_pos = self.pos()
self.setFixedWidth (self.get_minimum_table_width())
self.table.setColumnWidth(0, 200)
self.fill_table()
self.move(cur_pos)
self.update_table_columns()
self.counter = 0
self.shutdown_monitor = {}
self.last_measure_results = {}
@ -490,41 +479,25 @@ class VmManagerWindow(QMainWindow):
def set_table_geom_height(self):
# TODO: '6' -- WTF?!
tbl_H = self.toolbar.height() + 6 + \
self.table.horizontalHeader().height() + 6
tbl_H = self.toolbar.height() + \
self.table.horizontalHeader().height() + \
self.centralwidget.layout().contentsMargins().top() +\
self.centralwidget.layout().contentsMargins().bottom()
n = self.table.rowCount();
if n > VmManagerWindow.max_visible_rows:
n = VmManagerWindow.max_visible_rows
if n > 6:
for i in range(0,n-1):
tbl_H += self.table.rowHeight(i)
else:
tbl_H += self.table.verticalHeader().height()
"""
if n > self.max_visible_rows:
n = self.max_visible_rows
for i in range (0, n):
tbl_H += self.table.rowHeight(i)
tbl_H += self.table.rowHeight(i) """
self.setFixedHeight(tbl_H)
def addActions(self, target, actions):
for action in actions:
if action is None:
target.addSeparator()
else:
target.addAction(action)
def createAction(self, text, slot=None, shortcut=None, icon=None,
tip=None, checkable=False, signal="triggered()"):
action = QAction(text, self)
if icon is not None:
action.setIcon(QIcon(":/%s.png" % icon))
if shortcut is not None:
action.setShortcut(shortcut)
if tip is not None:
action.setToolTip(tip)
action.setStatusTip(tip)
if slot is not None:
self.connect(action, SIGNAL(signal), slot)
if checkable:
action.setCheckable(True)
return action
self.setMinimumHeight(tbl_H)
def get_vms_list(self):
@ -559,7 +532,7 @@ class VmManagerWindow(QMainWindow):
return vms_to_display
def fill_table(self):
self.table.clear()
#self.table.clear()
vms_list = self.get_vms_list()
self.table.setRowCount(len(vms_list))
@ -622,14 +595,17 @@ class VmManagerWindow(QMainWindow):
QTimer.singleShot (self.update_interval, self.update_table)
def update_table_columns(self):
state = 1 if self.__cpugraphs else 0
columns = self.columns_states[state]
#for i in range(0, self.table.columnCount()):
#TODO make elegant column visibility actions
#self.table.setColumnHidden(i, False)
for i in range(0, self.table.columnCount()):
enabled = columns.count(i) > 0
self.table.setColumnHidden(i, not enabled)
width = self.table.horizontalHeader().length() +\
self.table.verticalScrollBar().width() +\
self.centralwidget.layout().contentsMargins().left() +\
self.centralwidget.layout().contentsMargins().right()
self.setMinimumWidth(self.get_minimum_table_width())
self.table.setFixedWidth( width )
self.setFixedWidth( width)
def table_selection_changed (self):
vm = self.get_selected_vm()
@ -644,13 +620,6 @@ class VmManagerWindow(QMainWindow):
self.action_editfwrules.setEnabled(vm.is_networked() and not (vm.is_netvm() and not vm.is_proxyvm()))
self.action_updatevm.setEnabled(vm.is_updateable() or vm.qid == 0)
def get_minimum_table_width(self):
tbl_W = 0
for (col, w) in enumerate(VmManagerWindow.columns_widths):
if not self.table.isColumnHidden(col):
tbl_W += w
return tbl_W
def closeEvent (self, event):
if event.spontaneous(): # There is something borked in Qt, as the logic here is inverted on X11
@ -962,6 +931,36 @@ class VmManagerWindow(QMainWindow):
if dialog.exec_():
model.apply_rules()
def showhide_collumn(self, col_num, show):
self.table.setColumnHidden( col_num, not show)
self.update_table_columns()
def on_actionTemplate_toggled(self, checked):
self.showhide_collumn( 1, checked)
def on_actionNetVM_toggled(self, checked):
self.showhide_collumn( 2, checked)
def on_actionCPU_toggled(self, checked):
self.showhide_collumn( 3, checked)
def on_actionCPU_Graph_toggled(self, checked):
self.showhide_collumn( 4, checked)
def on_actionMEM_toggled(self, checked):
self.showhide_collumn( 5, checked)
def on_actionMEM_Graph_toggled(self, checked):
self.showhide_collumn( 6, checked)
def on_actionUpdate_Info_toggled(self, checked):
self.showhide_collumn( 7, checked)
def on_actionBlock_Devices_toggled(self, checked):
self.showhide_collumn( 8, checked)
class QubesTrayIcon(QSystemTrayIcon):
def __init__(self, icon):
QSystemTrayIcon.__init__(self, icon)