Merge branch 'master' of git.qubes-os.org:/var/lib/qubes/git/aga/qubes-manager
This commit is contained in:
commit
4eba458723
BIN
icons/appvm.png
BIN
icons/appvm.png
Binary file not shown.
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 32 KiB |
BIN
icons/hvm.png
Normal file
BIN
icons/hvm.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
BIN
icons/kill.png
Normal file
BIN
icons/kill.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
BIN
icons/proxyvm.png
Normal file
BIN
icons/proxyvm.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
BIN
icons/standalonevm.png
Normal file
BIN
icons/standalonevm.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
@ -151,6 +151,11 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
</column>
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
<column>
|
<column>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Name</string>
|
<string>Name</string>
|
||||||
@ -267,6 +272,7 @@
|
|||||||
<addaction name="action_resumevm"/>
|
<addaction name="action_resumevm"/>
|
||||||
<addaction name="action_pausevm"/>
|
<addaction name="action_pausevm"/>
|
||||||
<addaction name="action_shutdownvm"/>
|
<addaction name="action_shutdownvm"/>
|
||||||
|
<addaction name="action_killvm"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="action_settings"/>
|
<addaction name="action_settings"/>
|
||||||
<addaction name="action_editfwrules"/>
|
<addaction name="action_editfwrules"/>
|
||||||
@ -318,7 +324,7 @@
|
|||||||
<string>Start/Resume VM</string>
|
<string>Start/Resume VM</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Start/Resume a VM</string>
|
<string>Start/Resume selected VM</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_pausevm">
|
<action name="action_pausevm">
|
||||||
@ -333,7 +339,7 @@
|
|||||||
<string>Pause VM</string>
|
<string>Pause VM</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Pause a running VM</string>
|
<string>Pause selected VM</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_shutdownvm">
|
<action name="action_shutdownvm">
|
||||||
@ -348,7 +354,7 @@
|
|||||||
<string>Shutdown VM</string>
|
<string>Shutdown VM</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Shutdown a running VM</string>
|
<string>Shutdown selected VM</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_appmenus">
|
<action name="action_appmenus">
|
||||||
@ -386,7 +392,7 @@
|
|||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="checked">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="resources.qrc">
|
<iconset resource="resources.qrc">
|
||||||
@ -553,6 +559,18 @@
|
|||||||
<string>State</string>
|
<string>State</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="action_killvm">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="resources.qrc">
|
||||||
|
<normaloff>:/killvm.png</normaloff>:/killvm.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Kill VM</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Kill selected VM</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="resources.qrc"/>
|
<include location="resources.qrc"/>
|
||||||
|
@ -51,7 +51,7 @@ def mount_device(dev_path):
|
|||||||
pmount_cmd = [mount_for_backup_path, dev_path, mount_dir_name]
|
pmount_cmd = [mount_for_backup_path, dev_path, mount_dir_name]
|
||||||
res = subprocess.check_call(pmount_cmd)
|
res = subprocess.check_call(pmount_cmd)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
QMessageBox.warning (None, "Error mounting selected device!", "ERROR: {0}".format(ex))
|
QMessageBox.warning (None, "Error mounting selected device!", "<b>Could not mount {0}.</b><br><br>ERROR: {1}".format(dev_path, ex))
|
||||||
return None
|
return None
|
||||||
if res == 0:
|
if res == 0:
|
||||||
dev_mount_path = "/media/"+mount_dir_name
|
dev_mount_path = "/media/"+mount_dir_name
|
||||||
@ -59,14 +59,21 @@ def mount_device(dev_path):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def umount_device(dev_mount_path):
|
def umount_device(dev_mount_path):
|
||||||
try:
|
while True:
|
||||||
pumount_cmd = ["pumount", dev_mount_path]
|
try:
|
||||||
res = subprocess.check_call(pumount_cmd)
|
pumount_cmd = ["pumount", "--luks-force", dev_mount_path]
|
||||||
if res == 0:
|
res = subprocess.check_call(pumount_cmd)
|
||||||
dev_mount_path = None
|
if res == 0:
|
||||||
except Exception as ex:
|
dev_mount_path = None
|
||||||
QMessageBox.warning (None, "Could not unmount backup device!", "ERROR: {0}".format(ex))
|
return dev_mount_path
|
||||||
return dev_mount_path
|
except Exception as ex:
|
||||||
|
title = "Error unmounting backup device!"
|
||||||
|
text = "<b>Could not unmount {0}.</b><br>\
|
||||||
|
<b>Please retry or unmount it manually using</b><br> pumount {0}.<br><br>\
|
||||||
|
ERROR: {1}".format(dev_mount_path, ex)
|
||||||
|
button = QMessageBox.warning (None, title, text, QMessageBox.Ok | QMessageBox.Retry, QMessageBox.Retry)
|
||||||
|
if button == QMessageBox.Ok:
|
||||||
|
return dev_mount_path
|
||||||
|
|
||||||
|
|
||||||
def fill_devs_list(dialog):
|
def fill_devs_list(dialog):
|
||||||
|
@ -68,7 +68,7 @@ class QubesConfigFileWatcher(ProcessEvent):
|
|||||||
|
|
||||||
|
|
||||||
class VmIconWidget (QWidget):
|
class VmIconWidget (QWidget):
|
||||||
def __init__(self, icon_path, enabled=True, size_multiplier=0.7, parent=None):
|
def __init__(self, icon_path, enabled=True, size_multiplier=0.7, tooltip = None, parent=None):
|
||||||
super(VmIconWidget, self).__init__(parent)
|
super(VmIconWidget, self).__init__(parent)
|
||||||
|
|
||||||
label_icon = QLabel()
|
label_icon = QLabel()
|
||||||
@ -77,6 +77,8 @@ class VmIconWidget (QWidget):
|
|||||||
icon_pixmap = icon.pixmap(icon_sz, QIcon.Disabled if not enabled else QIcon.Normal)
|
icon_pixmap = icon.pixmap(icon_sz, QIcon.Disabled if not enabled else QIcon.Normal)
|
||||||
label_icon.setPixmap (icon_pixmap)
|
label_icon.setPixmap (icon_pixmap)
|
||||||
label_icon.setFixedSize (icon_sz)
|
label_icon.setFixedSize (icon_sz)
|
||||||
|
if tooltip != None:
|
||||||
|
label_icon.setToolTip(tooltip)
|
||||||
|
|
||||||
layout = QHBoxLayout()
|
layout = QHBoxLayout()
|
||||||
layout.addWidget(label_icon)
|
layout.addWidget(label_icon)
|
||||||
@ -84,6 +86,50 @@ class VmIconWidget (QWidget):
|
|||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
|
||||||
|
class VmTypeWidget(VmIconWidget):
|
||||||
|
|
||||||
|
class VmTypeItem(QTableWidgetItem):
|
||||||
|
def __init__(self, value):
|
||||||
|
super(VmTypeWidget.VmTypeItem, self).__init__()
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
def set_value(self, value):
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
return self.value < other.value
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, vm, parent=None):
|
||||||
|
(icon_path, tooltip) = self.get_vm_icon(vm)
|
||||||
|
super (VmTypeWidget, self).__init__(icon_path, True, 0.9, tooltip, parent)
|
||||||
|
self.vm = vm
|
||||||
|
self.tableItem = self.VmTypeItem(self.value)
|
||||||
|
|
||||||
|
def get_vm_icon(self, vm):
|
||||||
|
if vm.qid == 0:
|
||||||
|
self.value = 0
|
||||||
|
return (":/dom0.png", "Dom0")
|
||||||
|
elif vm.is_netvm() and not vm.is_proxyvm():
|
||||||
|
self.value = 1
|
||||||
|
return (":/netvm.png", "NetVM")
|
||||||
|
elif vm.is_proxyvm():
|
||||||
|
self.value = 2
|
||||||
|
return (":/proxyvm.png", "ProxyVM")
|
||||||
|
elif vm.is_template():
|
||||||
|
self.value = 3
|
||||||
|
return (":/templatevm.png", "TemplateVM")
|
||||||
|
elif vm.is_appvm() and vm.template is None:
|
||||||
|
self.value = 4
|
||||||
|
return (":/standalonevm.png", "StandaloneVM")
|
||||||
|
elif vm.type == "HVM":
|
||||||
|
self.value = 5
|
||||||
|
return (":/hvm.png", "HVM")
|
||||||
|
elif vm.is_appvm() or vm.is_disposablevm():
|
||||||
|
self.value = 5 + vm.label.index
|
||||||
|
return (":/off.png", "AppVM")
|
||||||
|
|
||||||
|
|
||||||
class VmLabelWidget(VmIconWidget):
|
class VmLabelWidget(VmIconWidget):
|
||||||
|
|
||||||
class VmLabelItem(QTableWidgetItem):
|
class VmLabelItem(QTableWidgetItem):
|
||||||
@ -100,23 +146,14 @@ class VmLabelWidget(VmIconWidget):
|
|||||||
|
|
||||||
def __init__(self, vm, parent=None):
|
def __init__(self, vm, parent=None):
|
||||||
icon_path = self.get_vm_icon_path(vm)
|
icon_path = self.get_vm_icon_path(vm)
|
||||||
super (VmLabelWidget, self).__init__(icon_path, True, 0.8, parent)
|
super (VmLabelWidget, self).__init__(icon_path, True, 0.8, None, parent)
|
||||||
self.vm = vm
|
self.vm = vm
|
||||||
self.tableItem = self.VmLabelItem(self.value)
|
self.tableItem = self.VmLabelItem(self.value)
|
||||||
|
|
||||||
def get_vm_icon_path(self, vm):
|
def get_vm_icon_path(self, vm):
|
||||||
if vm.qid == 0:
|
self.value = vm.label.index
|
||||||
self.value = 0
|
return vm.label.icon_path
|
||||||
return ":/dom0.png"
|
|
||||||
elif vm.is_netvm():
|
|
||||||
self.value = 1
|
|
||||||
return ":/netvm.png"
|
|
||||||
elif vm.is_template():
|
|
||||||
self.value = 2
|
|
||||||
return ":/templatevm.png"
|
|
||||||
elif vm.is_appvm() or vm.is_disposablevm():
|
|
||||||
self.value = 2 + vm.label.index
|
|
||||||
return vm.label.icon_path
|
|
||||||
|
|
||||||
|
|
||||||
class VmNameItem (QTableWidgetItem):
|
class VmNameItem (QTableWidgetItem):
|
||||||
@ -143,7 +180,7 @@ class VmStatusIcon(QLabel):
|
|||||||
def set_on_icon(self):
|
def set_on_icon(self):
|
||||||
if self.vm.last_power_state == "Running":
|
if self.vm.last_power_state == "Running":
|
||||||
icon = QIcon (":/on.png")
|
icon = QIcon (":/on.png")
|
||||||
elif self.vm.last_power_state in ["Starting", "Halting", "Dying"]:
|
elif self.vm.last_power_state in ["Transient", "Halting", "Dying"]:
|
||||||
icon = QIcon (":/transient.png")
|
icon = QIcon (":/transient.png")
|
||||||
else:
|
else:
|
||||||
icon = QIcon (":/off.png")
|
icon = QIcon (":/off.png")
|
||||||
@ -406,11 +443,15 @@ class VmUpdateInfoWidget(QWidget):
|
|||||||
self.tableItem = VmUpdateInfoWidget.VmUpdateInfoItem(self.value)
|
self.tableItem = VmUpdateInfoWidget.VmUpdateInfoItem(self.value)
|
||||||
|
|
||||||
def update_outdated(self, vm):
|
def update_outdated(self, vm):
|
||||||
|
if vm.type == "HVM":
|
||||||
|
return
|
||||||
|
|
||||||
outdated = vm.is_outdated()
|
outdated = vm.is_outdated()
|
||||||
if outdated and not self.previous_outdated:
|
if outdated and not self.previous_outdated:
|
||||||
self.update_status_widget("outdated")
|
self.update_status_widget("outdated")
|
||||||
|
|
||||||
self.previous_outdated = outdated
|
self.previous_outdated = outdated
|
||||||
|
|
||||||
if vm.is_updateable():
|
if vm.is_updateable():
|
||||||
update_recommended = self.previous_update_recommended
|
update_recommended = self.previous_update_recommended
|
||||||
stat_file = vm.dir_path + '/' + updates_stat_file
|
stat_file = vm.dir_path + '/' + updates_stat_file
|
||||||
@ -464,6 +505,10 @@ class VmRowInTable(object):
|
|||||||
|
|
||||||
table.setRowHeight (row_no, VmManagerWindow.row_height)
|
table.setRowHeight (row_no, VmManagerWindow.row_height)
|
||||||
|
|
||||||
|
self.type_widget = VmTypeWidget(vm)
|
||||||
|
table.setCellWidget(row_no, VmManagerWindow.columns_indices['Type'], self.type_widget)
|
||||||
|
table.setItem(row_no, VmManagerWindow.columns_indices['Type'], self.type_widget.tableItem)
|
||||||
|
|
||||||
self.label_widget = VmLabelWidget(vm)
|
self.label_widget = VmLabelWidget(vm)
|
||||||
table.setCellWidget(row_no, VmManagerWindow.columns_indices['Label'], self.label_widget)
|
table.setCellWidget(row_no, VmManagerWindow.columns_indices['Label'], self.label_widget)
|
||||||
table.setItem(row_no, VmManagerWindow.columns_indices['Label'], self.label_widget.tableItem)
|
table.setItem(row_no, VmManagerWindow.columns_indices['Label'], self.label_widget.tableItem)
|
||||||
@ -543,15 +588,16 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
|
|||||||
min_visible_rows = 10
|
min_visible_rows = 10
|
||||||
update_interval = 1000 # in msec
|
update_interval = 1000 # in msec
|
||||||
show_inactive_vms = True
|
show_inactive_vms = True
|
||||||
columns_indices = { "Label": 0,
|
columns_indices = { "Type": 0,
|
||||||
"Name": 1,
|
"Label": 1,
|
||||||
"State": 2,
|
"Name": 2,
|
||||||
"Template": 3,
|
"State": 3,
|
||||||
"NetVM": 4,
|
"Template": 4,
|
||||||
"CPU": 5,
|
"NetVM": 5,
|
||||||
"CPU Graph": 6,
|
"CPU": 6,
|
||||||
"MEM": 7,
|
"CPU Graph": 7,
|
||||||
"MEM Graph": 8,}
|
"MEM": 8,
|
||||||
|
"MEM Graph": 9,}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -596,11 +642,12 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
|
|||||||
self.actionMEM_Graph.setChecked(False)
|
self.actionMEM_Graph.setChecked(False)
|
||||||
self.table.setColumnWidth(self.columns_indices["State"], 80)
|
self.table.setColumnWidth(self.columns_indices["State"], 80)
|
||||||
self.table.setColumnWidth(self.columns_indices["Name"], 150)
|
self.table.setColumnWidth(self.columns_indices["Name"], 150)
|
||||||
self.table.setColumnWidth(self.columns_indices["Label"], 50)
|
self.table.setColumnWidth(self.columns_indices["Label"], 40)
|
||||||
|
self.table.setColumnWidth(self.columns_indices["Type"], 40)
|
||||||
|
|
||||||
self.table.horizontalHeader().setResizeMode(QHeaderView.Fixed)
|
self.table.horizontalHeader().setResizeMode(QHeaderView.Fixed)
|
||||||
|
|
||||||
self.table.sortItems(self.columns_indices["Label"], Qt.AscendingOrder)
|
self.table.sortItems(self.columns_indices["Type"], Qt.AscendingOrder)
|
||||||
|
|
||||||
self.context_menu = QMenu(self)
|
self.context_menu = QMenu(self)
|
||||||
self.context_menu.addAction(self.action_settings)
|
self.context_menu.addAction(self.action_settings)
|
||||||
@ -608,19 +655,31 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
|
|||||||
self.context_menu.addAction(self.action_resumevm)
|
self.context_menu.addAction(self.action_resumevm)
|
||||||
self.context_menu.addAction(self.action_pausevm)
|
self.context_menu.addAction(self.action_pausevm)
|
||||||
self.context_menu.addAction(self.action_shutdownvm)
|
self.context_menu.addAction(self.action_shutdownvm)
|
||||||
|
self.context_menu.addAction(self.action_killvm)
|
||||||
self.context_menu.addAction(self.action_appmenus)
|
self.context_menu.addAction(self.action_appmenus)
|
||||||
self.context_menu.addAction(self.action_editfwrules)
|
self.context_menu.addAction(self.action_editfwrules)
|
||||||
self.context_menu.addAction(self.action_updatevm)
|
self.context_menu.addAction(self.action_updatevm)
|
||||||
|
|
||||||
self.table_selection_changed()
|
self.table_selection_changed()
|
||||||
|
|
||||||
|
self.logs_menu = QMenu("Logs")
|
||||||
|
log_icon = QtGui.QIcon()
|
||||||
|
log_icon.addPixmap(QPixmap(":/log.png"))
|
||||||
|
self.logs_menu.setIcon(log_icon)
|
||||||
|
self.context_menu.addMenu(self.logs_menu)
|
||||||
|
|
||||||
|
|
||||||
self.blk_menu = QMenu("Block devices")
|
self.blk_menu = QMenu("Block devices")
|
||||||
|
blk_icon = QtGui.QIcon()
|
||||||
|
blk_icon.addPixmap(QPixmap(":/mount.png"))
|
||||||
|
self.blk_menu.setIcon(blk_icon)
|
||||||
self.context_menu.addMenu(self.blk_menu)
|
self.context_menu.addMenu(self.blk_menu)
|
||||||
self.context_menu.addSeparator()
|
self.context_menu.addSeparator()
|
||||||
|
|
||||||
self.connect(self.table.horizontalHeader(), SIGNAL("sortIndicatorChanged(int, Qt::SortOrder)"), self.sortIndicatorChanged)
|
self.connect(self.table.horizontalHeader(), SIGNAL("sortIndicatorChanged(int, Qt::SortOrder)"), self.sortIndicatorChanged)
|
||||||
self.connect(self.table, SIGNAL("customContextMenuRequested(const QPoint&)"), self.open_context_menu)
|
self.connect(self.table, SIGNAL("customContextMenuRequested(const QPoint&)"), self.open_context_menu)
|
||||||
self.connect(self.blk_menu, SIGNAL("triggered(QAction *)"), self.attach_dettach_device_triggered)
|
self.connect(self.blk_menu, SIGNAL("triggered(QAction *)"), self.attach_dettach_device_triggered)
|
||||||
|
self.connect(self.logs_menu, SIGNAL("triggered(QAction *)"), self.show_log)
|
||||||
|
|
||||||
self.table.setContentsMargins(0,0,0,0)
|
self.table.setContentsMargins(0,0,0,0)
|
||||||
self.centralwidget.layout().setContentsMargins(0,0,0,0)
|
self.centralwidget.layout().setContentsMargins(0,0,0,0)
|
||||||
@ -718,7 +777,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
|
|||||||
vms_list = [vm for vm in self.qvm_collection.values()]
|
vms_list = [vm for vm in self.qvm_collection.values()]
|
||||||
for vm in vms_list:
|
for vm in vms_list:
|
||||||
vm.last_power_state = vm.get_power_state()
|
vm.last_power_state = vm.get_power_state()
|
||||||
vm.last_running = vm.last_power_state in ["Running", "Starting"]
|
vm.last_running = vm.last_power_state in ["Running", "Transient"]
|
||||||
|
|
||||||
no_vms = len (vms_list)
|
no_vms = len (vms_list)
|
||||||
vms_to_display = []
|
vms_to_display = []
|
||||||
@ -781,7 +840,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
|
|||||||
state = vm.get_power_state()
|
state = vm.get_power_state()
|
||||||
if vm.last_power_state != state:
|
if vm.last_power_state != state:
|
||||||
vm.last_power_state = state
|
vm.last_power_state = state
|
||||||
vm.last_running = (state in ["Running", "Starting"])
|
vm.last_running = (state in ["Running", "Transient"])
|
||||||
some_vms_have_changed_power_state = True
|
some_vms_have_changed_power_state = True
|
||||||
|
|
||||||
reload_table = self.reload_table
|
reload_table = self.reload_table
|
||||||
@ -896,6 +955,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
|
|||||||
self.action_resumevm.setEnabled(not vm.last_running)
|
self.action_resumevm.setEnabled(not vm.last_running)
|
||||||
self.action_pausevm.setEnabled(vm.last_running and vm.qid != 0)
|
self.action_pausevm.setEnabled(vm.last_running and vm.qid != 0)
|
||||||
self.action_shutdownvm.setEnabled(vm.last_running and vm.qid != 0)
|
self.action_shutdownvm.setEnabled(vm.last_running and vm.qid != 0)
|
||||||
|
self.action_killvm.setEnabled(vm.last_running and vm.qid != 0)
|
||||||
self.action_appmenus.setEnabled(not vm.is_netvm())
|
self.action_appmenus.setEnabled(not vm.is_netvm())
|
||||||
self.action_editfwrules.setEnabled(vm.is_networked() and not (vm.is_netvm() and not vm.is_proxyvm()))
|
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)
|
self.action_updatevm.setEnabled(vm.is_updateable() or vm.qid == 0)
|
||||||
@ -905,6 +965,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
|
|||||||
self.action_resumevm.setEnabled(False)
|
self.action_resumevm.setEnabled(False)
|
||||||
self.action_pausevm.setEnabled(False)
|
self.action_pausevm.setEnabled(False)
|
||||||
self.action_shutdownvm.setEnabled(False)
|
self.action_shutdownvm.setEnabled(False)
|
||||||
|
self.action_killvm.setEnabled(False)
|
||||||
self.action_appmenus.setEnabled(False)
|
self.action_appmenus.setEnabled(False)
|
||||||
self.action_editfwrules.setEnabled(False)
|
self.action_editfwrules.setEnabled(False)
|
||||||
self.action_updatevm.setEnabled(False)
|
self.action_updatevm.setEnabled(False)
|
||||||
@ -1170,6 +1231,28 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
|
|||||||
QTimer.singleShot (vm_shutdown_timeout, self.shutdown_monitor[vm.qid].check_if_vm_has_shutdown)
|
QTimer.singleShot (vm_shutdown_timeout, self.shutdown_monitor[vm.qid].check_if_vm_has_shutdown)
|
||||||
|
|
||||||
|
|
||||||
|
@pyqtSlot(name='on_action_killvm_triggered')
|
||||||
|
def action_killvm_triggered(self):
|
||||||
|
vm = self.get_selected_vm()
|
||||||
|
assert vm.is_running()
|
||||||
|
|
||||||
|
reply = QMessageBox.question(None, "VM Kill Confirmation",
|
||||||
|
"Are you sure you want to kill the VM <b>'{0}'</b>?<br>"
|
||||||
|
"<small>This will end <b>(not shutdown!)</b> all the running applications within this VM.</small>".format(vm.name),
|
||||||
|
QMessageBox.Yes | QMessageBox.Cancel, QMessageBox.Cancel)
|
||||||
|
|
||||||
|
app.processEvents()
|
||||||
|
|
||||||
|
if reply == QMessageBox.Yes:
|
||||||
|
try:
|
||||||
|
vm.force_shutdown()
|
||||||
|
except Exception as ex:
|
||||||
|
QMessageBox.critical (None, "Error while killing VM!", "<b>An exception ocurred while killing {0}.</b><br>ERROR: {1}".format(vm.name, ex))
|
||||||
|
return
|
||||||
|
|
||||||
|
trayIcon.showMessage ("Qubes Manager", "VM '{0}' killed!".format(vm.name), msecs=3000)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@pyqtSlot(name='on_action_settings_triggered')
|
@pyqtSlot(name='on_action_settings_triggered')
|
||||||
def action_settings_triggered(self):
|
def action_settings_triggered(self):
|
||||||
@ -1311,7 +1394,46 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
|
|||||||
@pyqtSlot('const QPoint&')
|
@pyqtSlot('const QPoint&')
|
||||||
def open_context_menu(self, point):
|
def open_context_menu(self, point):
|
||||||
vm = self.get_selected_vm()
|
vm = self.get_selected_vm()
|
||||||
if not vm.is_running():
|
|
||||||
|
running = vm.is_running()
|
||||||
|
|
||||||
|
#logs menu
|
||||||
|
self.logs_menu.clear()
|
||||||
|
if vm.qid == 0:
|
||||||
|
text = "/var/log/xen/console/hypervisor.log"
|
||||||
|
action = self.logs_menu.addAction(QIcon(":/log.png"), text)
|
||||||
|
action.setData(QVariant(text))
|
||||||
|
self.logs_menu.setEnabled(True)
|
||||||
|
else:
|
||||||
|
menu_empty = True
|
||||||
|
text = "/var/log/xen/console/guest-"+vm.name+".log"
|
||||||
|
if os.path.exists(text):
|
||||||
|
action = self.logs_menu.addAction(QIcon(":/log.png"), text)
|
||||||
|
action.setData(QVariant(text))
|
||||||
|
menu_empty = False
|
||||||
|
|
||||||
|
text = "/var/log/xen/console/guest-"+vm.name+"-dm.log"
|
||||||
|
if os.path.exists(text):
|
||||||
|
action = self.logs_menu.addAction(QIcon(":/log.png"), text)
|
||||||
|
action.setData(QVariant(text))
|
||||||
|
menu_empty = False
|
||||||
|
|
||||||
|
if running:
|
||||||
|
xid = vm.xid
|
||||||
|
if xid != None:
|
||||||
|
text = "/var/log/qubes/guid."+str(xid)+".log"
|
||||||
|
action = self.logs_menu.addAction(QIcon(":/log.png"), text)
|
||||||
|
action.setData(QVariant(text))
|
||||||
|
|
||||||
|
text = "/var/log/qubes/qrexec."+str(xid)+".log"
|
||||||
|
action = self.logs_menu.addAction(QIcon(":/log.png"), text)
|
||||||
|
action.setData(QVariant(text))
|
||||||
|
|
||||||
|
menu_empty = False
|
||||||
|
self.logs_menu.setEnabled(not menu_empty)
|
||||||
|
|
||||||
|
# blk menu
|
||||||
|
if not running:
|
||||||
self.blk_menu.setEnabled(False)
|
self.blk_menu.setEnabled(False)
|
||||||
else:
|
else:
|
||||||
self.blk_menu.clear()
|
self.blk_menu.clear()
|
||||||
@ -1321,16 +1443,16 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
|
|||||||
if len(self.blk_manager.attached_devs) > 0 :
|
if len(self.blk_manager.attached_devs) > 0 :
|
||||||
for d in self.blk_manager.attached_devs:
|
for d in self.blk_manager.attached_devs:
|
||||||
if self.blk_manager.attached_devs[d]['attached_to']['vm'] == vm.name:
|
if self.blk_manager.attached_devs[d]['attached_to']['vm'] == vm.name:
|
||||||
str = "Detach " + d + " " + unicode(self.blk_manager.attached_devs[d]['size']) + " " + self.blk_manager.attached_devs[d]['desc']
|
text = "Detach " + d + " " + unicode(self.blk_manager.attached_devs[d]['size']) + " " + self.blk_manager.attached_devs[d]['desc']
|
||||||
action = self.blk_menu.addAction(QIcon(":/remove.png"), str)
|
action = self.blk_menu.addAction(QIcon(":/remove.png"), text)
|
||||||
action.setData(QVariant(d))
|
action.setData(QVariant(d))
|
||||||
|
|
||||||
if len(self.blk_manager.free_devs) > 0:
|
if len(self.blk_manager.free_devs) > 0:
|
||||||
for d in self.blk_manager.free_devs:
|
for d in self.blk_manager.free_devs:
|
||||||
if d.startswith(vm.name):
|
if d.startswith(vm.name):
|
||||||
continue
|
continue
|
||||||
str = "Attach " + d + " " + unicode(self.blk_manager.free_devs[d]['size']) + " " + self.blk_manager.free_devs[d]['desc']
|
text = "Attach " + d + " " + unicode(self.blk_manager.free_devs[d]['size']) + " " + self.blk_manager.free_devs[d]['desc']
|
||||||
action = self.blk_menu.addAction(QIcon(":/add.png"), str)
|
action = self.blk_menu.addAction(QIcon(":/add.png"), text)
|
||||||
action.setData(QVariant(d))
|
action.setData(QVariant(d))
|
||||||
|
|
||||||
self.blk_manager.blk_lock.release()
|
self.blk_manager.blk_lock.release()
|
||||||
@ -1340,6 +1462,14 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
|
|||||||
|
|
||||||
self.context_menu.exec_(self.table.mapToGlobal(point))
|
self.context_menu.exec_(self.table.mapToGlobal(point))
|
||||||
|
|
||||||
|
@pyqtSlot('QAction *')
|
||||||
|
def show_log(self, action):
|
||||||
|
log = str(action.data().toString())
|
||||||
|
|
||||||
|
cmd = ['kdialog', '--textbox', log, '700', '450', '--title', log]
|
||||||
|
subprocess.Popen(cmd)
|
||||||
|
|
||||||
|
|
||||||
@pyqtSlot('QAction *')
|
@pyqtSlot('QAction *')
|
||||||
def attach_dettach_device_triggered(self, action):
|
def attach_dettach_device_triggered(self, action):
|
||||||
dev = str(action.data().toString())
|
dev = str(action.data().toString())
|
||||||
|
@ -249,6 +249,12 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
|
|||||||
|
|
||||||
self.include_in_backups.setChecked(self.vm.include_in_backups)
|
self.include_in_backups.setChecked(self.vm.include_in_backups)
|
||||||
|
|
||||||
|
if hasattr(self.vm, 'debug'):
|
||||||
|
self.run_in_debug_mode.setVisible(True)
|
||||||
|
self.run_in_debug_mode.setChecked(self.vm.debug)
|
||||||
|
else:
|
||||||
|
self.run_in_debug_mode.setVisible(False)
|
||||||
|
|
||||||
#type
|
#type
|
||||||
self.type_label.setText(self.vm.type)
|
self.type_label.setText(self.vm.type)
|
||||||
|
|
||||||
@ -329,6 +335,13 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
|
|||||||
#include in backups
|
#include in backups
|
||||||
if self.vm.include_in_backups != self.include_in_backups.isChecked():
|
if self.vm.include_in_backups != self.include_in_backups.isChecked():
|
||||||
self.vm.include_in_backups = self.include_in_backups.isChecked()
|
self.vm.include_in_backups = self.include_in_backups.isChecked()
|
||||||
|
self.anything_changed = True
|
||||||
|
|
||||||
|
#run_in_debug_mode
|
||||||
|
if self.run_in_debug_mode.isVisible():
|
||||||
|
if self.vm.debug != self.run_in_debug_mode.isChecked():
|
||||||
|
self.vm.debug = self.run_in_debug_mode.isChecked()
|
||||||
|
self.anything_changed = True
|
||||||
|
|
||||||
#max priv storage
|
#max priv storage
|
||||||
priv_size = self.max_priv_storage.value()
|
priv_size = self.max_priv_storage.value()
|
||||||
@ -374,32 +387,29 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
|
|||||||
|
|
||||||
#kernel
|
#kernel
|
||||||
|
|
||||||
#in case VM is not Linux
|
#in case VM is HVM
|
||||||
if not hasattr(self.vm, "kernel"):
|
if not hasattr(self.vm, "kernel"):
|
||||||
self.kernel_groupbox.setVisible(False)
|
self.kernel_groupbox.setVisible(False)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if self.vm.template is not None:
|
# construct available kernels list
|
||||||
text = self.vm.kernel
|
text = "default (" + self.qvm_collection.get_default_kernel() +")"
|
||||||
self.kernel.insertItem(0, text)
|
kernel_list = [text]
|
||||||
self.kernel.setEnabled(False)
|
for k in os.listdir(qubes_kernels_base_dir):
|
||||||
self.kernel_idx = 0
|
kernel_list.append(k)
|
||||||
else:
|
kernel_list.append("none")
|
||||||
text = "default (" + self.qvm_collection.get_default_kernel() +")"
|
|
||||||
kernel_list = [text]
|
self.kernel_idx = 0
|
||||||
for k in os.listdir(qubes_kernels_base_dir):
|
|
||||||
kernel_list.append(k)
|
# put available kernels to a combobox
|
||||||
kernel_list.append("none")
|
for (i, k) in enumerate(kernel_list):
|
||||||
|
text = k
|
||||||
self.kernel_idx = 0
|
# and mark the current choice
|
||||||
|
if (text.startswith("default") and self.vm.uses_default_kernel) or ( self.vm.kernel == k and not self.vm.uses_default_kernel) or (k=="none" and self.vm.kernel==None):
|
||||||
for (i, k) in enumerate(kernel_list):
|
text += " (current)"
|
||||||
text = k
|
self.kernel_idx = i
|
||||||
if (text.startswith("default") and self.vm.uses_default_kernel) or ( self.vm.kernel == k and not self.vm.uses_default_kernel) or (k=="none" and self.vm.kernel==None):
|
self.kernel.insertItem(i,text)
|
||||||
text += " (current)"
|
self.kernel.setCurrentIndex(self.kernel_idx)
|
||||||
self.kernel_idx = i
|
|
||||||
self.kernel.insertItem(i,text)
|
|
||||||
self.kernel.setCurrentIndex(self.kernel_idx)
|
|
||||||
|
|
||||||
#kernel opts
|
#kernel opts
|
||||||
if self.vm.uses_default_kernelopts:
|
if self.vm.uses_default_kernelopts:
|
||||||
@ -432,6 +442,9 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
#kernel changed
|
#kernel changed
|
||||||
|
if not self.kernel_groupbox.isVisible():
|
||||||
|
return
|
||||||
|
|
||||||
if self.kernel.currentIndex() != self.kernel_idx:
|
if self.kernel.currentIndex() != self.kernel_idx:
|
||||||
new_kernel = self.kernel.currentText()
|
new_kernel = self.kernel.currentText()
|
||||||
new_kernel = new_kernel.split(' ')[0]
|
new_kernel = new_kernel.split(' ')[0]
|
||||||
@ -448,6 +461,7 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
|
|||||||
self.vm.kernel = kernel
|
self.vm.kernel = kernel
|
||||||
self.anything_changed = True
|
self.anything_changed = True
|
||||||
|
|
||||||
|
|
||||||
######## devices tab
|
######## devices tab
|
||||||
def __init_devices_tab__(self):
|
def __init_devices_tab__(self):
|
||||||
self.dev_list = MultiSelectWidget(self)
|
self.dev_list = MultiSelectWidget(self)
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
<file alias="on-old.png">icons/on-icon/on.png</file>
|
<file alias="on-old.png">icons/on-icon/on.png</file>
|
||||||
<file alias="show-all-running.png">icons/on-icon/show-all-running.png</file>
|
<file alias="show-all-running.png">icons/on-icon/show-all-running.png</file>
|
||||||
<file alias="mount.png">icons/mount.png</file>
|
<file alias="mount.png">icons/mount.png</file>
|
||||||
|
<file alias="log.png">icons/log.png</file>
|
||||||
<file alias="pencil.png">icons/pencil.png</file>
|
<file alias="pencil.png">icons/pencil.png</file>
|
||||||
<file alias="redfirewall.png">icons/redfirewall.png</file>
|
<file alias="redfirewall.png">icons/redfirewall.png</file>
|
||||||
<file alias="edit.png">icons/edit.png</file>
|
<file alias="edit.png">icons/edit.png</file>
|
||||||
@ -25,6 +26,9 @@
|
|||||||
<file alias="qubes.png">icons/qubes.png</file>
|
<file alias="qubes.png">icons/qubes.png</file>
|
||||||
<file alias="appvm.png">icons/appvm.png</file>
|
<file alias="appvm.png">icons/appvm.png</file>
|
||||||
<file alias="netvm.png">icons/netvm.png</file>
|
<file alias="netvm.png">icons/netvm.png</file>
|
||||||
|
<file alias="hvm.png">icons/hvm.png</file>
|
||||||
|
<file alias="proxyvm.png">icons/proxyvm.png</file>
|
||||||
|
<file alias="standalonevm.png">icons/standalonevm.png</file>
|
||||||
<file alias="networking.png">icons/networking.png</file>
|
<file alias="networking.png">icons/networking.png</file>
|
||||||
<file alias="dom0.png">icons/dom0.png</file>
|
<file alias="dom0.png">icons/dom0.png</file>
|
||||||
<file alias="storagevm.png">icons/storagevm.png</file>
|
<file alias="storagevm.png">icons/storagevm.png</file>
|
||||||
@ -35,9 +39,9 @@
|
|||||||
<file alias="createvm.png">icons/createvm.png</file>
|
<file alias="createvm.png">icons/createvm.png</file>
|
||||||
<file alias="removevm.png">icons/removevm.png</file>
|
<file alias="removevm.png">icons/removevm.png</file>
|
||||||
<file alias="shutdownvm.png">icons/shutdownvm.png</file>
|
<file alias="shutdownvm.png">icons/shutdownvm.png</file>
|
||||||
|
<file alias="killvm.png">icons/kill.png</file>
|
||||||
<file alias="resumevm.png">icons/resumevm.png</file>
|
<file alias="resumevm.png">icons/resumevm.png</file>
|
||||||
<file alias="pausevm.png">icons/pausevm.png</file>
|
<file alias="pausevm.png">icons/pausevm.png</file>
|
||||||
<file alias="showallvms.png">icons/showallvms.png</file>
|
|
||||||
<file alias="showcpuload.png">icons/showcpuload.png</file>
|
<file alias="showcpuload.png">icons/showcpuload.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource/>
|
<qresource/>
|
||||||
|
@ -11,7 +11,7 @@ Group: Qubes
|
|||||||
Vendor: Invisible Things Lab
|
Vendor: Invisible Things Lab
|
||||||
License: GPL
|
License: GPL
|
||||||
URL: http://fixme
|
URL: http://fixme
|
||||||
Requires: python, PyQt4, qubes-core-dom0 > 1.7.17, kdebase
|
Requires: python, PyQt4, qubes-core-dom0 > 1.7.19, kdebase
|
||||||
Requires: pmount, cryptsetup
|
Requires: pmount, cryptsetup
|
||||||
BuildRequires: PyQt4-devel
|
BuildRequires: PyQt4-devel
|
||||||
AutoReq: 0
|
AutoReq: 0
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<locale language="English" country="UnitedStates"/>
|
<locale language="English" country="UnitedStates"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>1</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="basic_tab">
|
<widget class="QWidget" name="basic_tab">
|
||||||
<property name="locale">
|
<property name="locale">
|
||||||
@ -59,13 +59,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
|
||||||
<widget class="QComboBox" name="vmlabel">
|
|
||||||
<property name="frame">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -86,23 +79,41 @@
|
|||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QComboBox" name="netVM"/>
|
<widget class="QComboBox" name="netVM"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0" colspan="2">
|
<item row="0" column="2">
|
||||||
<widget class="QCheckBox" name="include_in_backups">
|
<widget class="QComboBox" name="vmlabel">
|
||||||
<property name="enabled">
|
<property name="frame">
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Include in backups by default</string>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="include_in_backups">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Include in backups by default</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="run_in_debug_mode">
|
||||||
|
<property name="text">
|
||||||
|
<string>Run in debug mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QGroupBox" name="groupBox_4">
|
<widget class="QGroupBox" name="groupBox_4">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -154,7 +165,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" colspan="2">
|
<item row="3" column="0" colspan="2">
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -202,7 +213,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="4" column="0">
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@ -215,12 +226,15 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QGroupBox" name="networking_groupbox">
|
<widget class="QGroupBox" name="networking_groupbox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Networking</string>
|
<string>Networking</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QFormLayout" name="formLayout_3">
|
<layout class="QFormLayout" name="formLayout_3">
|
||||||
|
<property name="fieldGrowthPolicy">
|
||||||
|
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||||
|
</property>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_10">
|
<widget class="QLabel" name="label_10">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -228,19 +242,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLabel" name="ip_label">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>50</weight>
|
|
||||||
<bold>false</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>---</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_11">
|
<widget class="QLabel" name="label_11">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -281,6 +282,19 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLabel" name="ip_label">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>50</weight>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>---</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
Loading…
Reference in New Issue
Block a user