diff --git a/qubesmanager/main.py b/qubesmanager/main.py
index 2f3f9f2..82ac8ed 100755
--- a/qubesmanager/main.py
+++ b/qubesmanager/main.py
@@ -22,7 +22,6 @@
#
#
-# TODO: cleanup imports
import sys
import os
import os.path
@@ -33,52 +32,20 @@ from datetime import datetime, timedelta
import traceback
from qubesadmin import Qubes
-from qubesadmin import exc
from PyQt4 import QtGui
from PyQt4 import QtCore
-from PyQt4 import Qt
-from PyQt4.QtDBus import QDBusVariant, QDBusMessage
-from PyQt4.QtDBus import QDBusConnection
-from PyQt4.QtDBus import QDBusInterface, QDBusAbstractAdaptor
-from pyinotify import WatchManager, ThreadedNotifier, EventsCodes, \
- ProcessEvent
from . import ui_vtmanager
from . import thread_monitor
from . import table_widgets
+from . import settings
+from . import global_settings
+from . import restore
+from . import backup
import threading
-# from qubes.qubes import QubesVmCollection
-# from qubes.qubes import QubesException
-# from qubes.qubes import system_path
-# from qubes.qubes import QubesDaemonPidfile
-# from qubes.qubes import QubesHost
from qubesmanager.about import AboutDialog
-# import table_widgets
-# from block import QubesBlockDevicesManager
-# from table_widgets import VmTypeWidget, VmLabelWidget, VmNameItem, \
-# VmInfoWidget, VmTemplateItem, VmNetvmItem, VmUsageBarWidget, ChartWidget, \
-# VmSizeOnDiskItem, VmInternalItem, VmIPItem, VmIncludeInBackupsItem, \
-# VmLastBackupItem
-# from qubes.qubes import QubesHVm
-# from qubes import qubesutils
-# from ui_mainwindow import *
-# from create_new_vm import NewVmDlg
-# from settings import VMSettingsWindow
-# from restore import RestoreVMsWindow
-# from backup import BackupVMsWindow
-# from global_settings import GlobalSettingsWindow
-# from networknotes import NetworkNotesDialog
-# from log_dialog import LogDialog
-
-# TODO: probably unneeded
-update_suggestion_interval = 14 # 14 days
-# TODO: probably unneeded
-dbus_object_path = '/org/qubesos/QubesManager'
-dbus_interface = 'org.qubesos.QubesManager'
-system_bus = None
-session_bus = None
# TODO: probably unneeded
@@ -88,7 +55,6 @@ class QMVmState:
AudioRecAllowed = 3
-#TODO: this is actually needed O_O
class SearchBox(QtGui.QLineEdit):
def __init__(self, parent=None):
super(SearchBox, self).__init__(parent)
@@ -107,12 +73,12 @@ class SearchBox(QtGui.QLineEdit):
class VmRowInTable(object):
- cpu_graph_hue = 210
- mem_graph_hue = 120
def __init__(self, vm, row_no, table):
self.vm = vm
self.row_no = row_no
+ # TODO: replace a million different widgets with a more generic
+ # VmFeatureWidget or VMPropertyWidget
table_widgets.row_height = VmManagerWindow.row_height
table.setRowHeight(row_no, VmManagerWindow.row_height)
@@ -147,44 +113,6 @@ class VmRowInTable(object):
table.setItem(row_no, VmManagerWindow.columns_indices['NetVM'],
self.netvm_widget)
- # self.cpu_usage_widget = table_widgets.VmUsageBarWidget(
- # 0, 100, "%v %",
- # # lambda v, val: val if v.last_running else 0,
- # lambda v, val: val,
- # vm, 0, self.cpu_graph_hue)
- # table.setCellWidget(row_no, VmManagerWindow.columns_indices['CPU'],
- # self.cpu_usage_widget)
- # table.setItem(row_no, VmManagerWindow.columns_indices['CPU'],
- # self.cpu_usage_widget.tableItem)
-
- # self.load_widget = table_widgets.ChartWidget(
- # vm,
- # lambda v, val: val if v.last_running else 0,
- # self.cpu_graph_hue, 0)
- # table.setCellWidget(row_no,
- # VmManagerWindow.columns_indices['CPU Graph'],
- # self.load_widget)
- # table.setItem(row_no, VmManagerWindow.columns_indices['CPU Graph'],
- # self.load_widget.tableItem)
-
- # self.mem_usage_widget = table_widgets.VmUsageBarWidget(
- # 0, qubes_host.memory_total / 1024, "%v MB",
- # lambda v, val: v.get_mem() / 1024,
- # vm, 0, self.mem_graph_hue)
- # table.setCellWidget(row_no, VmManagerWindow.columns_indices['MEM'],
- # self.mem_usage_widget)
- # table.setItem(row_no, VmManagerWindow.columns_indices['MEM'],
- # self.mem_usage_widget.tableItem)
- #
- # # self.mem_widget = table_widgets.ChartWidget(
- # # vm, lambda v, val: v.get_mem() * 100 / qubes_host.memory_total,
- # # self.mem_graph_hue, 0)
- # table.setCellWidget(row_no,
- # VmManagerWindow.columns_indices['MEM Graph'],
- # self.mem_widget)
- # table.setItem(row_no, VmManagerWindow.columns_indices['MEM Graph'],
- # self.mem_widget.tableItem)
-
self.size_widget = table_widgets.VmSizeOnDiskItem(vm)
table.setItem(row_no, VmManagerWindow.columns_indices['Size'],
self.size_widget)
@@ -197,7 +125,8 @@ class VmRowInTable(object):
table.setItem(row_no, VmManagerWindow.columns_indices['IP'],
self.ip_widget)
- self.include_in_backups_widget = table_widgets.VmIncludeInBackupsItem(vm)
+ self.include_in_backups_widget = \
+ table_widgets.VmIncludeInBackupsItem(vm)
table.setItem(row_no, VmManagerWindow.columns_indices[
'Backups'], self.include_in_backups_widget)
@@ -205,35 +134,26 @@ class VmRowInTable(object):
table.setItem(row_no, VmManagerWindow.columns_indices[
'Last backup'], self.last_backup_widget)
- def update(self, blk_visible=None, cpu_load=None, update_size_on_disk=False,
- rec_visible=None):
+ def update(self, update_size_on_disk=False):
"""
Update info in a single VM row
- :param blk_visible: if not None, show/hide block icon, otherwise
- don't change its visibility
- :param cpu_load: current CPU load (if applicable), in percents
:param update_size_on_disk: should disk utilization be updated? the
widget will extract the data from VM object
- :param rec_visible: if not None, show/hide mic icon, otherwise don't
- change its visibility
:return: None
"""
- self.info_widget.update_vm_state(self.vm, blk_visible, rec_visible)
- if cpu_load is not None:
- 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, None)
+ self.info_widget.update_vm_state(self.vm)
if update_size_on_disk:
self.size_widget.update()
vm_shutdown_timeout = 20000 # in msec
-vm_restart_check_timeout= 1000 # in msec
+vm_restart_check_timeout = 1000 # in msec
class VmShutdownMonitor(QtCore.QObject):
- def __init__(self, vm, shutdown_time=vm_shutdown_timeout, check_time=vm_restart_check_timeout, and_restart=False, caller=None):
+ def __init__(self, vm, shutdown_time=vm_shutdown_timeout,
+ check_time=vm_restart_check_timeout,
+ and_restart=False, caller=None):
QtCore.QObject.__init__(self)
self.vm = vm
self.shutdown_time = shutdown_time
@@ -245,6 +165,7 @@ class VmShutdownMonitor(QtCore.QObject):
def restart_vm_if_needed(self):
if self.and_restart and self.caller:
self.caller.start_vm(self.vm)
+# TODO: can i kill running vm
def check_again_later(self):
# noinspection PyTypeChecker,PyCallByClass
@@ -260,12 +181,14 @@ class VmShutdownMonitor(QtCore.QObject):
vm = self.vm
vm_is_running = vm.is_running()
vm_start_time = vm.get_start_time()
- if vm_is_running and vm_start_time and vm_start_time < self.shutdown_started:
+ if vm_is_running and vm_start_time \
+ and vm_start_time < self.shutdown_started:
if self.timeout_reached():
reply = QtGui.QMessageBox.question(
None, self.tr("VM Shutdown"),
- self.tr("The VM '{0}' hasn't shutdown within the last "
- "{1} seconds, do you want to kill it?
").format(
+ self.tr(
+ "The VM '{0}' hasn't shutdown within the last "
+ "{1} seconds, do you want to kill it?
").format(
vm.name, self.shutdown_time / 1000),
self.tr("Kill it!"),
self.tr("Wait another {0} seconds...").format(
@@ -289,26 +212,20 @@ class VmShutdownMonitor(QtCore.QObject):
self.restart_vm_if_needed()
+
class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
row_height = 30
column_width = 200
min_visible_rows = 10
- show_inactive_vms = True
- show_internal_vms = False
search = ""
# suppress saving settings while initializing widgets
settings_loaded = False
- # TODO: does this work
columns_indices = {"Type": 0,
"Label": 1,
"Name": 2,
"State": 3,
"Template": 4,
"NetVM": 5,
- # "CPU": 6, # delete
- # "CPU Graph": 7, # delete
- # "MEM": 8, # delete
- # "MEM Graph": 9, # delete
"Size": 6,
"Internal": 7,
"IP": 8,
@@ -321,18 +238,11 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
self.setupUi(self)
self.toolbar = self.toolBar
- self.manager_settings = QtCore.QSettings() #TODO use Qt settings mechanism
+ self.manager_settings = QtCore.QSettings(self)
- # self.qubes_watch = qubesutils.QubesWatch()
self.qvm_collection = qvm_collection
- # self.qubes_watch.setup_domain_watch(self.domain_state_changed_callback)
- # self.qubes_watch.setup_block_watch(self.blk_manager.block_devs_event)
- # self.blk_watch_thread = threading.Thread(
- # target=self.qubes_watch.watch_loop)
- # self.blk_watch_thread.daemon = True
- # self.blk_watch_thread.start()
- self.searchbox = SearchBox() #TODO check if this works
+ self.searchbox = SearchBox() # TODO check if this works
self.searchbox.setValidator(QtGui.QRegExpValidator(
QtCore.QRegExp("[a-zA-Z0-9-]*", QtCore.Qt.CaseInsensitive), None))
self.searchContainer.addWidget(self.searchbox)
@@ -351,8 +261,6 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
self.vms_list = []
self.vms_in_table = {}
self.reload_table = False
- self.running_vms_count = 0
- self.internal_vms_count = 0
self.vm_errors = {}
self.vm_rec = {}
@@ -369,10 +277,6 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
self.columns_indices["State"]: self.action_state,
self.columns_indices["Template"]: self.action_template,
self.columns_indices["NetVM"]: self.action_netvm,
- # self.columns_indices["CPU"]: self.action_cpu,
- # self.columns_indices["CPU Graph"]: self.action_cpu_graph,
- # self.columns_indices["MEM"]: self.action_mem,
- # self.columns_indices["MEM Graph"]: self.action_mem_graph,
self.columns_indices["Size"]: self.action_size_on_disk,
self.columns_indices["Internal"]: self.action_internal,
self.columns_indices["IP"]: self
@@ -383,12 +287,6 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
# TODO: make refresh button
self.visible_columns_count = len(self.columns_indices)
- # self.table.setColumnHidden(self.columns_indices["CPU"], True)
- # self.action_cpu.setChecked(False)
- # self.table.setColumnHidden(self.columns_indices["CPU Graph"], True)
- # self.action_cpu_graph.setChecked(False)
- # self.table.setColumnHidden(self.columns_indices["MEM Graph"], True)
- # self.action_mem_graph.setChecked(False)
self.table.setColumnHidden(self.columns_indices["Size"], True)
self.action_size_on_disk.setChecked(False)
self.table.setColumnHidden(self.columns_indices["Internal"], True)
@@ -417,11 +315,11 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
self.context_menu = QtGui.QMenu(self)
+ # TODO: check if this works, check all options
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.addMenu(self.blk_menu)
self.context_menu.addAction(self.action_toggle_audio_input)
self.context_menu.addSeparator()
@@ -463,12 +361,11 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
QtCore.SIGNAL("customContextMenuRequested(const QPoint&)"),
lambda pos: self.open_tools_context_menu(self.toolBar,
pos))
- self.connect(self.blk_menu, QtCore.SIGNAL("triggered(QAction *)"),
- self.attach_dettach_device_triggered)
self.connect(self.logs_menu, QtCore.SIGNAL("triggered(QAction *)"),
self.show_log)
- self.connect(self.searchbox, QtCore.SIGNAL("textChanged(const QString&)"),
+ self.connect(self.searchbox,
+ QtCore.SIGNAL("textChanged(const QString&)"),
self.do_search)
self.table.setContentsMargins(0, 0, 0, 0)
@@ -480,13 +377,8 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
self.connect(self.action_toolbar, QtCore.SIGNAL("toggled(bool)"),
self.showhide_toolbar)
- self.register_dbus_watches()
-
self.load_manager_settings()
- self.action_showallvms.setChecked(self.show_inactive_vms)
- self.action_showinternalvms.setChecked(self.show_internal_vms)
-
self.fill_table()
self.counter = 0
@@ -494,129 +386,39 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
self.shutdown_monitor = {}
self.last_measure_results = {}
self.last_measure_time = time.time()
- # noinspection PyCallByClass,PyTypeChecker
- # QtCore.QTimer.singleShot(self.update_interval, self.update_table)
- QubesDbusNotifyServerAdaptor(self)
-
- def load_manager_settings(self): #TODO: replace with a Qt-based settings gizmo also make it work
+ def load_manager_settings(self):
# visible columns
# self.manager_settings.beginGroup("columns")
- # for col in self.columns_indices.keys():
- # col_no = self.columns_indices[col]
- # visible = self.manager_settings.value(
- # col,
- # defaultValue=not self.table.isColumnHidden(col_no))
- # self.columns_actions[col_no].setChecked(visible)
+ for col in self.columns_indices.keys():
+ col_no = self.columns_indices[col]
+ visible = self.manager_settings.value(
+ 'columns/%s' % col,
+ defaultValue=not self.table.isColumnHidden(col_no))
+ self.columns_actions[col_no].setChecked(visible == "true")
# self.manager_settings.endGroup()
- # self.show_inactive_vms = self.manager_settings.value(
- # "view/show_inactive_vms", defaultValue=False)
- # self.show_internal_vms = self.manager_settings.value(
- # "view/show_internal_vms", defaultValue=False)
- # self.sort_by_column = str(
- # self.manager_settings.value("view/sort_column",
- # defaultValue=self.sort_by_column))
- # # self.sort_order = QtCore.Qt.SortOrder( #TODO does not seem to work
- # # self.manager_settings.value("view/sort_order",
- # # defaultValue=self.sort_order)[
- # # 0])
- # self.table.sortItems(self.columns_indices[self.sort_by_column],
- # self.sort_order)
- # if not self.manager_settings.value("view/menubar_visible",
- # defaultValue=True):
- # self.action_menubar.setChecked(False)
- # if not self.manager_settings.value("view/toolbar_visible",
- # defaultValue=True):
- # self.action_toolbar.setChecked(False)
- # x = self.manager_settings.value('position/x', defaultValue=-1)[
- # 0]
- # y = self.manager_settings.value('position/y', defaultValue=-1)[
- # 0]
- # if x != -1 or y != -1:
- # self.move(x, y)
+
+ self.sort_by_column = str(
+ self.manager_settings.value("view/sort_column",
+ defaultValue=self.sort_by_column))
+ self.sort_order = QtCore.Qt.SortOrder(
+ self.manager_settings.value("view/sort_order",
+ defaultValue=self.sort_order)[
+ 0])
+ self.table.sortItems(self.columns_indices[self.sort_by_column],
+ self.sort_order)
+ if not self.manager_settings.value("view/menubar_visible",
+ defaultValue=True):
+ self.action_menubar.setChecked(False)
+ if not self.manager_settings.value("view/toolbar_visible",
+ defaultValue=True):
+ self.action_toolbar.setChecked(False)
self.settings_loaded = True
def show(self):
super(VmManagerWindow, self).show()
self.screen_number = app.desktop().screenNumber(self)
- # def set_table_geom_size(self):
- #
- # desktop_width = app.desktop().availableGeometry(
- # self).width() - self.frame_width # might be wrong...
- # desktop_height = app.desktop().availableGeometry(
- # self).height() - self.frame_height # might be wrong...
- # desktop_height -= self.row_height # UGLY! to somehow ommit taskbar...
- #
- # w = self.table.horizontalHeader().length() + \
- # self.table.verticalScrollBar().width() + \
- # 2 * self.table.frameWidth() + 1
- #
- # h = self.table.horizontalHeader().height() + \
- # 2 * self.table.frameWidth()
- #
- # mainwindow_to_add = 0
- #
- # available_space = desktop_height
- # if self.menubar.isVisible():
- # menubar_height = (self.menubar.sizeHint().height() +
- # self.menubar.contentsMargins().top() +
- # self.menubar.contentsMargins().bottom())
- # available_space -= menubar_height
- # mainwindow_to_add += menubar_height
- # if self.toolbar.isVisible():
- # toolbar_height = (self.toolbar.sizeHint().height() +
- # self.toolbar.contentsMargins().top() +
- # self.toolbar.contentsMargins().bottom())
- # available_space -= toolbar_height
- # mainwindow_to_add += toolbar_height
- # if w >= desktop_width:
- # available_space -= self.table.horizontalScrollBar().height()
- # h += self.table.horizontalScrollBar().height()
- #
- # # account for search box height
- # available_space -= self.searchbox.height()
- # h += self.searchbox.height()
- #
- # default_rows = int(available_space / self.row_height)
- #
- # n = sum(not self.table.isRowHidden(row) for row in
- # range(self.table.rowCount()))
- #
- # if n > default_rows:
- # h += default_rows * self.row_height
- # self.table.verticalScrollBar().show()
- # else:
- # h += n * self.row_height
- # self.table.verticalScrollBar().hide()
- # w -= self.table.verticalScrollBar().width()
- #
- # w = min(desktop_width, w)
- #
- # self.centralwidget.setFixedHeight(h)
- #
- # h += mainwindow_to_add
- #
- # self.setMaximumHeight(h)
- # self.setMinimumHeight(h)
- #
- # self.table.setFixedWidth(w)
- # self.centralwidget.setFixedWidth(w)
- # # don't change the following two lines to setFixedWidth!
- # self.setMaximumWidth(w)
- # self.setMinimumWidth(w)
-
- def moveEvent(self, event):
- super(VmManagerWindow, self).moveEvent(event)
- screen_number = app.desktop().screenNumber(self)
- if self.screen_number != screen_number:
- self.screen_changed = True
- self.screen_number = screen_number
- if self.settings_loaded:
- self.manager_settings.setValue('position/x', self.x())
- self.manager_settings.setValue('position/y', self.y())
- # do not sync for performance reasons
-
def domain_state_changed_callback(self, name=None, uuid=None):
if name is not None:
vm = self.qvm_collection.domains[name]
@@ -624,30 +426,7 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
vm.refresh()
def get_vms_list(self):
- # self.qvm_collection.lock_db_for_reading()
- # self.qvm_collection.load()
- # self.qvm_collection.unlock_db()
-
- running_count = 0
- internal_count = 0
-
- vms_list = [vm for vm in self.qvm_collection.domains]
- for vm in vms_list:
- # vm.last_power_state = vm.get_power_state()
- # vm.last_running = vm.is_running()
- # if vm.last_running:
- # running_count += 1
- # if vm.internal:
- # internal_count += 1
- # vm.qubes_manager_state = {}
- # self.update_audio_rec_info(vm)
- # vm.qubes_manager_state[QMVmState.ErrorMsg] = self.vm_errors[
- # vm.qid] if vm.qid in self.vm_errors else None
- running_count +=1
-
- self.running_vms_count = running_count
- self.internal_vms_count = internal_count
- return vms_list
+ return [vm for vm in self.qvm_collection.domains]
def fill_table(self):
# save current selection
@@ -684,25 +463,16 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
self.table.setSortingEnabled(True)
self.showhide_vms()
- # self.set_table_geom_size()
- def showhide_vms(self):
- if self.show_inactive_vms and self.show_internal_vms and not self.search:
+ def showhide_vms(self): # TODO: just show all all the time?
+ if not self.search:
for row_no in range(self.table.rowCount()):
self.table.setRowHidden(row_no, False)
else:
for row_no in range(self.table.rowCount()):
widget = self.table.cellWidget(row_no,
self.columns_indices["State"])
- running = False
- internal = False
- # running = widget.vm.last_running
- # internal = widget.vm.internal
- name = widget.vm.name
-
- show = (running or self.show_inactive_vms) and \
- (not internal or self.show_internal_vms) and \
- (self.search in widget.vm.name or not self.search)
+ show = (self.search in widget.vm.name or not self.search)
self.table.setRowHidden(row_no, not show)
@QtCore.pyqtSlot(str)
@@ -721,7 +491,6 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
# When calling update_table() directly, always use out_of_schedule=True!
def update_table(self, out_of_schedule=False):
- update_devs = self.update_block_devices() or out_of_schedule
reload_table = self.reload_table
if manager_window.isVisible():
@@ -768,72 +537,20 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
self.fill_table()
update_devs = True
- # if not self.show_inactive_vms and \
- # some_vms_have_changed_power_state:
- # self.showhide_vms()
- # self.set_table_geom_size()
-
# if self.sort_by_column == \
# "State" and some_vms_have_changed_power_state:
- # self.table.sortItems(self.columns_indices[self.sort_by_column],
+ # self.table.sortItems(self.columns_indices[self.sort_by_column],
# self.sort_order)
- blk_visible = None
- rows_with_blk = None
- # if update_devs:
- # rows_with_blk = []
- # self.blk_manager.blk_lock.acquire()
- # for d in self.blk_manager.attached_devs:
- # rows_with_blk.append(
- # self.blk_manager.attached_devs[d]['attached_to'][
- # 'vm'].qid)
- # self.blk_manager.blk_lock.release()
-
- if (not self.table.isColumnHidden(self.columns_indices['Size'])) and \
- self.counter % 60 == 0 or out_of_schedule:
+ if (not self.table.isColumnHidden(self.columns_indices['Size'])) \
+ and self.counter % 60 == 0 or out_of_schedule:
self.update_size_on_disk = True
- if self.counter % 3 == 0 or out_of_schedule:
- # (self.last_measure_time, self.last_measure_results) = \
- # qubes_host.measure_cpu_usage(self.qvm_collection,
- # self.last_measure_results,
- # self.last_measure_time)
+ for vm_row in self.vms_in_table.values():
+ vm_row.update(update_size_on_disk=self.update_size_on_disk)
+ # TODO: fix these for saner opts TODO2: is it fixed?
- for vm_row in self.vms_in_table.values():
- cur_cpu_load = None
- # if vm_row.vm.get_xid() in self.last_measure_results:
- # cur_cpu_load = self.last_measure_results[vm_row.vm.xid][
- # 'cpu_usage']
- # else:
- # cur_cpu_load = 0
-
- if rows_with_blk is not None:
- if vm_row.vm.qid in rows_with_blk:
- blk_visible = True
- else:
- blk_visible = False
-
- vm_row.update(blk_visible=blk_visible,
- cpu_load=cur_cpu_load,
- update_size_on_disk=self.update_size_on_disk,
- rec_visible=self.vm_rec.get(vm_row.vm.name,
- False))
-
- else:
- for vm_row in self.vms_in_table.values():
- if rows_with_blk is not None:
- if vm_row.vm.qid in rows_with_blk:
- blk_visible = True
- else:
- blk_visible = False
-
- vm_row.update(blk_visible=blk_visible,
- update_size_on_disk=self.update_size_on_disk,
- rec_visible=self.vm_rec.get(vm_row.vm.name,
- False))
-
- if self.sort_by_column in ["CPU", "CPU Graph", "MEM", "MEM Graph",
- "State", "Size", "Internal"]:
+ if self.sort_by_column in ["CPU", "State", "Size", "Internal"]:
# "State": needed to sort after reload (fill_table sorts items
# with setSortingEnabled, but by that time the widgets values
# are not correct yet).
@@ -843,36 +560,12 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
self.table_selection_changed()
self.update_size_on_disk = False
- if not out_of_schedule:
- self.counter += 1
- # noinspection PyCallByClass,PyTypeChecker
- # QtCore.QTimer.singleShot(self.update_interval, self.update_table)
-
- def update_block_devices(self):
- pass
- # res, msg = self.blk_manager.check_for_updates()
- # if msg is not None and len(msg) > 0:
- # trayIcon.showMessage('\n'.join(msg), msecs=5000)
- # return res
# noinspection PyPep8Naming
@QtCore.pyqtSlot(bool, str)
def recAllowedChanged(self, state, vmname):
self.vm_rec[str(vmname)] = bool(state)
- def register_dbus_watches(self):
- global session_bus
-
- if not session_bus:
- session_bus = QDBusConnection.sessionBus()
-
- if not session_bus.connect("", # service
- "", # path
- "org.QubesOS.Audio", # interface
- "RecAllowedChanged", # name
- self.recAllowedChanged): # slot
- print(session_bus.lastError().message())
-
# noinspection PyPep8Naming
def sortIndicatorChanged(self, column, order):
self.sort_by_column = [name for name in self.columns_indices.keys() if
@@ -885,18 +578,19 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
self.manager_settings.sync()
def table_selection_changed(self):
+ # TODO: and this should actually work, fixit
vm = self.get_selected_vm()
if vm is not None:
# Update available actions:
self.action_settings.setEnabled(vm.qid != 0)
- self.action_removevm.setEnabled(
- not vm.installed_by_rpm and not vm.last_running)
- self.action_clonevm.setEnabled(
- not vm.last_running and not vm.is_netvm())
- # self.action_resumevm.setEnabled(not vm.last_running or
- # vm.last_power_state == "Paused")
+ self.action_removevm.setEnabled(vm.klass != 'AdminVM'
+ and not vm.is_running())
+ # TODO: think about this
+ self.action_clonevm.setEnabled(vm.klass != 'AdminVM')
+ self.action_resumevm.setEnabled(vm.get_power_state() == "Paused")
+ # TODO: check
try:
pass
# self.action_startvm_tools_install.setVisible(
@@ -904,37 +598,33 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
except NameError:
# ignore non existing QubesHVm
pass
- self.action_startvm_tools_install.setEnabled(not vm.last_running)
- # self.action_pausevm.setEnabled(
- # vm.last_running and
- # vm.last_power_state != "Paused" and
- # vm.qid != 0)
- # self.action_shutdownvm.setEnabled(
- # vm.last_running and
- # vm.last_power_state != "Paused" and
- # vm.qid != 0)
- # self.action_restartvm.setEnabled(
- # vm.last_running and
- # vm.last_power_state != "Paused" and
- # vm.qid != 0 and
- # not vm.is_disposablevm())
- # self.action_killvm.setEnabled((vm.last_running or
- # vm.last_power_state == "Paused") and
- # vm.qid != 0)
- # self.action_appmenus.setEnabled(vm.qid != 0 and
- # not vm.internal and
- # not vm.is_disposablevm())
- # self.action_editfwrules.setEnabled(vm.is_networked() and not (
- # vm.is_netvm() and not vm.is_proxyvm()))
+ self.action_startvm_tools_install.setEnabled(
+ getattr(vm, 'updateable', False))
+ # TODO: add qvm boot from device to this and add there windows tools
+ self.action_pausevm.setEnabled(vm.get_power_state() != "Paused" and
+ vm.qid != 0)
+ self.action_shutdownvm.setEnabled(vm.get_power_state() != "Paused"
+ and vm.qid != 0)
+ self.action_restartvm.setEnabled(vm.get_power_state() != "Paused"
+ and vm.qid != 0
+ and vm.klass != 'DisposableVM')
+ self.action_killvm.setEnabled(vm.get_power_state() == "Paused" and
+ vm.qid != 0)
+ # TODO: check conditions
+ self.action_appmenus.setEnabled(
+ vm.klass != 'AdminVM' and vm.klass != 'DisposableMV'
+ and not vm.features.get('internal', False))
+ self.action_editfwrules.setEnabled(True) # TODO: remove this and make sure the option is enabled in designer
+ # TODO: this should work
# self.action_updatevm.setEnabled(vm.is_updateable() or vm.qid == 0)
+ # TODO: this should work
# self.action_toggle_audio_input.setEnabled(
# vm.qubes_manager_state[QMVmState.AudioRecAvailable])
- # self.action_run_command_in_vm.setEnabled(
- # not vm.last_power_state == "Paused" and vm.qid != 0)
- # self.action_set_keyboard_layout.setEnabled(
- # vm.qid != 0 and
- # vm.last_running and
- # vm.last_power_state != "Paused")
+ self.action_run_command_in_vm.setEnabled(
+ not vm.get_power_state() == "Paused" and vm.qid != 0)
+ self.action_set_keyboard_layout.setEnabled(
+ vm.qid != 0 and
+ vm.get_power_state() != "Paused")
else:
self.action_settings.setEnabled(False)
self.action_removevm.setEnabled(False)
@@ -953,13 +643,6 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
self.action_run_command_in_vm.setEnabled(False)
self.action_set_keyboard_layout.setEnabled(False)
- def closeEvent(self, event):
- # There is something borked in Qt,
- # as the logic here is inverted on X11
- if event.spontaneous():
- self.hide()
- event.ignore()
-
def set_error(self, qid, message):
for vm in self.vms_list:
if vm.qid == qid:
@@ -981,10 +664,8 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
self.vm_errors.pop(qid, None)
@QtCore.pyqtSlot(name='on_action_createvm_triggered')
- def action_createvm_triggered(self):
- pass
- # dialog = NewVmDlg(app, self.qvm_collection, trayIcon)
- # dialog.exec_()
+ def action_createvm_triggered(self): # TODO: this should work
+ subprocess.check_call('qubes-vm-create')
def get_selected_vm(self):
# vm selection relies on the VmInfo widget's value used
@@ -1004,7 +685,7 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
return None
@QtCore.pyqtSlot(name='on_action_removevm_triggered')
- def action_removevm_triggered(self):
+ def action_removevm_triggered(self): # TODO: this should work
vm = self.get_selected_vm()
assert not vm.is_running()
@@ -1013,25 +694,27 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
vm = self.qvm_collection[vm.qid]
if vm.is_template():
- dependent_vms = self.qvm_collection.domains[vm.qid]
- if len(dependent_vms) > 0:
+ dependent_vms = 0
+ for single_vm in self.qvm_collection.domains:
+ if getattr(single_vm, 'template', None) == vm:
+ dependent_vms += 1
+ if dependent_vms > 0:
QtGui.QMessageBox.warning(
None, self.tr("Warning!"),
- self.tr("This Template VM cannot be removed, because there is at "
- "least one AppVM that is based on it.
"
- "If you want to remove this Template VM and all "
- "the AppVMs based on it,"
- "you should first remove each individual AppVM that uses "
- "this template."))
-
+ self.tr("This Template VM cannot be removed, "
+ "because there is at least one AppVM that is based "
+ "on it.
If you want to remove this "
+ "Template VM and all the AppVMs based on it, you "
+ "should first remove each individual AppVM that "
+ "uses this template."))
return
(requested_name, ok) = QtGui.QInputDialog.getText(
None, self.tr("VM Removal Confirmation"),
- self.tr("Are you sure you want to remove the VM '{0}'?
"
- "All data on this VM's private storage will be lost!
"
- "Type the name of the VM ({1}) below to confirm:")
- .format(vm.name, vm.name))
+ self.tr("Are you sure you want to remove the VM '{0}'?
"
+ "All data on this VM's private storage will be lost!"
+ "
Type the name of the VM ({1}) below to "
+ "confirm:").format(vm.name, vm.name))
if not ok:
# user clicked cancel
@@ -1039,15 +722,19 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
elif requested_name != vm.name:
# name did not match
- QtGui.QMessageBox.warning(None, self.tr("VM removal confirmation failed"),
- self.tr("Entered name did not match! Not removing {0}.").format(vm.name))
+ QtGui.QMessageBox.warning(
+ None,
+ self.tr("VM removal confirmation failed"),
+ self.tr(
+ "Entered name did not match! Not removing "
+ "{0}.").format(vm.name))
return
else:
# remove the VM
t_monitor = thread_monitor.ThreadMonitor()
thread = threading.Thread(target=self.do_remove_vm,
- args=(vm, t_monitor))
+ args=(vm, self.qvm_collection, t_monitor))
thread.daemon = True
thread.start()
@@ -1057,45 +744,30 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
progress.setModal(True)
progress.show()
- while not thread_monitor.is_finished():
+ while not t_monitor.is_finished():
app.processEvents()
time.sleep(0.1)
progress.hide()
- if thread_monitor.success:
- trayIcon.showMessage(
- self.tr("VM '{0}' has been removed.").format(vm.name), msecs=3000)
+ if t_monitor.success:
+ pass
else:
QtGui.QMessageBox.warning(None, self.tr("Error removing VM!"),
- self.tr("ERROR: {0}").format(
- thread_monitor.error_msg))
+ self.tr("ERROR: {0}").format(
+ t_monitor.error_msg))
@staticmethod
- def do_remove_vm(vm, thread_monitor):
- qc = Qubes()
+ def do_remove_vm(vm, qvm_collection, t_monitor):
try:
- vm = qc.domains[vm.qid]
-
- # TODO: the following two conditions should really be checked
- # by qvm_collection.pop() overload...
- if vm.is_template() and \
- qc.default_template_qid == vm.qid:
- qc.default_template_qid = None
- if vm.is_netvm() and \
- qc.default_netvm_qid == vm.qid:
- qc.default_netvm_qid = None
-
- # qc.pop(vm.qid)
- # qc.save()
- vm.remove_from_disk()
+ del qvm_collection.domains[vm.name]
except Exception as ex:
- thread_monitor.set_error_msg(str(ex))
+ t_monitor.set_error_msg(str(ex))
- thread_monitor.set_finished()
+ t_monitor.set_finished()
@QtCore.pyqtSlot(name='on_action_clonevm_triggered')
- def action_clonevm_triggered(self):
+ def action_clonevm_triggered(self): # TODO: this should work
vm = self.get_selected_vm()
name_number = 1
@@ -1112,14 +784,14 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
t_monitor = thread_monitor.ThreadMonitor()
thread = threading.Thread(target=self.do_clone_vm,
- args=(vm, str(clone_name), t_monitor))
+ args=(vm, self.qvm_collection,
+ clone_name, t_monitor))
thread.daemon = True
thread.start()
progress = QtGui.QProgressDialog(
- self.tr("Cloning VM {0} to {1}...").format(vm.name,
- clone_name), "", 0,
- 0)
+ self.tr("Cloning VM {0} to {1}...").format(
+ vm.name, clone_name), "", 0, 0)
progress.setCancelButton(None)
progress.setModal(True)
progress.show()
@@ -1131,48 +803,38 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
progress.hide()
if not t_monitor.success:
- QtGui.QMessageBox.warning(None, self.tr("Error while cloning VM"),
- self.tr("Exception while cloning:
{0}").format(
- t_monitor.error_msg))
+ QtGui.QMessageBox.warning(
+ None,
+ self.tr("Error while cloning VM"),
+ self.tr("Exception while cloning:
{0}").format(
+ t_monitor.error_msg))
@staticmethod
- def do_clone_vm(vm, dst_name, thread_monitor):
+ def do_clone_vm(src_vm, qvm_collection, dst_name, t_monitor):
dst_vm = None
- qc = Qubes()
try:
- src_vm = qc[vm.qid]
-
- dst_vm = qc.add_new_vm(src_vm.__class__.__name__,
- name=dst_name,
- template=src_vm.template,
- installed_by_rpm=False)
-
- dst_vm.clone_attrs(src_vm)
- dst_vm.clone_disk_files(src_vm=src_vm, verbose=False)
- qc.save()
+ dst_vm = qvm_collection.clone_vm(src_vm, dst_name)
except Exception as ex:
if dst_vm:
- qc.pop(dst_vm.qid)
- dst_vm.remove_from_disk()
- thread_monitor.set_error_msg(str(ex))
- thread_monitor.set_finished()
+ pass # TODO: should I remove any remnants?
+ t_monitor.set_error_msg(str(ex))
+ t_monitor.set_finished()
@QtCore.pyqtSlot(name='on_action_resumevm_triggered')
def action_resumevm_triggered(self):
vm = self.get_selected_vm()
- # if vm.get_power_state() in ["Paused", "Suspended"]:
- # try:
- # vm.resume()
- # except Exception as ex:
- # QtGui.QMessageBox.warning(None, self.tr("Error unpausing VM!"),
- # self.tr("ERROR: {0}").format(ex))
- # return
-
+ if vm.get_power_state() in ["Paused", "Suspended"]:
+ try:
+ vm.unpause()
+ except Exception as ex:
+ QtGui.QMessageBox.warning(None, self.tr("Error unpausing VM!"),
+ self.tr("ERROR: {0}").format(ex))
+ return
self.start_vm(vm)
- def start_vm(self, vm):
+ def start_vm(self, vm): # TODO: this should work
assert not vm.is_running()
t_monitor = thread_monitor.ThreadMonitor()
thread = threading.Thread(target=self.do_start_vm,
@@ -1180,22 +842,14 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
thread.daemon = True
thread.start()
- trayIcon.showMessage(self.tr("Starting '{0}'...").format(vm.name), msecs=3000)
-
while not t_monitor.is_finished():
app.processEvents()
time.sleep(0.1)
- if t_monitor.success:
- trayIcon.showMessage(self.tr("VM '{0}' has been started.").format(vm.name),
- msecs=3000)
- else:
- trayIcon.showMessage(
- self.tr("Error starting VM '{0}': {1}").format(
- vm.name, t_monitor.error_msg),
- msecs=3000)
- self.set_error(vm.qid,
- self.tr("Error starting VM: %s") % t_monitor.error_msg)
+ if not t_monitor.success:
+ self.set_error(
+ vm.qid,
+ self.tr("Error starting VM: %s") % t_monitor.error_msg)
@staticmethod
def do_start_vm(vm, t_monitor):
@@ -1209,6 +863,7 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
t_monitor.set_finished()
@QtCore.pyqtSlot(name='on_action_startvm_tools_install_triggered')
+ # TODO: replace with boot from device
def action_startvm_tools_install_triggered(self):
vm = self.get_selected_vm()
assert not vm.is_running()
@@ -1218,49 +873,40 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
if not windows_tools_installed:
msg = QtGui.QMessageBox()
msg.warning(self, self.tr("Error starting VM!"),
- self.tr("You need to install 'qubes-windows-tools' "
- "package to use this option"))
+ self.tr("You need to install 'qubes-windows-tools' "
+ "package to use this option"))
return
-
t_monitor = thread_monitor.ThreadMonitor()
thread = threading.Thread(target=self.do_start_vm_tools_install,
args=(vm, t_monitor))
thread.daemon = True
thread.start()
- trayIcon.showMessage(self.tr("Starting '{0}'...").format(vm.name), msecs=3000)
-
while not t_monitor.is_finished():
app.processEvents()
time.sleep(0.1)
- if t_monitor.success:
- trayIcon.showMessage(self.tr("VM '{0}' has been started. Start Qubes "
- "Tools installation from attached CD")
- .format(vm.name), msecs=3000)
- else:
- trayIcon.showMessage(
- self.tr("Error starting VM '{0}': {1}")
- .format(vm.name, t_monitor.error_msg),
- msecs=3000)
- self.set_error(vm.qid,
- self.tr("Error starting VM: %s") % t_monitor.error_msg)
+ if not t_monitor.success:
+ self.set_error(
+ vm.qid,
+ self.tr("Error starting VM: %s") % t_monitor.error_msg)
# noinspection PyMethodMayBeStatic
- def do_start_vm_tools_install(self, vm, thread_monitor):
+ def do_start_vm_tools_install(self, vm, t_monitor):
+ # TODO: should this work?
prev_drive = vm.drive
try:
vm.drive = 'cdrom:dom0:/usr/lib/qubes/qubes-windows-tools.iso'
vm.start()
except Exception as ex:
- thread_monitor.set_error_msg(str(ex))
- thread_monitor.set_finished()
+ t_monitor.set_error_msg(str(ex))
+ t_monitor.set_finished()
return
finally:
vm.drive = prev_drive
- thread_monitor.set_finished()
+ t_monitor.set_finished()
@QtCore.pyqtSlot(name='on_action_pausevm_triggered')
def action_pausevm_triggered(self):
@@ -1269,8 +915,10 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
try:
vm.pause()
except Exception as ex:
- QtGui.QMessageBox.warning(None, self.tr("Error pausing VM!"),
- self.tr("ERROR: {0}").format(ex))
+ QtGui.QMessageBox.warning(
+ None,
+ self.tr("Error pausing VM!"),
+ self.tr("ERROR: {0}").format(ex))
return
@QtCore.pyqtSlot(name='on_action_shutdownvm_triggered')
@@ -1278,34 +926,32 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
vm = self.get_selected_vm()
assert vm.is_running()
- # self.blk_manager.check_if_serves_as_backend(vm)
-
reply = QtGui.QMessageBox.question(
None, self.tr("VM Shutdown Confirmation"),
- self.tr("Are you sure you want to power down the VM '{0}'?
"
- "This will shutdown all the running applications "
- "within this VM.").format(vm.name),
- QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel)
+ self.tr("Are you sure you want to power down the VM"
+ " '{0}'?
This will shutdown all the "
+ "running applications within this VM.").format(
+ vm.name), QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel)
- app.processEvents()
+ app.processEvents() # TODO: is this needed??
if reply == QtGui.QMessageBox.Yes:
self.shutdown_vm(vm)
def shutdown_vm(self, vm, shutdown_time=vm_shutdown_timeout,
- check_time=vm_restart_check_timeout, and_restart=False):
+ check_time=vm_restart_check_timeout, and_restart=False):
try:
vm.shutdown()
except Exception as ex:
- QtGui.QMessageBox.warning(None, self.tr("Error shutting down VM!"),
- self.tr("ERROR: {0}").format(ex))
+ QtGui.QMessageBox.warning(
+ None,
+ self.tr("Error shutting down VM!"),
+ self.tr("ERROR: {0}").format(ex))
return
- trayIcon.showMessage(self.tr("VM '{0}' is shutting down...").format(vm.name),
- msecs=3000)
-
self.shutdown_monitor[vm.qid] = VmShutdownMonitor(vm, shutdown_time,
- check_time, and_restart, self)
+ check_time,
+ and_restart, self)
# noinspection PyCallByClass,PyTypeChecker
QtCore.QTimer.singleShot(check_time, self.shutdown_monitor[
vm.qid].check_if_vm_has_shutdown)
@@ -1315,13 +961,11 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
vm = self.get_selected_vm()
assert vm.is_running()
- # self.blk_manager.check_if_serves_as_backend(vm)
-
reply = QtGui.QMessageBox.question(
None, self.tr("VM Restart Confirmation"),
self.tr("Are you sure you want to restart the VM '{0}'?
"
- "This will shutdown all the running applications "
- "within this VM.").format(vm.name),
+ "This will shutdown all the running applications "
+ "within this VM.").format(vm.name),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel)
app.processEvents()
@@ -1337,8 +981,9 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
reply = QtGui.QMessageBox.question(
None, self.tr("VM Kill Confirmation"),
self.tr("Are you sure you want to kill the VM '{0}'?
"
- "This will end (not shutdown!) all the running "
- "applications within this VM.").format(vm.name),
+ "This will end (not shutdown!) all the "
+ "running applications within this VM.").format(
+ vm.name),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel,
QtGui.QMessageBox.Cancel)
@@ -1350,65 +995,26 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
except Exception as ex:
QtGui.QMessageBox.critical(
None, self.tr("Error while killing VM!"),
- self.tr("An exception ocurred while killing {0}.
"
- "ERROR: {1}").format(vm.name, ex))
+ self.tr(
+ "An exception ocurred while killing {0}.
"
+ "ERROR: {1}").format(vm.name, ex))
return
- trayIcon.showMessage(self.tr("VM '{0}' killed!")
- .format(vm.name), msecs=3000)
-
@QtCore.pyqtSlot(name='on_action_settings_triggered')
def action_settings_triggered(self):
- pass
- #TODO this should work, actually, but please not now
- # vm = self.get_selected_vm()
- # settings_window = VMSettingsWindow(vm, app, self.qvm_collection,
- # "basic")
- # settings_window.exec_()
+ vm = self.get_selected_vm()
+ settings_window = settings.VMSettingsWindow(vm, app, "basic")
+ settings_window.exec_()
@QtCore.pyqtSlot(name='on_action_appmenus_triggered')
def action_appmenus_triggered(self):
pass
- #TODO this should work, actually, but please not now
+ # TODO this should work, actually, but please not now
# vm = self.get_selected_vm()
# settings_window = VMSettingsWindow(vm, app, self.qvm_collection,
# "applications")
# settings_window.exec_()
- def update_audio_rec_info(self, vm):
- vm.qubes_manager_state[QMVmState.AudioRecAvailable] = (
- session_bus.interface().isServiceRegistered(
- 'org.QubesOS.Audio.%s' % vm.name).value())
- if vm.qubes_manager_state[QMVmState.AudioRecAvailable]:
- vm.qubes_manager_state[
- QMVmState.AudioRecAllowed] = self.get_audio_rec_allowed(vm.name)
- else:
- vm.qubes_manager_state[QMVmState.AudioRecAllowed] = False
-
- # noinspection PyMethodMayBeStatic
- def get_audio_rec_allowed(self, vmname):
- properties = QDBusInterface('org.QubesOS.Audio.%s' % vmname,
- '/org/qubesos/audio',
- 'org.freedesktop.DBus.Properties',
- session_bus)
-
- current_audio = properties.call('Get', 'org.QubesOS.Audio',
- 'RecAllowed')
- if current_audio.type() == current_audio.ReplyMessage:
- value = current_audio.arguments()[0].toPyObject()
- return bool(value)
- return False
-
- @QtCore.pyqtSlot(name='on_action_toggle_audio_input_triggered')
- def action_toggle_audio_input_triggered(self):
- vm = self.get_selected_vm()
- properties = QDBusInterface('org.QubesOS.Audio.%s' % vm.name,
- '/org/qubesos/audio',
- 'org.freedesktop.DBus.Properties',
- session_bus)
- properties.call('Set', 'org.QubesOS.Audio', 'RecAllowed',
- QDBusVariant(not self.get_audio_rec_allowed(vm.name)))
- # icon will be updated based on dbus signal
@QtCore.pyqtSlot(name='on_action_updatevm_triggered')
def action_updatevm_triggered(self):
@@ -1422,8 +1028,6 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel)
if reply != QtGui.QMessageBox.Yes:
return
- trayIcon.showMessage(self.tr("Starting '{0}'...").format(vm.name),
- msecs=3000)
app.processEvents()
@@ -1453,16 +1057,13 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
t_monitor.error_msg))
@staticmethod
- def do_update_vm(vm, thread_monitor):
+ def do_update_vm(vm, thread_monitor): #TODO: fixme
try:
if vm.qid == 0:
subprocess.check_call(
["/usr/bin/qubes-dom0-update", "--clean", "--gui"])
else:
if not vm.is_running():
- trayIcon.showMessage(
- "Starting the '{0}' VM...".format(vm.name),
- msecs=3000)
vm.start()
vm.run_service("qubes.InstallUpdatesGUI", gui=True,
user="root", wait=False)
@@ -1498,80 +1099,49 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
t_monitor.error_msg))
@staticmethod
- def do_run_command_in_vm(vm, command_to_run, thread_monitor):
+ def do_run_command_in_vm(vm, command_to_run, t_monitor):
try:
- vm.run(command_to_run, verbose=False, autostart=True,
- notify_function=lambda lvl, msg: trayIcon.showMessage(
- msg, msecs=3000))
+ vm.run(command_to_run, verbose=False, autostart=True)
except Exception as ex:
- thread_monitor.set_error_msg(str(ex))
- thread_monitor.set_finished()
+ t_monitor.set_error_msg(str(ex))
+ t_monitor.set_finished()
@QtCore.pyqtSlot(name='on_action_set_keyboard_layout_triggered')
def action_set_keyboard_layout_triggered(self):
vm = self.get_selected_vm()
vm.run('qubes-change-keyboard-layout', verbose=False)
- @QtCore.pyqtSlot(name='on_action_showallvms_triggered')
- def action_showallvms_triggered(self):
- self.show_inactive_vms = self.action_showallvms.isChecked()
-
- self.showhide_vms()
- # self.set_table_geom_size()
- if self.settings_loaded:
- self.manager_settings.setValue('view/show_inactive_vms',
- self.show_inactive_vms)
- self.manager_settings.sync()
-
- @QtCore.pyqtSlot(name='on_action_showinternalvms_triggered')
- def action_showinternalvms_triggered(self):
- self.show_internal_vms = self.action_showinternalvms.isChecked()
-
- self.showhide_vms()
- # self.set_table_geom_size()
- if self.settings_loaded:
- self.manager_settings.setValue('view/show_internal_vms',
- self.show_internal_vms)
- self.manager_settings.sync()
+ #TODO: remove showallvms / show inactive vms / show internal vms
@QtCore.pyqtSlot(name='on_action_editfwrules_triggered')
def action_editfwrules_triggered(self):
- pass
- #TODO: revive
- # vm = self.get_selected_vm()
- # settings_window = VMSettingsWindow(vm, app, self.qvm_collection,
- # "firewall")
- # settings_window.exec_()
+ vm = self.get_selected_vm()
+ settings_window = settings.VMSettingsWindow(vm, app, "firewall")
+ settings_window.exec_()
@QtCore.pyqtSlot(name='on_action_global_settings_triggered')
def action_global_settings_triggered(self):
- pass
- #TODO: revive
- # global_settings_window = GlobalSettingsWindow(app, self.qvm_collection)
- # global_settings_window.exec_()
+ global_settings_window = global_settings.GlobalSettingsWindow(
+ app,
+ self.qvm_collection)
+ global_settings_window.exec_()
@QtCore.pyqtSlot(name='on_action_show_network_triggered')
def action_show_network_triggered(self):
pass
- #TODO: revive
+ #TODO: revive TODO: what is this thing??
# network_notes_dialog = NetworkNotesDialog()
# network_notes_dialog.exec_()
@QtCore.pyqtSlot(name='on_action_restore_triggered')
def action_restore_triggered(self):
- pass
- #TODO: revive
- # restore_window = RestoreVMsWindow(app, self.qvm_collection,
- # self.blk_manager)
- # restore_window.exec_()
+ restore_window = restore.RestoreVMsWindow(app, self.qvm_collection)
+ restore_window.exec_()
@QtCore.pyqtSlot(name='on_action_backup_triggered')
def action_backup_triggered(self):
- pass
- #TODO: revive
- # backup_window = BackupVMsWindow(app, self.qvm_collection,
- # self.blk_manager, self.shutdown_vm)
- # backup_window.exec_()
+ backup_window = backup.BackupVMsWindow(app, self.qvm_collection)
+ backup_window.exec_()
def showhide_menubar(self, checked):
self.menubar.setVisible(checked)
@@ -1597,17 +1167,17 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
def showhide_column(self, col_num, show):
self.table.setColumnHidden(col_num, not show)
- # self.set_table_geom_size()
+
val = 1 if show else -1
self.visible_columns_count += val
- if self.visible_columns_count == 1:
+ if self.visible_columns_count == 1: # TODO: is this working at all??
# disable hiding the last one
for c in self.columns_actions:
if self.columns_actions[c].isChecked():
self.columns_actions[c].setEnabled(False)
break
- elif self.visible_columns_count == 2 and val == 1:
+ elif self.visible_columns_count == 2 and val == 1: # TODO: likewise??
# enable hiding previously disabled column
for c in self.columns_actions:
if not self.columns_actions[c].isEnabled():
@@ -1650,18 +1220,6 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
def on_action_netvm_toggled(self, checked):
self.showhide_column(self.columns_indices['NetVM'], checked)
- def on_action_cpu_toggled(self, checked):
- self.showhide_column(self.columns_indices['CPU'], checked)
-
- def on_action_cpu_graph_toggled(self, checked):
- self.showhide_column(self.columns_indices['CPU Graph'], checked)
-
- def on_action_mem_toggled(self, checked):
- self.showhide_column(self.columns_indices['MEM'], checked)
-
- def on_action_mem_graph_toggled(self, checked):
- self.showhide_column(self.columns_indices['MEM Graph'], checked)
-
def on_action_size_on_disk_toggled(self, checked):
self.showhide_column(self.columns_indices['Size'], checked)
@@ -1707,48 +1265,6 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
self.logs_menu.setEnabled(not menu_empty)
- # blk menu
- if not running:
- self.blk_menu.setEnabled(False)
- else:
- self.blk_menu.clear()
- self.blk_menu.setEnabled(True)
-
- # self.blk_manager.blk_lock.acquire()
- # if len(self.blk_manager.attached_devs) > 0:
- # for d in self.blk_manager.attached_devs:
- # if (self.blk_manager.attached_devs[d]
- # ['attached_to']['vm'].qid == vm.qid):
- # text = self.tr("Detach {dev} {size} {desc}").format(
- # dev=d,
- # size=
- # self.blk_manager.attached_devs[d]['size'],
- # desc=self.blk_manager.attached_devs[d]['desc'])
- # action = self.blk_menu.addAction(QtGui.QIcon(":/remove.png"),
- # text)
- # action.setData(QtCore.QVariant(d))
- #
- # if len(self.blk_manager.free_devs) > 0:
- # for d in self.blk_manager.free_devs:
- # if d.startswith(vm.name):
- # continue
- # # skip partitions heuristic
- # if d[-1].isdigit() and \
- # d[0:-1] in self.blk_manager.current_blk:
- # continue
- # text = self.tr("Attach {dev} {size} {desc}").format(
- # dev=d,
- # size=
- # self.blk_manager.free_devs[d]['size'],
- # desc=self.blk_manager.free_devs[d]['desc'])
- # action = self.blk_menu.addAction(QtGui.QIcon(":/add.png"), text)
- # action.setData(QtCore.QVariant(d))
- #
- # self.blk_manager.blk_lock.release()
-
- if self.blk_menu.isEmpty():
- self.blk_menu.setEnabled(False)
-
self.context_menu.exec_(self.table.mapToGlobal(point))
@QtCore.pyqtSlot('QAction *')
@@ -1759,312 +1275,15 @@ class VmManagerWindow(ui_vtmanager.Ui_VmManagerWindow, QtGui.QMainWindow):
# log_dialog = LogDialog(app, log)
# log_dialog.exec_()
- @QtCore.pyqtSlot('QAction *')
- def attach_dettach_device_triggered(self, action):
- pass
- # dev = str(action.data())
- # vm = self.get_selected_vm()
- #
- # self.blk_manager.blk_lock.acquire()
- # try:
- # if dev in self.blk_manager.attached_devs:
- # self.blk_manager.detach_device(vm, dev)
- # else:
- # self.blk_manager.attach_device(vm, dev)
- # self.blk_manager.blk_lock.release()
- # except exc.QubesException as e:
- # self.blk_manager.blk_lock.release()
- # QtGui.QMessageBox.critical(None,
- # self.tr("Block attach/detach error!"), str(e))
-
-
-class QubesTrayIcon(QtGui.QSystemTrayIcon):
- def __init__(self, icon):
- QtGui.QSystemTrayIcon.__init__(self, icon)
- self.menu = QtGui.QMenu()
-
- action_showmanager = self.create_action(
- self.tr("Open VM Manager"),
- slot=show_manager, icon="qubes")
- # action_copy = self.create_action(
- # self.tr("Copy Dom0 clipboard"), icon="copy",
- # slot=do_dom0_copy)
- action_backup = self.create_action(self.tr("Make backup"))
- action_preferences = self.create_action(self.tr("Preferences"))
- action_set_netvm = self.create_action(self.tr("Set default NetVM"),
- icon="networking")
- action_sys_info = self.create_action(self.tr("System Info"), icon="dom0")
- action_exit = self.create_action(self.tr("Exit"), slot=exit_app)
-
- action_backup.setDisabled(True)
- action_preferences.setDisabled(True)
- action_set_netvm.setDisabled(True)
- action_sys_info.setDisabled(True)
-
- # self.blk_manager = blk_manager
-
- self.blk_menu = QtGui.QMenu(self.menu)
- self.blk_menu.setTitle(self.tr("Block devices"))
- action_blk_menu = self.create_action(self.tr("Block devices"))
- action_blk_menu.setMenu(self.blk_menu)
-
- self.add_actions(self.menu, (action_showmanager,
- # action_copy,
- action_blk_menu,
- action_backup,
- action_sys_info,
- None,
- action_preferences,
- action_set_netvm,
- None,
- action_exit))
-
- self.setContextMenu(self.menu)
-
- # self.connect(self,
- # QtCore.SIGNAL("activated (QtGui.QSystemTrayIcon::ActivationReason)"),
- # self.icon_clicked)
-
- self.tray_notifier_type = None
- self.tray_notifier = QDBusInterface("org.freedesktop.Notifications",
- "/org/freedesktop/Notifications",
- "org.freedesktop.Notifications",
- session_bus)
- srv_info = self.tray_notifier.call("GetServerInformation")
- if srv_info.type() == QDBusMessage.ReplyMessage and \
- len(srv_info.arguments()) > 1:
- self.tray_notifier_type = srv_info.arguments()[1]
-
- if os.path.exists(table_widgets.qubes_dom0_updates_stat_file):
- self.showMessage(self.tr("Qubes dom0 updates available."), msecs=0)
-
- def update_blk_menu(self):
- global manager_window
-
- def create_vm_submenu(dev):
- blk_vm_menu = QtGui.QMenu(self.blk_menu)
- blk_vm_menu.triggered.connect(
- lambda a, trig_dev=dev: self.attach_device_triggered(a,
- trig_dev))
- for this_vm in sorted(manager_window.qvm_collection.domains,
- key=lambda x: x.name):
- if not this_vm.is_running():
- continue
- if this_vm.qid == 0:
- # skip dom0 to prevent (fatal) mistakes
- continue
- this_action = blk_vm_menu.addAction(QtGui.QIcon(":/add.png"),
- this_vm.name)
- this_action.setData(QtCore.QVariant(this_vm))
- return blk_vm_menu
-
- self.blk_menu.clear()
- self.blk_menu.setEnabled(True)
-
- # self.blk_manager.blk_lock.acquire()
- # if len(self.blk_manager.attached_devs) > 0:
- # for d in self.blk_manager.attached_devs:
- # vm = self.blk_manager.attached_devs[d]['attached_to']['vm']
- # text = self.tr("Detach {dev} {desc} ({size}) from {vm}").format(
- # dev=d,
- # desc=self.blk_manager.attached_devs[d]['desc'],
- # size=self.blk_manager.attached_devs[d]['size'],
- # vm=vm.name)
- # action = self.blk_menu.addAction(QtGui.QIcon(":/remove.png"), text)
- # action.setData(QtCore.QVariant(d))
- # action.triggered.connect(
- # lambda b, a=action: self.dettach_device_triggered(a))
- #
- # if len(self.blk_manager.free_devs) > 0:
- # for d in self.blk_manager.free_devs:
- # # skip partitions heuristic
- # if d[-1].isdigit() and d[0:-1] in self.blk_manager.current_blk:
- # continue
- # text = self.tr("Attach {dev} {size} {desc}").format(
- # dev=d,
- # size=self.blk_manager.free_devs[d]['size'],
- # desc=self.blk_manager.free_devs[d]['desc']
- # )
- # action = self.blk_menu.addAction(QtGui.QIcon(":/add.png"), text)
- # action.setMenu(create_vm_submenu(d))
- #
- # self.blk_manager.blk_lock.release()
-
- if self.blk_menu.isEmpty():
- self.blk_menu.setEnabled(False)
-
- @QtCore.pyqtSlot('QAction *')
- def attach_device_triggered(self, action, dev):
- pass
- # vm = action.data().toPyObject()
- #
- # self.blk_manager.blk_lock.acquire()
- # try:
- # self.blk_manager.attach_device(vm, dev)
- # self.blk_manager.blk_lock.release()
- # except exc.QubesException as e:
- # self.blk_manager.blk_lock.release()
- # QtGui.QMessageBox.critical(None,
- # self.tr("Block attach/detach error!"), str(e))
-
- @QtCore.pyqtSlot('QAction *')
- def dettach_device_triggered(self, action):
- pass
- # dev = str(action.data())
- # vm = self.blk_manager.attached_devs[dev]['attached_to']['vm']
- #
- # self.blk_manager.blk_lock.acquire()
- # try:
- # self.blk_manager.detach_device(vm, dev)
- # self.blk_manager.blk_lock.release()
- # except exc.QubesException as e:
- # self.blk_manager.blk_lock.release()
- # QtGui.QMessageBox.critical(None,
- # self.tr("Block attach/detach error!"), str(e))
-
- def icon_clicked(self, reason):
- if reason == QtGui.QSystemTrayIcon.Context:
- self.update_blk_menu()
- # Handle the right click normally, i.e. display the context menu
- return
- else:
- bring_manager_to_front()
-
- # noinspection PyMethodMayBeStatic
- def add_actions(self, target, actions):
- for action in actions:
- if action is None:
- target.addSeparator()
- else:
- target.addAction(action)
-
- def showMessage(self, message, msecs, **kwargs):
- # QtDBus bindings doesn't use introspection to get proper method
- # parameters types, so must cast explicitly
- # v_replace_id = QtCore.QVariant(0)
- # v_replace_id.convert(QtCore.QVariant.UInt)
- # v_actions = QtCore.QVariant([])
- # v_actions.convert(QtCore.QVariant.StringList)
- # if self.tray_notifier_type == "KDE":
- # message = message.replace('\n', '
\n')
- # self.tray_notifier.call("Notify", "Qubes", v_replace_id,
- # "qubes-manager", "Qubes VM Manager",
- # message, v_actions, QtCore.QVariant.fromMap({}), msecs)
- pass
-
- def create_action(self, text, slot=None, shortcut=None, icon=None,
- tip=None, checkable=False, signal="triggered()"):
- action = QtGui.QAction(text, self)
- if icon is not None:
- action.setIcon(QtGui.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, QtCore.SIGNAL(signal), slot)
- if checkable:
- action.setCheckable(True)
- return action
-
-
-class QubesDbusNotifyServerAdaptor(QDBusAbstractAdaptor):
- """ This provides the DBus adaptor to the outside world"""
-
- # Q_CLASSINFO("D-Bus Interface", dbus_interface)
-
- @QtCore.pyqtSlot(str, str)
- def notify_error(self, vmname, message):
- vm = self.parent().qvm_collection.domains[vmname]
- if vm:
- self.parent().set_error(vm.qid, message)
- else:
- # ignore VM-not-found error
- pass
-
- @QtCore.pyqtSlot(str, str)
- def clear_error_exact(self, vmname, message):
- vm = self.parent().qvm_collection.domains[vmname]
- if vm:
- self.parent().clear_error_exact(vm.qid, message)
- else:
- # ignore VM-not-found error
- pass
-
- @QtCore.pyqtSlot(str)
- def clear_error(self, vmname):
- vm = self.parent().qvm_collection.domains[vmname]
- if vm:
- self.parent().clear_error(vm.qid)
- else:
- # ignore VM-not-found error
- pass
-
- @QtCore.pyqtSlot()
- def show_manager(self):
- bring_manager_to_front()
-
-
-# def get_frame_size():
-# w = 0
-# h = 0
-# cmd = ['/usr/bin/xprop', '-name', 'Qubes VM Manager', '|', 'grep',
-# '_NET_FRAME_EXTENTS']
-# xprop = subprocess.Popen(cmd, stdout=subprocess.PIPE)
-# for l in xprop.stdout:
-# line = l.split('=')
-# if len(line) == 2:
-# line = line[1].strip().split(',')
-# if len(line) == 4:
-# w = int(line[0].strip()) + int(line[1].strip())
-# h = int(line[2].strip()) + int(line[3].strip())
-# break
-# # in case of some weird window managers we have to assume sth...
-# if w <= 0:
-# w = 10
-# if h <= 0:
-# h = 30
-#
-# manager_window.frame_width = w
-# manager_window.frame_height = h
-# return
-
def show_manager():
manager_window.show()
- # manager_window.set_table_geom_size()
manager_window.repaint()
manager_window.update_table(out_of_schedule=True)
app.processEvents()
- # get_frame_size()
- # print manager_window.frame_width, " x ", manager_window.frame_height
- # manager_window.set_table_geom_size()
-
-
-def bring_manager_to_front():
- if manager_window.isVisible():
- subprocess.check_call(
- ['/usr/bin/wmctrl', '-R', str(manager_window.windowTitle())])
-
- else:
- show_manager()
-
-
-def show_running_manager_via_dbus():
- global system_bus
- if system_bus is None:
- system_bus = QDBusConnection.systemBus()
-
- qubes_manager = QDBusInterface('org.qubesos.QubesManager',
- '/org/qubesos/QubesManager',
- 'org.qubesos.QubesManager', system_bus)
- qubes_manager.call('show_manager')
-
def exit_app():
- # notifier.stop()
app.exit()
@@ -2093,42 +1312,17 @@ def sighup_handler(signum, frame):
def main():
signal.signal(signal.SIGHUP, sighup_handler)
- global system_bus
- system_bus = QDBusConnection.systemBus()
- # Avoid starting more than one instance of the app
- # if not system_bus.registerService('org.qubesos.QubesManager'):
- # show_running_manager_via_dbus()
- # return
-
- # global qubes_host
- # qubes_host = QubesHost()
-
global app
app = QtGui.QApplication(sys.argv)
app.setOrganizationName("The Qubes Project")
app.setOrganizationDomain("http://qubes-os.org")
app.setApplicationName("Qubes VM Manager")
app.setWindowIcon(QtGui.QIcon.fromTheme("qubes-manager"))
- # app.setAttribute(Qt.AA_DontShowIconsInMenus, False)
-
- # qt_translator = QTranslator()
- # locale = QLocale.system().name()
- # i18n_dir = os.path.join(
- # os.path.dirname(os.path.realpath(__file__)),
- # 'i18n')
- # qt_translator.load("qubesmanager_{!s}.qm".format(locale), i18n_dir)
- # app.installTranslator(qt_translator)
sys.excepthook = handle_exception
- global session_bus
- session_bus = QDBusConnection.sessionBus()
-
qvm_collection = Qubes()
- global trayIcon
- trayIcon = QubesTrayIcon(QtGui.QIcon.fromTheme("qubes-manager"))
-
global manager_window
manager_window = VmManagerWindow(qvm_collection)
@@ -2150,16 +1344,13 @@ def main():
# wm.add_watch(os.path.dirname(table_widgets.qubes_dom0_updates_stat_file),
# EventsCodes.OP_FLAGS.get('IN_CREATE'))
- system_bus.registerObject(dbus_object_path, manager_window)
-
threading.currentThread().setName("QtMainThread")
- trayIcon.show()
show_manager()
app.exec_()
- trayIcon = None
-
if __name__ == "__main__":
main()
+
+# TODO: change file name to something better
\ No newline at end of file
diff --git a/qubesmanager/table_widgets.py b/qubesmanager/table_widgets.py
index fe2cd49..9acc05e 100644
--- a/qubesmanager/table_widgets.py
+++ b/qubesmanager/table_widgets.py
@@ -23,7 +23,6 @@ from PyQt4 import QtGui
from PyQt4 import QtCore
# TODO: are those needed?
-qubes_dom0_updates_stat_file = '/var/lib/qubes/updates/dom0-updates-available'
power_order = QtCore.Qt.DescendingOrder
update_order = QtCore.Qt.AscendingOrder
@@ -31,7 +30,6 @@ update_order = QtCore.Qt.AscendingOrder
row_height = 30
-# TODO: do I need to find icons?
class VmIconWidget(QtGui.QWidget):
def __init__(self, icon_path, enabled=True, size_multiplier=0.7,
tooltip=None, parent=None, icon_sz=(32, 32)):
@@ -81,7 +79,7 @@ class VmTypeWidget(VmIconWidget):
elif other.vm.qid == 0:
return False
elif self.value == other.value:
- return self.vm.qid < other.vm.qid
+ return self.vm.name < other.vm.name
else:
return self.value < other.value
@@ -137,7 +135,7 @@ class VmLabelWidget(VmIconWidget):
elif other.vm.qid == 0:
return False
elif self.value == other.value:
- return self.vm.qid < other.vm.qid
+ return self.vm.name < other.vm.name
else:
return self.value < other.value
@@ -217,14 +215,14 @@ class VmInfoWidget (QtGui.QWidget):
self_val = self.upd_info_item.value
other_val = other.upd_info_item.value
- # TODO: is this shit needed?
+
if self.tableWidget().\
horizontalHeader().sortIndicatorOrder() == update_order:
# the result will be sorted by upd, sorting order: Ascending
self_val += 1 if self.vm.is_running() else 0
other_val += 1 if other.vm.is_running() else 0
if self_val == other_val:
- return self.vm.qid < other.vm.qid
+ return self.vm.name < other.vm.name
else:
return self_val > other_val
elif self.tableWidget().\
@@ -236,7 +234,7 @@ class VmInfoWidget (QtGui.QWidget):
other_val = -(other_val/10 +
10*(1 if other.vm.is_running() else 0))
if self_val == other_val:
- return self.vm.qid < other.vm.qid
+ return self.vm.name < other.vm.name
else:
return self_val > other_val
else:
@@ -272,19 +270,10 @@ class VmInfoWidget (QtGui.QWidget):
self.tableItem = self.VmInfoItem(self.upd_info.tableItem, vm)
- def update_vm_state(self, vm, blk_visible, rec_visible=None):
+ def update_vm_state(self, vm):
self.on_icon.update()
self.upd_info.update_outdated(vm)
- if blk_visible is not None:
- self.blk_icon.setVisible(blk_visible)
- if rec_visible is not None:
- self.rec_icon.setVisible(rec_visible)
- # TODO: are these needed?
- # self.error_icon.setToolTip(vm.qubes_manager_state[main.QMVmState
- # .ErrorMsg])
- # self.error_icon.setVisible(vm.qubes_manager_state[main.QMVmState
- # .ErrorMsg] is not None)
-
+ # TODO: add updating things like label? name? evrything? size?
# TODO add main to git history as a saner name and with a decent comment
# TODO and rename that shit
@@ -294,7 +283,7 @@ class VmTemplateItem (QtGui.QTableWidgetItem):
self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.vm = vm
- if vm.template is not None:
+ if getattr(vm, 'template', None) is not None:
self.setText(vm.template.name)
else:
font = QtGui.QFont()
@@ -312,7 +301,7 @@ class VmTemplateItem (QtGui.QTableWidgetItem):
elif other.vm.qid == 0:
return False
elif self.text() == other.text():
- return self.vm.qid < other.vm.qid
+ return self.vm.name < other.vm.name
else:
return super(VmTemplateItem, self).__lt__(other)
@@ -325,7 +314,7 @@ class VmNetvmItem (QtGui.QTableWidgetItem):
# TODO: differentiate without no net vm/ no networking?
# TODO: mark provides network somehow?
- if vm.netvm is None:
+ if getattr(vm, 'netvm', None) is None:
self.setText("n/a")
else:
self.setText(vm.netvm.name)
@@ -338,7 +327,7 @@ class VmNetvmItem (QtGui.QTableWidgetItem):
elif other.vm.qid == 0:
return False
elif self.text() == other.text():
- return self.vm.qid < other.vm.qid
+ return self.vm.name < other.vm.name
else:
return super(VmNetvmItem, self).__lt__(other)
@@ -350,7 +339,6 @@ class VmInternalItem(QtGui.QTableWidgetItem):
self.vm = vm
self.internal = vm.features.get('internal', False)
- # TODO: should default be false
self.setText("Yes" if self.internal else "")
@@ -386,7 +374,7 @@ class VmUpdateInfoWidget(QtGui.QWidget):
elif other.vm.qid == 0:
return False
elif self.value == other.value:
- return self.vm.qid < other.vm.qid
+ return self.vm.name < other.vm.name
else:
return self.value < other.value
@@ -419,7 +407,8 @@ class VmUpdateInfoWidget(QtGui.QWidget):
except AttributeError:
pass
- if not outdated_state and vm.template and vm.template.is_running():
+ 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)
@@ -491,24 +480,19 @@ class VmSizeOnDiskItem (QtGui.QTableWidgetItem):
elif other.vm.qid == 0:
return False
elif self.value == other.value:
- return self.vm.qid < other.vm.qid
+ return self.vm.name < other.vm.name
else:
return self.value < other.value
-
+# TODO: replace these widgets with a generic widgets
class VmIPItem(QtGui.QTableWidgetItem):
def __init__(self, vm):
super(VmIPItem, self).__init__()
self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
- # TODO: check if you don't need a try around here
self.vm = vm
- self.ip = self.vm.ip
- if self.ip:
- self.setText(self.ip)
- else:
- self.setText("n/a")
- self.setText("n/a")
+ self.ip = getattr(self.vm, 'ip', None)
+ self.setText(self.ip if self.ip is not None else 'n/a')
def __lt__(self, other):
if self.vm.qid == 0:
@@ -524,7 +508,7 @@ class VmIncludeInBackupsItem(QtGui.QTableWidgetItem):
self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.vm = vm
- if self.vm.include_in_backups:
+ if getattr(self.vm, 'include_in_backups', None):
self.setText("Yes")
else:
self.setText("")
@@ -536,7 +520,7 @@ class VmIncludeInBackupsItem(QtGui.QTableWidgetItem):
elif other.vm.qid == 0:
return False
elif self.vm.include_in_backups == other.vm.include_in_backups:
- return self.vm.qid < other.vm.qid
+ return self.vm.name < other.vm.name
else:
return self.vm.include_in_backups < other.vm.include_in_backups
@@ -547,7 +531,7 @@ class VmLastBackupItem(QtGui.QTableWidgetItem):
self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.vm = vm
- if self.vm.backup_timestamp:
+ if getattr(self.vm, 'backup_timestamp', None):
self.setText(self.vm.backup_timestamp)
else:
self.setText("")
@@ -559,7 +543,7 @@ class VmLastBackupItem(QtGui.QTableWidgetItem):
elif other.vm.qid == 0:
return False
elif self.vm.backup_timestamp == other.vm.backup_timestamp:
- return self.vm.qid < other.vm.qid
+ return self.vm.name < other.vm.name
elif not self.vm.backup_timestamp:
return False
elif not other.vm.backup_timestamp:
diff --git a/rpm_spec/qmgr.spec b/rpm_spec/qmgr.spec
index 6ee0f64..27ed4e5 100644
--- a/rpm_spec/qmgr.spec
+++ b/rpm_spec/qmgr.spec
@@ -64,6 +64,7 @@ rm -rf $RPM_BUILD_ROOT
/usr/bin/qubes-vm-boot-from-device
/usr/bin/qubes-backup
/usr/bin/qubes-backup-restore
+/usr/bin/qubes-template-volume-manager
/usr/libexec/qubes-manager/mount_for_backup.sh
/usr/libexec/qubes-manager/qvm_about.sh
@@ -87,6 +88,7 @@ rm -rf $RPM_BUILD_ROOT
%{python3_sitelib}/qubesmanager/informationnotes.py
%{python3_sitelib}/qubesmanager/create_new_vm.py
%{python3_sitelib}/qubesmanager/thread_monitor.py
+%{python3_sitelib}/qubesmanager/main.py
%{python3_sitelib}/qubesmanager/utils.py
%{python3_sitelib}/qubesmanager/bootfromdevice.py
@@ -104,6 +106,7 @@ rm -rf $RPM_BUILD_ROOT
%{python3_sitelib}/qubesmanager/ui_about.py
%{python3_sitelib}/qubesmanager/ui_releasenotes.py
%{python3_sitelib}/qubesmanager/ui_informationnotes.py
+%{python3_sitelib}/qubesmanager/ui_vtmanager.py
%{python3_sitelib}/qubesmanager/i18n/qubesmanager_*.qm
%{python3_sitelib}/qubesmanager/i18n/qubesmanager_*.ts
diff --git a/setup.py b/setup.py
index c89c898..940e99b 100644
--- a/setup.py
+++ b/setup.py
@@ -23,6 +23,7 @@ if __name__ == '__main__':
'qubes-vm-create = qubesmanager.create_new_vm:main',
'qubes-vm-boot-from-device = qubesmanager.bootfromdevice:main',
'qubes-backup = qubesmanager.backup:main',
- 'qubes-backup-restore = qubesmanager.restore:main'
+ 'qubes-backup-restore = qubesmanager.restore:main',
+ 'qubes-template-volume-manager = qubesmanager.main:main'
],
})
diff --git a/ui/vtmanager.ui b/ui/vtmanager.ui
index 4e89f45..03932fd 100644
--- a/ui/vtmanager.ui
+++ b/ui/vtmanager.ui
@@ -136,7 +136,7 @@
10
- 15
+ 11
false
@@ -209,32 +209,6 @@
VM's netVM
-
-
- CPU
-
-
-
-
- CPU Graph
-
-
- CPU usage graph
-
-
-
-
- MEM
-
-
-
-
- MEM Graph
-
-
- Memory usage graph
-
-
Size
@@ -295,10 +269,6 @@
-
-
-
-