diff --git a/icons/appvm.png b/icons/appvm.png
index e9fc4a5..4735fb6 100644
Binary files a/icons/appvm.png and b/icons/appvm.png differ
diff --git a/icons/hvm.png b/icons/hvm.png
new file mode 100644
index 0000000..2fdaa04
Binary files /dev/null and b/icons/hvm.png differ
diff --git a/icons/kill.png b/icons/kill.png
new file mode 100644
index 0000000..6072634
Binary files /dev/null and b/icons/kill.png differ
diff --git a/icons/proxyvm.png b/icons/proxyvm.png
new file mode 100644
index 0000000..d4ad590
Binary files /dev/null and b/icons/proxyvm.png differ
diff --git a/icons/standalonevm.png b/icons/standalonevm.png
new file mode 100644
index 0000000..0c09de5
Binary files /dev/null and b/icons/standalonevm.png differ
diff --git a/mainwindow.ui b/mainwindow.ui
index 03e1249..d861c9d 100644
--- a/mainwindow.ui
+++ b/mainwindow.ui
@@ -151,6 +151,11 @@
+
+
+
+
+
Name
@@ -267,6 +272,7 @@
+
@@ -318,7 +324,7 @@
Start/Resume VM
- Start/Resume a VM
+ Start/Resume selected VM
@@ -333,7 +339,7 @@
Pause VM
- Pause a running VM
+ Pause selected VM
@@ -348,7 +354,7 @@
Shutdown VM
- Shutdown a running VM
+ Shutdown selected VM
@@ -386,7 +392,7 @@
true
- true
+ false
@@ -553,6 +559,18 @@
State
+
+
+
+ :/killvm.png:/killvm.png
+
+
+ Kill VM
+
+
+ Kill selected VM
+
+
diff --git a/qubesmanager/backup_utils.py b/qubesmanager/backup_utils.py
index 368b546..fbf0923 100644
--- a/qubesmanager/backup_utils.py
+++ b/qubesmanager/backup_utils.py
@@ -51,7 +51,7 @@ def mount_device(dev_path):
pmount_cmd = [mount_for_backup_path, dev_path, mount_dir_name]
res = subprocess.check_call(pmount_cmd)
except Exception as ex:
- QMessageBox.warning (None, "Error mounting selected device!", "ERROR: {0}".format(ex))
+ QMessageBox.warning (None, "Error mounting selected device!", "Could not mount {0}.
ERROR: {1}".format(dev_path, ex))
return None
if res == 0:
dev_mount_path = "/media/"+mount_dir_name
@@ -59,14 +59,21 @@ def mount_device(dev_path):
return None
def umount_device(dev_mount_path):
- try:
- pumount_cmd = ["pumount", dev_mount_path]
- res = subprocess.check_call(pumount_cmd)
- if res == 0:
- dev_mount_path = None
- except Exception as ex:
- QMessageBox.warning (None, "Could not unmount backup device!", "ERROR: {0}".format(ex))
- return dev_mount_path
+ while True:
+ try:
+ pumount_cmd = ["pumount", "--luks-force", dev_mount_path]
+ res = subprocess.check_call(pumount_cmd)
+ if res == 0:
+ dev_mount_path = None
+ return dev_mount_path
+ except Exception as ex:
+ title = "Error unmounting backup device!"
+ text = "Could not unmount {0}.
\
+ Please retry or unmount it manually using
pumount {0}.
\
+ 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):
diff --git a/qubesmanager/main.py b/qubesmanager/main.py
index 12b42fe..6991ac7 100755
--- a/qubesmanager/main.py
+++ b/qubesmanager/main.py
@@ -68,7 +68,7 @@ class QubesConfigFileWatcher(ProcessEvent):
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)
label_icon = QLabel()
@@ -77,6 +77,8 @@ class VmIconWidget (QWidget):
icon_pixmap = icon.pixmap(icon_sz, QIcon.Disabled if not enabled else QIcon.Normal)
label_icon.setPixmap (icon_pixmap)
label_icon.setFixedSize (icon_sz)
+ if tooltip != None:
+ label_icon.setToolTip(tooltip)
layout = QHBoxLayout()
layout.addWidget(label_icon)
@@ -84,6 +86,50 @@ class VmIconWidget (QWidget):
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 VmLabelItem(QTableWidgetItem):
@@ -100,23 +146,14 @@ class VmLabelWidget(VmIconWidget):
def __init__(self, vm, parent=None):
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.tableItem = self.VmLabelItem(self.value)
def get_vm_icon_path(self, vm):
- if vm.qid == 0:
- self.value = 0
- 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
+ self.value = vm.label.index
+ return vm.label.icon_path
+
class VmNameItem (QTableWidgetItem):
@@ -143,7 +180,7 @@ class VmStatusIcon(QLabel):
def set_on_icon(self):
if self.vm.last_power_state == "Running":
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")
else:
icon = QIcon (":/off.png")
@@ -406,11 +443,15 @@ class VmUpdateInfoWidget(QWidget):
self.tableItem = VmUpdateInfoWidget.VmUpdateInfoItem(self.value)
def update_outdated(self, vm):
+ if vm.type == "HVM":
+ return
+
outdated = vm.is_outdated()
if outdated and not self.previous_outdated:
self.update_status_widget("outdated")
self.previous_outdated = outdated
+
if vm.is_updateable():
update_recommended = self.previous_update_recommended
stat_file = vm.dir_path + '/' + updates_stat_file
@@ -464,6 +505,10 @@ class VmRowInTable(object):
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)
table.setCellWidget(row_no, VmManagerWindow.columns_indices['Label'], self.label_widget)
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
update_interval = 1000 # in msec
show_inactive_vms = True
- columns_indices = { "Label": 0,
- "Name": 1,
- "State": 2,
- "Template": 3,
- "NetVM": 4,
- "CPU": 5,
- "CPU Graph": 6,
- "MEM": 7,
- "MEM Graph": 8,}
+ columns_indices = { "Type": 0,
+ "Label": 1,
+ "Name": 2,
+ "State": 3,
+ "Template": 4,
+ "NetVM": 5,
+ "CPU": 6,
+ "CPU Graph": 7,
+ "MEM": 8,
+ "MEM Graph": 9,}
@@ -596,11 +642,12 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
self.actionMEM_Graph.setChecked(False)
self.table.setColumnWidth(self.columns_indices["State"], 80)
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.sortItems(self.columns_indices["Label"], Qt.AscendingOrder)
+ self.table.sortItems(self.columns_indices["Type"], Qt.AscendingOrder)
self.context_menu = QMenu(self)
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_pausevm)
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_editfwrules)
self.context_menu.addAction(self.action_updatevm)
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")
+ 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.addSeparator()
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.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.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()]
for vm in vms_list:
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)
vms_to_display = []
@@ -781,7 +840,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
state = vm.get_power_state()
if 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
reload_table = self.reload_table
@@ -896,6 +955,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
self.action_resumevm.setEnabled(not vm.last_running)
self.action_pausevm.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_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)
@@ -905,6 +965,7 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
self.action_resumevm.setEnabled(False)
self.action_pausevm.setEnabled(False)
self.action_shutdownvm.setEnabled(False)
+ self.action_killvm.setEnabled(False)
self.action_appmenus.setEnabled(False)
self.action_editfwrules.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)
+ @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 '{0}'?
"
+ "This will end (not shutdown!) all the running applications within this VM.".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!", "An exception ocurred while killing {0}.
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')
def action_settings_triggered(self):
@@ -1311,7 +1394,46 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
@pyqtSlot('const QPoint&')
def open_context_menu(self, point):
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)
else:
self.blk_menu.clear()
@@ -1321,16 +1443,16 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
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'] == vm.name:
- str = "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)
+ 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"), text)
action.setData(QVariant(d))
if len(self.blk_manager.free_devs) > 0:
for d in self.blk_manager.free_devs:
if d.startswith(vm.name):
continue
- str = "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)
+ 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"), text)
action.setData(QVariant(d))
self.blk_manager.blk_lock.release()
@@ -1340,6 +1462,14 @@ class VmManagerWindow(Ui_VmManagerWindow, QMainWindow):
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 *')
def attach_dettach_device_triggered(self, action):
dev = str(action.data().toString())
diff --git a/qubesmanager/settings.py b/qubesmanager/settings.py
index 26a2a02..2c712e8 100644
--- a/qubesmanager/settings.py
+++ b/qubesmanager/settings.py
@@ -249,6 +249,12 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
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
self.type_label.setText(self.vm.type)
@@ -329,6 +335,13 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
#include in backups
if 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
priv_size = self.max_priv_storage.value()
@@ -374,32 +387,29 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
#kernel
- #in case VM is not Linux
+ #in case VM is HVM
if not hasattr(self.vm, "kernel"):
self.kernel_groupbox.setVisible(False)
return;
- if self.vm.template is not None:
- text = self.vm.kernel
- self.kernel.insertItem(0, text)
- self.kernel.setEnabled(False)
- self.kernel_idx = 0
- else:
- text = "default (" + self.qvm_collection.get_default_kernel() +")"
- kernel_list = [text]
- for k in os.listdir(qubes_kernels_base_dir):
- kernel_list.append(k)
- kernel_list.append("none")
-
- self.kernel_idx = 0
-
- for (i, k) in enumerate(kernel_list):
- text = k
- 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):
- text += " (current)"
- self.kernel_idx = i
- self.kernel.insertItem(i,text)
- self.kernel.setCurrentIndex(self.kernel_idx)
+ # construct available kernels list
+ text = "default (" + self.qvm_collection.get_default_kernel() +")"
+ kernel_list = [text]
+ for k in os.listdir(qubes_kernels_base_dir):
+ kernel_list.append(k)
+ kernel_list.append("none")
+
+ self.kernel_idx = 0
+
+ # put available kernels to a combobox
+ for (i, k) in enumerate(kernel_list):
+ text = k
+ # 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):
+ text += " (current)"
+ self.kernel_idx = i
+ self.kernel.insertItem(i,text)
+ self.kernel.setCurrentIndex(self.kernel_idx)
#kernel opts
if self.vm.uses_default_kernelopts:
@@ -432,6 +442,9 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
return;
#kernel changed
+ if not self.kernel_groupbox.isVisible():
+ return
+
if self.kernel.currentIndex() != self.kernel_idx:
new_kernel = self.kernel.currentText()
new_kernel = new_kernel.split(' ')[0]
@@ -448,6 +461,7 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog):
self.vm.kernel = kernel
self.anything_changed = True
+
######## devices tab
def __init_devices_tab__(self):
self.dev_list = MultiSelectWidget(self)
diff --git a/resources.qrc b/resources.qrc
index 7d34360..bd4e676 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -10,6 +10,7 @@
icons/on-icon/on.png
icons/on-icon/show-all-running.png
icons/mount.png
+ icons/log.png
icons/pencil.png
icons/redfirewall.png
icons/edit.png
@@ -25,6 +26,9 @@
icons/qubes.png
icons/appvm.png
icons/netvm.png
+ icons/hvm.png
+ icons/proxyvm.png
+ icons/standalonevm.png
icons/networking.png
icons/dom0.png
icons/storagevm.png
@@ -35,9 +39,9 @@
icons/createvm.png
icons/removevm.png
icons/shutdownvm.png
+ icons/kill.png
icons/resumevm.png
icons/pausevm.png
- icons/showallvms.png
icons/showcpuload.png
diff --git a/rpm_spec/qmgr.spec b/rpm_spec/qmgr.spec
index 660ea58..aac95da 100644
--- a/rpm_spec/qmgr.spec
+++ b/rpm_spec/qmgr.spec
@@ -11,7 +11,7 @@ Group: Qubes
Vendor: Invisible Things Lab
License: GPL
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
BuildRequires: PyQt4-devel
AutoReq: 0
diff --git a/settingsdlg.ui b/settingsdlg.ui
index 1fbe60d..a766215 100644
--- a/settingsdlg.ui
+++ b/settingsdlg.ui
@@ -29,7 +29,7 @@
- 1
+ 0
@@ -59,13 +59,6 @@
- -
-
-
- true
-
-
-
-
@@ -86,23 +79,41 @@
-
- -
-
-
- true
-
-
- Include in backups by default
-
-
+
-
+
+
true
+ -
+
+
-
+
+
+ true
+
+
+ Include in backups by default
+
+
+ true
+
+
+
+ -
+
+
+ Run in debug mode
+
+
+
+
+
- -
+
-
true
@@ -154,7 +165,7 @@
- -
+
-
true
@@ -202,7 +213,7 @@
- -
+
-
Qt::Vertical
@@ -215,12 +226,15 @@
- -
+
-
Networking
+
+ QFormLayout::AllNonFixedFieldsGrow
+
-
@@ -228,19 +242,6 @@
- -
-
-
-
- 50
- false
-
-
-
- ---
-
-
-
-
@@ -281,6 +282,19 @@
+ -
+
+
+
+ 50
+ false
+
+
+
+ ---
+
+
+