Merge branch 'master' of git://git.qubes-os.org/aga/qubes-manager
8
Makefile
@ -13,10 +13,16 @@ rpms:
|
||||
rpm --addsign $(RPMS_DIR)/x86_64/qubes-manager*$(VERSION)*.rpm
|
||||
|
||||
res:
|
||||
pyrcc4 -o qubesmanager/qrc_resources.py resources.qrc
|
||||
pyrcc4 -o qubesmanager/resources_rc.py resources.qrc
|
||||
pyuic4 -o qubesmanager/ui_mainwindow.py mainwindow.ui
|
||||
pyuic4 -o qubesmanager/ui_newappvmdlg.py newappvmdlg.ui
|
||||
pyuic4 -o qubesmanager/ui_editfwrulesdlg.py editfwrulesdlg.ui
|
||||
pyuic4 -o qubesmanager/ui_newfwruledlg.py newfwruledlg.ui
|
||||
pyuic4 -o qubesmanager/ui_multiselectwidget.py multiselectwidget.ui
|
||||
pyuic4 -o qubesmanager/ui_settingsdlg.py settingsdlg.ui
|
||||
pyuic4 -o qubesmanager/ui_restoredlg.py restoredlg.ui
|
||||
pyuic4 -o qubesmanager/ui_backupdlg.py backupdlg.ui
|
||||
pyuic4 -o qubesmanager/ui_globalsettingsdlg.py globalsettingsdlg.ui
|
||||
|
||||
update-repo-current:
|
||||
ln -f $(RPMS_DIR)/x86_64/qubes-manager-*$(VERSION)*.rpm ../yum/current-release/current/dom0/rpm/
|
||||
|
196
backupdlg.ui
Normal file
@ -0,0 +1,196 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Backup</class>
|
||||
<widget class="QWizard" name="Backup">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>700</width>
|
||||
<height>399</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Qubes Backup VMs</string>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="English" country="UnitedStates"/>
|
||||
</property>
|
||||
<property name="options">
|
||||
<set>QWizard::NoBackButtonOnLastPage|QWizard::NoBackButtonOnStartPage</set>
|
||||
</property>
|
||||
<widget class="QWizardPage" name="select_vms_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>false</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select VMs to backup:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWizardPage" name="select_dir_page">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Backup destination directory</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Device:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="dev_combobox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>dev1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>longdeviceblablabla</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>dev2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>dev3</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Backup directory:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="dir_line_edit"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QToolButton" name="select_path_button">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWizardPage" name="confirm_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>false</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>You're about to perform the following actions:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEdit">
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A lot of info<br />A lot of info<br />A lot of info<br />A lot of info<br />A lot of info<br />A lot of info<br />A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info<br />A lot of info</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>false</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>To continue press Next. </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWizardPage" name="commit_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>false</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Backup in progress...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progress_bar">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
224
globalsettingsdlg.ui
Normal file
@ -0,0 +1,224 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GlobalSettings</class>
|
||||
<widget class="QDialog" name="GlobalSettings">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>678</width>
|
||||
<height>288</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Qubes Global Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>System defaults</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>UpdateVM:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="updateVMcombo"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>ClockVM:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="clockVMcombo"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Default netVM:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="defaultNetVMcombo"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Default template:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="defaultTemplateVMCombo"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Default memory settings</string>
|
||||
</property>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>11</x>
|
||||
<y>26</y>
|
||||
<width>134</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Minimal VM's memory:</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>11</x>
|
||||
<y>57</y>
|
||||
<width>139</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>dom0 memory margin:</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSpinBox" name="minVMmem">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>156</x>
|
||||
<y>26</y>
|
||||
<width>121</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MB</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSpinBox" name="dom0memMargin">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>156</x>
|
||||
<y>57</y>
|
||||
<width>121</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MB</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>50</number>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Kernel</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Default kernel:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBox_5"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>GlobalSettings</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>GlobalSettings</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
BIN
icons/add.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
icons/appsprefs.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
icons/edit.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
icons/flag-blue.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
icons/flag-green.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
icons/flag-red.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
icons/flag-yellow.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
icons/mount.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
icons/newfirewall.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
icons/on.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
icons/pencil.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
icons/redfirewall.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
icons/redfirewall2.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
icons/remove.png
Normal file
After Width: | Height: | Size: 12 KiB |
534
mainwindow.ui
Normal file
@ -0,0 +1,534 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>VmManagerWindow</class>
|
||||
<widget class="QMainWindow" name="VmManagerWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>821</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::DefaultContextMenu</enum>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Qubes VM Manager</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/qubes.png</normaloff>:/qubes.png</iconset>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="English" country="UnitedStates"/>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="English" country="UnitedStates"/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTableWidget" name="table">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="sizeIncrement">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="gridStyle">
|
||||
<enum>Qt::NoPen</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="cornerButtonEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="rowCount">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderCascadingSectionResizes">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>150</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderMinimumSectionSize">
|
||||
<number>150</number>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderCascadingSectionResizes">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Nowy wiersz</string>
|
||||
</property>
|
||||
</row>
|
||||
<row/>
|
||||
<row/>
|
||||
<row/>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>VM name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Upd</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Update info</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Template</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>VM's template</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>NetVM</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>VM's netVM</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>CPU</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>CPU Graph</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>CPU usage graph</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>MEM</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>MEM Graph</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Memory usage graph</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>821</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuOptions">
|
||||
<property name="title">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<addaction name="action_global_settings"/>
|
||||
<addaction name="action_backup"/>
|
||||
<addaction name="action_restore"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuView">
|
||||
<property name="title">
|
||||
<string>View</string>
|
||||
</property>
|
||||
<addaction name="actionUpd"/>
|
||||
<addaction name="actionTemplate"/>
|
||||
<addaction name="actionNetVM"/>
|
||||
<addaction name="actionCPU"/>
|
||||
<addaction name="actionCPU_Graph"/>
|
||||
<addaction name="actionMEM"/>
|
||||
<addaction name="actionMEM_Graph"/>
|
||||
</widget>
|
||||
<addaction name="menuOptions"/>
|
||||
<addaction name="menuView"/>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="windowTitle">
|
||||
<string>toolBar</string>
|
||||
</property>
|
||||
<property name="allowedAreas">
|
||||
<set>Qt::BottomToolBarArea|Qt::TopToolBarArea</set>
|
||||
</property>
|
||||
<property name="floatable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="action_createvm"/>
|
||||
<addaction name="action_removevm"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_resumevm"/>
|
||||
<addaction name="action_pausevm"/>
|
||||
<addaction name="action_shutdownvm"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_settings"/>
|
||||
<addaction name="action_editfwrules"/>
|
||||
<addaction name="action_appmenus"/>
|
||||
<addaction name="action_updatevm"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_showallvms"/>
|
||||
</widget>
|
||||
<action name="action_createvm">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/createvm.png</normaloff>:/createvm.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create AppVM</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Create a new AppVM</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_removevm">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/removevm.png</normaloff>:/removevm.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>remove AppVM</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Remove an existing AppVM (must be stopped first)</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_resumevm">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/resumevm.png</normaloff>:/resumevm.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start/Resume VM</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Start/Resume a VM</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_pausevm">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pausevm.png</normaloff>:/pausevm.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pause VM</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Pause a running VM</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_shutdownvm">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/shutdownvm.png</normaloff>:/shutdownvm.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Shutdown VM</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Shutdown a running VM</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_appmenus">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/appsprefs.png</normaloff>:/appsprefs.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select VM applications</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Select applications present in menu for this VM</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_updatevm">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/updateable.png</normaloff>:/updateable.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update VM</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Update VM system</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_showallvms">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/showallvms.png</normaloff>
|
||||
<selectedoff>:/showallvms.png</selectedoff>:/showallvms.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show/Hide inactive VMs</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide inactive VMs</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_editfwrules">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/redfirewall.png</normaloff>:/redfirewall.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit VM Firewall rules</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Edit VM Firewall rules</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_showgraphs">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/showcpuload.png</normaloff>:/showcpuload.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show graphs</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show Graphs</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOptions">
|
||||
<property name="text">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionView">
|
||||
<property name="text">
|
||||
<string>View</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCPU">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>CPU</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCPU_Graph">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>CPU Graph</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMEM">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MEM</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMEM_Graph">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MEM Graph</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTemplate">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Template</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNetVM">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>NetVM</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_settings">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/root.png</normaloff>:/root.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>VM Settings</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_restore">
|
||||
<property name="text">
|
||||
<string>Restore VMs from backup</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_backup">
|
||||
<property name="text">
|
||||
<string>Backup VMs</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_global_settings">
|
||||
<property name="text">
|
||||
<string>Global settings</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionUpd">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Upd</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
193
multiselectwidget.ui
Normal file
@ -0,0 +1,193 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MultiSelectWidget</class>
|
||||
<widget class="QWidget" name="MultiSelectWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>602</width>
|
||||
<height>459</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Available</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="available_list"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="add_all_button">
|
||||
<property name="text">
|
||||
<string>>></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="add_selected_button">
|
||||
<property name="text">
|
||||
<string>></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="remove_selected_button">
|
||||
<property name="text">
|
||||
<string><</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="remove_all_button">
|
||||
<property name="text">
|
||||
<string><<</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Selected</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="selected_list"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -33,235 +33,87 @@ from qubes.qubes import QubesDaemonPidfile
|
||||
from qubes.qubes import QubesHost
|
||||
from qubes.qubes import qrexec_client_path
|
||||
|
||||
import qubesmanager.qrc_resources
|
||||
import qubesmanager.resources_rc
|
||||
|
||||
from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
|
||||
|
||||
import subprocess
|
||||
import time
|
||||
import threading
|
||||
|
||||
from operator import itemgetter
|
||||
|
||||
from thread_monitor import *
|
||||
from multiselectwidget import *
|
||||
|
||||
whitelisted_filename = 'whitelisted-appmenus.list'
|
||||
|
||||
class AppRowInTable(object):
|
||||
def __init__(self, filename, name, row_no, table):
|
||||
class AppListWidgetItem(QListWidgetItem):
|
||||
def __init__(self, name, filename, parent = None):
|
||||
super(AppListWidgetItem, self).__init__(name, parent)
|
||||
self.filename = filename
|
||||
self.row_no = row_no
|
||||
|
||||
table.setRowHeight (row_no, AppmenuSelectWindow.row_height)
|
||||
|
||||
self.name_widget = QTableWidgetItem(name)
|
||||
self.name_widget.setFlags (Qt.ItemIsSelectable | Qt.ItemIsEnabled )
|
||||
table.setItem(row_no, 0, self.name_widget)
|
||||
|
||||
self.appvm_widget = QCheckBox()
|
||||
table.setCellWidget(row_no, 1, self.appvm_widget)
|
||||
|
||||
class ThreadMonitor(QObject):
|
||||
def __init__(self):
|
||||
self.success = True
|
||||
self.error_msg = None
|
||||
self.event_finished = threading.Event()
|
||||
|
||||
def set_error_msg(self, error_msg):
|
||||
self.success = False
|
||||
self.error_msg = error_msg
|
||||
self.set_finished()
|
||||
|
||||
def is_finished(self):
|
||||
return self.event_finished.is_set()
|
||||
|
||||
def set_finished(self):
|
||||
self.event_finished.set()
|
||||
|
||||
|
||||
class AppmenuSelectWindow(QDialog):
|
||||
row_height = 20
|
||||
|
||||
def __init__(self, vm, parent=None):
|
||||
super(AppmenuSelectWindow, self).__init__(parent)
|
||||
|
||||
self.gridLayout = QGridLayout(self)
|
||||
|
||||
self.buttonBox = QDialogButtonBox(self)
|
||||
self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
|
||||
self.connect(self.buttonBox, SIGNAL("accepted()"), self.save_and_apply)
|
||||
self.connect(self.buttonBox, SIGNAL("rejected()"), self.reject)
|
||||
|
||||
self.table = QTableWidget(self)
|
||||
self.table.clear()
|
||||
self.table.setColumnCount(2)
|
||||
self.table.setColumnWidth (0, 200)
|
||||
self.table.setColumnWidth (1, 40)
|
||||
|
||||
self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch)
|
||||
self.table.horizontalHeader().setResizeMode(1, QHeaderView.Fixed)
|
||||
self.table.setAlternatingRowColors(True)
|
||||
self.table.verticalHeader().hide()
|
||||
self.table.horizontalHeader().show()
|
||||
self.table.setGridStyle(Qt.NoPen)
|
||||
self.table.setSortingEnabled(True)
|
||||
self.table.setSelectionBehavior(QTableWidget.SelectRows)
|
||||
self.table.setSelectionMode(QTableWidget.SingleSelection)
|
||||
|
||||
self.gridLayout.addWidget(self.table, 0, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.buttonBox, 1, 0, 1, 1)
|
||||
class AppmenuSelectManager:
|
||||
def __init__(self, vm, apps_multiselect, parent=None):
|
||||
|
||||
self.app_list = apps_multiselect # this is a multiselect wiget
|
||||
|
||||
self.vm = vm
|
||||
if self.vm.template_vm:
|
||||
self.source_vm = self.vm.template_vm
|
||||
else:
|
||||
self.source_vm = self.vm
|
||||
self.setWindowTitle("Qubes Appmenus for %s" % vm.name)
|
||||
self.resize(250,500)
|
||||
|
||||
self.fill_table()
|
||||
self.load_list_of_selected()
|
||||
self.fill_apps_list()
|
||||
|
||||
def reject(self):
|
||||
self.done(0)
|
||||
|
||||
def addActions(self, target, actions):
|
||||
for action in actions:
|
||||
if action is None:
|
||||
target.addSeparator()
|
||||
else:
|
||||
target.addAction(action)
|
||||
|
||||
def createAction(self, text, slot=None, shortcut=None, icon=None,
|
||||
tip=None, checkable=False, signal="triggered()"):
|
||||
action = QAction(text, self)
|
||||
if icon is not None:
|
||||
action.setIcon(QIcon(":/%s.png" % icon))
|
||||
if shortcut is not None:
|
||||
action.setShortcut(shortcut)
|
||||
if tip is not None:
|
||||
action.setToolTip(tip)
|
||||
action.setStatusTip(tip)
|
||||
if slot is not None:
|
||||
self.connect(action, SIGNAL(signal), slot)
|
||||
if checkable:
|
||||
action.setCheckable(True)
|
||||
return action
|
||||
|
||||
def fill_table(self):
|
||||
def fill_apps_list(self):
|
||||
|
||||
template_dir = self.source_vm.appmenus_templates_dir
|
||||
|
||||
template_file_list = os.listdir(template_dir)
|
||||
|
||||
self.table.clear()
|
||||
self.table.setHorizontalHeaderLabels(['Name', 'VM'])
|
||||
self.table.setRowCount(len(template_file_list))
|
||||
whitelisted = []
|
||||
if os.path.exists(self.vm.dir_path + '/' + whitelisted_filename):
|
||||
f = open(self.vm.dir_path + '/' + whitelisted_filename, 'r')
|
||||
whitelisted = [item.strip() for item in f]
|
||||
f.close()
|
||||
|
||||
row_no = 0
|
||||
appmenus = []
|
||||
self.app_list.clear()
|
||||
|
||||
|
||||
available_appmenus = []
|
||||
for template_file in template_file_list:
|
||||
desktop_template = open(template_dir + '/' + template_file, 'r')
|
||||
for line in desktop_template:
|
||||
if line.startswith("Name=%VMNAME%: "):
|
||||
desktop_name = line.partition('Name=%VMNAME%: ')[2].strip()
|
||||
row = AppRowInTable (template_file, desktop_name, row_no, self.table)
|
||||
appmenus.append(row)
|
||||
row_no += 1
|
||||
available_appmenus.append( (template_file, desktop_name) )
|
||||
break
|
||||
desktop_template.close()
|
||||
|
||||
self.table.setRowCount(row_no)
|
||||
self.appmenus = appmenus
|
||||
self.table.sortItems(0)
|
||||
whitelisted_appmenus = [a for a in available_appmenus if a[0] in whitelisted]
|
||||
available_appmenus = [a for a in available_appmenus if a[0] not in whitelisted]
|
||||
|
||||
for a in available_appmenus:
|
||||
self.app_list.available_list.addItem( AppListWidgetItem(a[1], a[0]))
|
||||
|
||||
def load_list_of_selected(self):
|
||||
if not os.path.exists(self.vm.dir_path + '/' + whitelisted_filename):
|
||||
# select none
|
||||
for row in self.appmenus:
|
||||
row.appvm_widget.setCheckState(Qt.Unchecked)
|
||||
return
|
||||
|
||||
f = open(self.vm.dir_path + '/' + whitelisted_filename, 'r')
|
||||
whitelisted = [item.strip() for item in f]
|
||||
f.close()
|
||||
for row in self.appmenus:
|
||||
if row.filename in whitelisted:
|
||||
row.appvm_widget.setCheckState(Qt.Checked)
|
||||
else:
|
||||
row.appvm_widget.setCheckState(Qt.Unchecked)
|
||||
for a in whitelisted_appmenus:
|
||||
self.app_list.selected_list.addItem( AppListWidgetItem(a[1], a[0]))
|
||||
|
||||
self.app_list.available_list.sortItems()
|
||||
self.app_list.selected_list.sortItems()
|
||||
|
||||
def save_list_of_selected(self):
|
||||
whitelisted = open(self.vm.dir_path + '/' + whitelisted_filename, 'w')
|
||||
for row in self.appmenus:
|
||||
if row.appvm_widget.checkState() == Qt.Checked:
|
||||
whitelisted.write(row.filename + '\n')
|
||||
whitelisted.close()
|
||||
for i in range(self.app_list.selected_list.count()):
|
||||
item = self.app_list.selected_list.item(i)
|
||||
whitelisted.write(item.filename + '\n')
|
||||
whitelisted.close()
|
||||
|
||||
|
||||
def save_and_apply(self):
|
||||
def save_appmenu_select_changes(self):
|
||||
self.save_list_of_selected()
|
||||
subprocess.check_call([qubes_appmenu_remove_cmd, self.vm.name])
|
||||
subprocess.check_call([qubes_appmenu_create_cmd, self.source_vm.appmenus_templates_dir, self.vm.name])
|
||||
self.done(0)
|
||||
|
||||
# Bases on the original code by:
|
||||
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
|
||||
|
||||
def handle_exception( exc_type, exc_value, exc_traceback ):
|
||||
import sys
|
||||
import os.path
|
||||
import traceback
|
||||
|
||||
filename, line, dummy, dummy = traceback.extract_tb( exc_traceback ).pop()
|
||||
filename = os.path.basename( filename )
|
||||
error = "%s: %s" % ( exc_type.__name__, exc_value )
|
||||
|
||||
QMessageBox.critical(None, "Houston, we have a problem...",
|
||||
"Whoops. A critical error has occured. This is most likely a bug "
|
||||
"in Qubes Appmenu Select application.<br><br>"
|
||||
"<b><i>%s</i></b>" % error +
|
||||
"at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
|
||||
% ( line, filename ))
|
||||
|
||||
#sys.exit(1)
|
||||
|
||||
def main():
|
||||
|
||||
|
||||
global qubes_host
|
||||
qubes_host = QubesHost()
|
||||
|
||||
global app
|
||||
app = QApplication(sys.argv)
|
||||
app.setOrganizationName("The Qubes Project")
|
||||
app.setOrganizationDomain("http://qubes-os.org")
|
||||
app.setApplicationName("Qubes Appmenu Select")
|
||||
app.setWindowIcon(QIcon(":/qubes.png"))
|
||||
|
||||
sys.excepthook = handle_exception
|
||||
|
||||
qvm_collection = QubesVmCollection()
|
||||
qvm_collection.lock_db_for_reading()
|
||||
qvm_collection.load()
|
||||
qvm_collection.unlock_db()
|
||||
|
||||
vm = None
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
vm = qvm_collection.get_vm_by_name(sys.argv[1])
|
||||
if vm is None or vm.qid not in qvm_collection:
|
||||
QMessageBox.critical(None, "Qubes Appmenu Select Error",
|
||||
"A VM with the name '{0}' does not exist in the system.".format(sys.argv[1]))
|
||||
sys.exit(1)
|
||||
else:
|
||||
vms_list = [vm.name for vm in qvm_collection.values() if (vm.is_appvm() or vm.is_template())]
|
||||
vmname = QInputDialog.getItem(None, "Select VM", "Select VM:", vms_list, editable = False)
|
||||
if not vmname[1]:
|
||||
sys.exit(1)
|
||||
vm = qvm_collection.get_vm_by_name(vmname[0])
|
||||
|
||||
global manager_window
|
||||
select_window = AppmenuSelectWindow(vm)
|
||||
|
||||
select_window.show()
|
||||
|
||||
app.exec_()
|
||||
app.exit()
|
||||
|
||||
|
239
qubesmanager/backup.py
Normal file
@ -0,0 +1,239 @@
|
||||
#!/usr/bin/python2.6
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2012 Agnieszka Kostrzewa <agnieszka.kostrzewa@gmail.com>
|
||||
# Copyright (C) 2012 Marek Marczykowski <marmarek@mimuw.edu.pl>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
import sys
|
||||
import os
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtGui import *
|
||||
|
||||
from qubes.qubes import QubesVmCollection
|
||||
from qubes.qubes import QubesException
|
||||
from qubes.qubes import QubesDaemonPidfile
|
||||
from qubes.qubes import QubesHost
|
||||
from qubes import qubesutils
|
||||
|
||||
import qubesmanager.resources_rc
|
||||
|
||||
from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
|
||||
|
||||
import subprocess
|
||||
import time
|
||||
from thread_monitor import *
|
||||
from operator import itemgetter
|
||||
|
||||
from datetime import datetime
|
||||
from string import replace
|
||||
|
||||
from ui_backupdlg import *
|
||||
from multiselectwidget import *
|
||||
|
||||
from backup_utils import *
|
||||
|
||||
|
||||
class BackupVMsWindow(Ui_Backup, QWizard):
|
||||
|
||||
__pyqtSignals__ = ("backup_progress(int)",)
|
||||
|
||||
excluded = []
|
||||
to_backup = []
|
||||
|
||||
def __init__(self, app, qvm_collection, blk_manager, parent=None):
|
||||
super(BackupVMsWindow, self).__init__(parent)
|
||||
|
||||
self.app = app
|
||||
self.qvm_collection = qvm_collection
|
||||
self.blk_manager = blk_manager
|
||||
|
||||
self.dev_mount_path = None
|
||||
self.backup_dir = None
|
||||
self.func_output = []
|
||||
|
||||
for vm in self.qvm_collection.values():
|
||||
if vm.qid == 0:
|
||||
self.vm = vm
|
||||
break;
|
||||
|
||||
assert self.vm != None
|
||||
|
||||
self.setupUi(self)
|
||||
|
||||
self.dir_line_edit.setReadOnly(True)
|
||||
|
||||
self.select_vms_widget = MultiSelectWidget(self)
|
||||
self.verticalLayout.insertWidget(1, self.select_vms_widget)
|
||||
|
||||
self.connect(self, SIGNAL("currentIdChanged(int)"), self.current_page_changed)
|
||||
self.connect(self.dev_combobox, SIGNAL("activated(int)"), self.dev_combobox_activated)
|
||||
self.connect(self, SIGNAL("backup_progress(int)"), self.progress_bar.setValue)
|
||||
|
||||
self.select_vms_page.isComplete = self.has_selected_vms
|
||||
self.select_dir_page.isComplete = self.has_selected_dir
|
||||
#FIXME
|
||||
#this causes to run isComplete() twice, I don't know why
|
||||
self.select_vms_page.connect(self.select_vms_widget, SIGNAL("selected_changed()"), SIGNAL("completeChanged()"))
|
||||
|
||||
self.__fill_vms_list__()
|
||||
fill_devs_list(self)
|
||||
|
||||
def __fill_vms_list__(self):
|
||||
for vm in self.qvm_collection.values():
|
||||
if vm.is_running() and vm.qid != 0:
|
||||
self.excluded.append(vm.name)
|
||||
continue
|
||||
|
||||
if vm.is_appvm() and vm.internal:
|
||||
self.excluded.append(vm.name)
|
||||
continue
|
||||
|
||||
if vm.is_template() and vm.installed_by_rpm:
|
||||
self.excluded.append(vm.name)
|
||||
continue
|
||||
|
||||
self.to_backup.append(vm.name)
|
||||
self.select_vms_widget.available_list.addItem(vm.name)
|
||||
|
||||
|
||||
def dev_combobox_activated(self, idx):
|
||||
dev_combobox_activated(self, idx)
|
||||
|
||||
|
||||
@pyqtSlot(name='on_select_path_button_clicked')
|
||||
def select_path_button_clicked(self):
|
||||
select_path_button_clicked(self)
|
||||
|
||||
def validateCurrentPage(self):
|
||||
if self.currentPage() is self.select_vms_page:
|
||||
for i in range(self.select_vms_widget.available_list.count()):
|
||||
vmname = self.select_vms_widget.available_list.item(i).text()
|
||||
self.excluded.append(vmname)
|
||||
return True
|
||||
|
||||
def gather_output(self, s):
|
||||
self.func_output.append(s)
|
||||
|
||||
def update_progress_bar(self, value):
|
||||
self.emit(SIGNAL("backup_progress(int)"), value)
|
||||
|
||||
|
||||
def __do_backup__(self, thread_monitor):
|
||||
msg = []
|
||||
try:
|
||||
qubesutils.backup_do(str(self.backup_dir), self.files_to_backup, self.update_progress_bar)
|
||||
#simulate_long_lasting_proces(10, self.update_progress_bar)
|
||||
except Exception as ex:
|
||||
msg.append(str(ex))
|
||||
|
||||
if len(msg) > 0 :
|
||||
thread_monitor.set_error_msg('\n'.join(msg))
|
||||
|
||||
thread_monitor.set_finished()
|
||||
|
||||
|
||||
def current_page_changed(self, id):
|
||||
if self.currentPage() is self.confirm_page:
|
||||
del self.func_output[:]
|
||||
self.files_to_backup = qubesutils.backup_prepare(str(self.backup_dir), exclude_list = self.excluded, print_callback = self.gather_output)
|
||||
|
||||
self.textEdit.setReadOnly(True)
|
||||
self.textEdit.setFontFamily("Monospace")
|
||||
self.textEdit.setText("\n".join(self.func_output))
|
||||
|
||||
elif self.currentPage() is self.commit_page:
|
||||
self.button(self.CancelButton).setDisabled(True)
|
||||
self.button(self.FinishButton).setDisabled(True)
|
||||
self.thread_monitor = ThreadMonitor()
|
||||
thread = threading.Thread (target= self.__do_backup__ , args=(self.thread_monitor,))
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
while not self.thread_monitor.is_finished():
|
||||
self.app.processEvents()
|
||||
time.sleep (0.1)
|
||||
|
||||
if not self.thread_monitor.success:
|
||||
QMessageBox.warning (None, "Backup error!", "ERROR: {1}".format(self.vm.name, self.thread_monitor.error_msg))
|
||||
|
||||
umount_device(self.dev_mount_path)
|
||||
self.button(self.FinishButton).setEnabled(True)
|
||||
|
||||
def has_selected_vms(self):
|
||||
return self.select_vms_widget.selected_list.count() > 0
|
||||
|
||||
def has_selected_dir(self):
|
||||
return self.backup_dir != None
|
||||
|
||||
|
||||
|
||||
|
||||
# Bases on the original code by:
|
||||
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
|
||||
|
||||
def handle_exception( exc_type, exc_value, exc_traceback ):
|
||||
import sys
|
||||
import os.path
|
||||
import traceback
|
||||
|
||||
filename, line, dummy, dummy = traceback.extract_tb( exc_traceback ).pop()
|
||||
filename = os.path.basename( filename )
|
||||
error = "%s: %s" % ( exc_type.__name__, exc_value )
|
||||
|
||||
QMessageBox.critical(None, "Houston, we have a problem...",
|
||||
"Whoops. A critical error has occured. This is most likely a bug "
|
||||
"in Qubes Restore VMs application.<br><br>"
|
||||
"<b><i>%s</i></b>" % error +
|
||||
"at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
|
||||
% ( line, filename ))
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
global qubes_host
|
||||
qubes_host = QubesHost()
|
||||
|
||||
global app
|
||||
app = QApplication(sys.argv)
|
||||
app.setOrganizationName("The Qubes Project")
|
||||
app.setOrganizationDomain("http://qubes-os.org")
|
||||
app.setApplicationName("Qubes Backup VMs")
|
||||
|
||||
sys.excepthook = handle_exception
|
||||
|
||||
qvm_collection = QubesVmCollection()
|
||||
qvm_collection.lock_db_for_reading()
|
||||
qvm_collection.load()
|
||||
qvm_collection.unlock_db()
|
||||
|
||||
global backup_window
|
||||
backup_window = BackupVMsWindow()
|
||||
|
||||
backup_window.show()
|
||||
|
||||
app.exec_()
|
||||
app.exit()
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
159
qubesmanager/backup_utils.py
Normal file
@ -0,0 +1,159 @@
|
||||
#!/usr/bin/python2.6
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2012 Agnieszka Kostrzewa <agnieszka.kostrzewa@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
import sys
|
||||
import os
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtGui import *
|
||||
|
||||
from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
|
||||
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
from thread_monitor import *
|
||||
|
||||
from datetime import datetime
|
||||
from string import replace
|
||||
|
||||
|
||||
def check_if_mounted(dev_path):
|
||||
mounts_file = open("/proc/mounts")
|
||||
for m in list(mounts_file):
|
||||
if m.startswith(dev_path):
|
||||
return m.split(" ")[1]
|
||||
return None
|
||||
|
||||
|
||||
def mount_device(dev_path):
|
||||
try:
|
||||
mount_dir_name = "backup" + replace(str(datetime.now()),' ', '-').split(".")[0]
|
||||
pmount_cmd = ["pmount", 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))
|
||||
return None
|
||||
if res == 0:
|
||||
dev_mount_path = "/media/"+mount_dir_name
|
||||
return dev_mount_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
|
||||
|
||||
|
||||
def fill_devs_list(dialog):
|
||||
dialog.dev_combobox.clear()
|
||||
dialog.dev_combobox.addItem("None")
|
||||
for a in dialog.blk_manager.attached_devs:
|
||||
if dialog.blk_manager.attached_devs[a]['attached_to']['vm'] == dialog.vm.name :
|
||||
att = a + " " + unicode(dialog.blk_manager.attached_devs[a]['size']) + " " + dialog.blk_manager.attached_devs[a]['desc']
|
||||
dialog.dev_combobox.addItem(att, QVariant(a))
|
||||
for a in dialog.blk_manager.free_devs:
|
||||
att = a + " " + unicode(dialog.blk_manager.free_devs[a]['size']) + " " + dialog.blk_manager.free_devs[a]['desc']
|
||||
dialog.dev_combobox.addItem(att, QVariant(a))
|
||||
dialog.dev_combobox.setCurrentIndex(0) #current selected is null ""
|
||||
dialog.prev_dev_idx = 0
|
||||
dialog.dir_line_edit.clear()
|
||||
dialog.dir_line_edit.setEnabled(False)
|
||||
dialog.select_path_button.setEnabled(False)
|
||||
|
||||
|
||||
def enable_dir_line_edit(dialog, boolean):
|
||||
dialog.dir_line_edit.setEnabled(boolean)
|
||||
dialog.select_path_button.setEnabled(boolean)
|
||||
|
||||
|
||||
def dev_combobox_activated(dialog, idx):
|
||||
if idx == dialog.prev_dev_idx: #nothing has changed
|
||||
return
|
||||
#there was a change
|
||||
|
||||
dialog.dir_line_edit.setText("")
|
||||
dialog.backup_dir = None
|
||||
|
||||
if dialog.dev_mount_path != None:
|
||||
dialog.dev_mount_path = umount_device(dialog.dev_mount_path)
|
||||
if dialog_dev_mount_path != None:
|
||||
dialog.dev_combobox.setCurrentIndex(dialog.prev_dev_idx)
|
||||
return
|
||||
|
||||
enable_dir_line_edit(dialog, False)
|
||||
|
||||
if dialog.dev_combobox.currentText() != "None": #An existing device chosen
|
||||
dev_name = str(dialog.dev_combobox.itemData(idx).toString())
|
||||
|
||||
if dev_name in dialog.blk_manager.free_devs:
|
||||
if dev_name.startswith(dialog.vm.name): # originally attached to dom0
|
||||
dev_path = "/dev/"+dev_name.split(":")[1]
|
||||
|
||||
else: # originally attached to another domain, eg. usbvm
|
||||
#attach it to dom0, then treat it as an attached device
|
||||
dialog.blk_manager.attach_device(dialog.vm, dev_name)
|
||||
|
||||
if dev_name in dialog.blk_manager.attached_devs: #is attached to dom0
|
||||
assert dialog.blk_manager.attached_devs[dev_name]['attached_to']['vm'] == dialog.vm.name
|
||||
dev_path = "/dev/" + dialog.blk_manager.attached_devs[dev_name]['attached_to']['frontend']
|
||||
|
||||
#check if device mounted
|
||||
dialog.dev_mount_path = check_if_mounted(dev_path)
|
||||
if dialog.dev_mount_path != None:
|
||||
enable_dir_line_edit(dialog, True)
|
||||
else:
|
||||
dialog.dev_mount_path = mount_device(dev_path)
|
||||
if dialog.dev_mount_path != None:
|
||||
enable_dir_line_edit(dialog, True)
|
||||
else:
|
||||
dialog.dev_combobox.setCurrentIndex(0) #if couldn't mount - set current device to "None"
|
||||
|
||||
|
||||
dialog.prev_dev_idx = idx
|
||||
dialog.select_dir_page.emit(SIGNAL("completeChanged()"))
|
||||
|
||||
|
||||
def select_path_button_clicked(dialog):
|
||||
dialog.backup_dir = dialog.dir_line_edit.text()
|
||||
file_dialog = QFileDialog()
|
||||
file_dialog.setReadOnly(True)
|
||||
new_path = file_dialog.getExistingDirectory(dialog, "Select backup directory.", dialog.dev_mount_path)
|
||||
if new_path:
|
||||
dialog.dir_line_edit.setText(new_path)
|
||||
dialog.backup_dir = new_path
|
||||
dialog.select_dir_page.emit(SIGNAL("completeChanged()"))
|
||||
|
||||
|
||||
|
||||
def simulate_long_lasting_proces(period, progress_callback):
|
||||
for i in range(period):
|
||||
progress_callback((i*100)/period)
|
||||
time.sleep(1)
|
||||
|
||||
progress_callback(100)
|
||||
return 0
|
||||
|
@ -31,106 +31,8 @@ from qubes.qubes import QubesVmCollection
|
||||
from qubes.qubes import QubesException
|
||||
from qubes.qubes import dry_run
|
||||
|
||||
import ui_editfwrulesdlg
|
||||
import ui_newfwruledlg
|
||||
|
||||
class EditFwRulesDlg (QDialog, ui_editfwrulesdlg.Ui_EditFwRulesDlg):
|
||||
def __init__(self, parent = None):
|
||||
super (EditFwRulesDlg, self).__init__(parent)
|
||||
self.setupUi(self)
|
||||
self.newRuleButton.clicked.connect(self.new_rule_button_pressed)
|
||||
self.editRuleButton.clicked.connect(self.edit_rule_button_pressed)
|
||||
self.deleteRuleButton.clicked.connect(self.delete_rule_button_pressed)
|
||||
self.policyAllowRadioButton.toggled.connect(self.policy_radio_toggled)
|
||||
self.dnsCheckBox.toggled.connect(self.dns_checkbox_toggled)
|
||||
self.icmpCheckBox.toggled.connect(self.icmp_checkbox_toggled)
|
||||
|
||||
def set_model(self, model):
|
||||
self.__model = model
|
||||
self.rulesTreeView.setModel(model)
|
||||
self.rulesTreeView.header().setResizeMode(QHeaderView.ResizeToContents)
|
||||
self.rulesTreeView.header().setResizeMode(0, QHeaderView.Stretch)
|
||||
self.set_allow(model.allow)
|
||||
self.dnsCheckBox.setChecked(model.allowDns)
|
||||
self.icmpCheckBox.setChecked(model.allowIcmp)
|
||||
self.setWindowTitle(model.get_vm_name() + " firewall")
|
||||
|
||||
def set_allow(self, allow):
|
||||
self.policyAllowRadioButton.setChecked(allow)
|
||||
self.policyDenyRadioButton.setChecked(not allow)
|
||||
|
||||
def policy_radio_toggled(self, on):
|
||||
self.__model.allow = self.policyAllowRadioButton.isChecked()
|
||||
|
||||
def dns_checkbox_toggled(self, on):
|
||||
self.__model.allowDns = on
|
||||
|
||||
def icmp_checkbox_toggled(self, on):
|
||||
self.__model.allowIcmp = on
|
||||
|
||||
def new_rule_button_pressed(self):
|
||||
dialog = NewFwRuleDlg()
|
||||
self.run_rule_dialog(dialog)
|
||||
|
||||
def edit_rule_button_pressed(self):
|
||||
dialog = NewFwRuleDlg()
|
||||
dialog.set_ok_enabled(True)
|
||||
selected = self.rulesTreeView.selectedIndexes()
|
||||
if len(selected) > 0:
|
||||
row = self.rulesTreeView.selectedIndexes().pop().row()
|
||||
address = self.__model.get_column_string(0, row).replace(' ', '')
|
||||
dialog.addressComboBox.setItemText(0, address)
|
||||
dialog.addressComboBox.setCurrentIndex(0)
|
||||
service = self.__model.get_column_string(1, row)
|
||||
dialog.serviceComboBox.setItemText(0, service)
|
||||
dialog.serviceComboBox.setCurrentIndex(0)
|
||||
self.run_rule_dialog(dialog, row)
|
||||
|
||||
def run_rule_dialog(self, dialog, row = None):
|
||||
if dialog.exec_():
|
||||
address = str(dialog.addressComboBox.currentText())
|
||||
service = str(dialog.serviceComboBox.currentText())
|
||||
port = None
|
||||
port2 = None
|
||||
|
||||
unmask = address.split("/", 1)
|
||||
if len(unmask) == 2:
|
||||
address = unmask[0]
|
||||
netmask = int(unmask[1])
|
||||
else:
|
||||
netmask = 32
|
||||
|
||||
if address == "*":
|
||||
address = "0.0.0.0"
|
||||
netmask = 0
|
||||
|
||||
if service == "*":
|
||||
service = "0"
|
||||
try:
|
||||
range = service.split("-", 1)
|
||||
if len(range) == 2:
|
||||
port = int(range[0])
|
||||
port2 = int(range[1])
|
||||
else:
|
||||
port = int(service)
|
||||
except (TypeError, ValueError) as ex:
|
||||
port = self.__model.get_service_port(service)
|
||||
|
||||
if port is not None:
|
||||
if port2 is not None and port2 <= port:
|
||||
QMessageBox.warning(None, "Invalid service ports range", "Port {0} is lower than port {1}.".format(port2, port))
|
||||
else:
|
||||
item = QubesFirewallRuleItem(address, netmask, port, port2)
|
||||
if row is not None:
|
||||
self.__model.setChild(row, item)
|
||||
else:
|
||||
self.__model.appendChild(item)
|
||||
else:
|
||||
QMessageBox.warning(None, "Invalid service name", "Service '{0} is unknown.".format(service))
|
||||
|
||||
def delete_rule_button_pressed(self):
|
||||
for i in set([index.row() for index in self.rulesTreeView.selectedIndexes()]):
|
||||
self.__model.removeChild(i)
|
||||
|
||||
class QIPAddressValidator(QValidator):
|
||||
def __init__(self, parent = None):
|
||||
@ -397,3 +299,4 @@ class QubesFirewallRulesModel(QAbstractItemModel):
|
||||
|
||||
def __len__(self):
|
||||
return len(self.children)
|
||||
|
||||
|
107
qubesmanager/global_settings.py
Normal file
@ -0,0 +1,107 @@
|
||||
#!/usr/bin/python2.6
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2012 Agnieszka Kostrzewa <agnieszka.kostrzewa@gmail.com>
|
||||
# Copyright (C) 2012 Marek Marczykowski <marmarek@mimuw.edu.pl>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
import sys
|
||||
import os
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtGui import *
|
||||
|
||||
from qubes.qubes import QubesVmCollection
|
||||
from qubes.qubes import QubesException
|
||||
from qubes.qubes import QubesDaemonPidfile
|
||||
from qubes.qubes import QubesHost
|
||||
|
||||
import qubesmanager.resources_rc
|
||||
|
||||
from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
|
||||
|
||||
import subprocess
|
||||
import time
|
||||
import threading
|
||||
from operator import itemgetter
|
||||
|
||||
from ui_globalsettingsdlg import *
|
||||
|
||||
class GlobalSettingsWindow(Ui_GlobalSettings, QDialog):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(GlobalSettingsWindow, self).__init__(parent)
|
||||
|
||||
self.setupUi(self)
|
||||
|
||||
def reject(self):
|
||||
self.done(0)
|
||||
|
||||
def save_and_apply(self):
|
||||
pass
|
||||
|
||||
# Bases on the original code by:
|
||||
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
|
||||
|
||||
def handle_exception( exc_type, exc_value, exc_traceback ):
|
||||
import sys
|
||||
import os.path
|
||||
import traceback
|
||||
|
||||
filename, line, dummy, dummy = traceback.extract_tb( exc_traceback ).pop()
|
||||
filename = os.path.basename( filename )
|
||||
error = "%s: %s" % ( exc_type.__name__, exc_value )
|
||||
|
||||
QMessageBox.critical(None, "Houston, we have a problem...",
|
||||
"Whoops. A critical error has occured. This is most likely a bug "
|
||||
"in Qubes Global Settings application.<br><br>"
|
||||
"<b><i>%s</i></b>" % error +
|
||||
"at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
|
||||
% ( line, filename ))
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
global qubes_host
|
||||
qubes_host = QubesHost()
|
||||
|
||||
global app
|
||||
app = QApplication(sys.argv)
|
||||
app.setOrganizationName("The Qubes Project")
|
||||
app.setOrganizationDomain("http://qubes-os.org")
|
||||
app.setApplicationName("Qubes Global Settings")
|
||||
|
||||
sys.excepthook = handle_exception
|
||||
|
||||
qvm_collection = QubesVmCollection()
|
||||
qvm_collection.lock_db_for_reading()
|
||||
qvm_collection.load()
|
||||
qvm_collection.unlock_db()
|
||||
|
||||
global global_window
|
||||
global_window = GlobalSettingsWindow()
|
||||
|
||||
global_window.show()
|
||||
|
||||
app.exec_()
|
||||
app.exit()
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
1065
qubesmanager/main.py
52
qubesmanager/multiselectwidget.py
Normal file
@ -0,0 +1,52 @@
|
||||
import sys
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtGui import *
|
||||
from ui_multiselectwidget import *
|
||||
|
||||
class MultiSelectWidget(Ui_MultiSelectWidget, QWidget):
|
||||
|
||||
__pyqtSignals__ = ("selected_changed()",)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(MultiSelectWidget, self).__init__()
|
||||
self.setupUi(self);
|
||||
self.add_selected_button.clicked.connect(self.add_selected)
|
||||
self.add_all_button.clicked.connect(self.add_all)
|
||||
self.remove_selected_button.clicked.connect(self.remove_selected)
|
||||
self.remove_all_button.clicked.connect(self.remove_all)
|
||||
self.available_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
|
||||
self.selected_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
|
||||
|
||||
def switch_selected(self, src, dst):
|
||||
selected = src.selectedItems()
|
||||
|
||||
for s in selected:
|
||||
row = src.indexFromItem(s).row()
|
||||
item = src.takeItem(row)
|
||||
dst.addItem(item)
|
||||
dst.sortItems()
|
||||
self.emit(SIGNAL("selected_changed()"))
|
||||
|
||||
def add_selected(self):
|
||||
self.switch_selected(self.available_list, self.selected_list)
|
||||
|
||||
def remove_selected(self):
|
||||
self.switch_selected(self.selected_list, self.available_list)
|
||||
|
||||
def move_all(self, src, dst):
|
||||
while src.count() > 0:
|
||||
item = src.takeItem(0)
|
||||
dst.addItem(item)
|
||||
dst.sortItems()
|
||||
self.emit(SIGNAL("selected_changed()"))
|
||||
|
||||
def add_all(self):
|
||||
self.move_all(self.available_list, self.selected_list)
|
||||
|
||||
def remove_all(self):
|
||||
self.move_all(self.selected_list, self.available_list)
|
||||
|
||||
def clear(self):
|
||||
self.available_list.clear()
|
||||
self.selected_list.clear()
|
||||
|
276
qubesmanager/restore.py
Normal file
@ -0,0 +1,276 @@
|
||||
#!/usr/bin/python2.6
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2012 Agnieszka Kostrzewa <agnieszka.kostrzewa@gmail.com>
|
||||
# Copyright (C) 2012 Marek Marczykowski <marmarek@mimuw.edu.pl>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
import sys
|
||||
import os
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtGui import *
|
||||
|
||||
from qubes.qubes import QubesVmCollection
|
||||
from qubes.qubes import QubesException
|
||||
from qubes.qubes import QubesDaemonPidfile
|
||||
from qubes.qubes import QubesHost
|
||||
from qubes.qubes import qubes_base_dir
|
||||
import qubesmanager.resources_rc
|
||||
|
||||
from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
|
||||
|
||||
import subprocess
|
||||
import time
|
||||
from operator import itemgetter
|
||||
from thread_monitor import *
|
||||
|
||||
from qubes import qubesutils
|
||||
|
||||
from ui_restoredlg import *
|
||||
from multiselectwidget import *
|
||||
|
||||
from backup_utils import *
|
||||
|
||||
|
||||
|
||||
class RestoreVMsWindow(Ui_Restore, QWizard):
|
||||
|
||||
__pyqtSignals__ = ("restore_progress(int)",)
|
||||
|
||||
def __init__(self, app, qvm_collection, blk_manager, parent=None):
|
||||
super(RestoreVMsWindow, self).__init__(parent)
|
||||
|
||||
self.app = app
|
||||
self.qvm_collection = qvm_collection
|
||||
self.blk_manager = blk_manager
|
||||
|
||||
self.dev_mount_path = None
|
||||
self.backup_dir = None
|
||||
self.restore_options = None
|
||||
self.backup_vms_list = None
|
||||
self.func_output = []
|
||||
|
||||
self.excluded = {}
|
||||
|
||||
for vm in self.qvm_collection.values():
|
||||
if vm.qid == 0:
|
||||
self.vm = vm
|
||||
break;
|
||||
|
||||
assert self.vm != None
|
||||
|
||||
self.setupUi(self)
|
||||
|
||||
self.select_vms_widget = MultiSelectWidget(self)
|
||||
self.select_vms_layout.insertWidget(1, self.select_vms_widget)
|
||||
|
||||
self.connect(self, SIGNAL("currentIdChanged(int)"), self.current_page_changed)
|
||||
self.connect(self.dev_combobox, SIGNAL("activated(int)"), self.dev_combobox_activated)
|
||||
self.connect(self, SIGNAL("restore_progress(QString)"), self.commit_text_edit.append)
|
||||
|
||||
self.select_dir_page.isComplete = self.has_selected_dir
|
||||
self.select_vms_page.isComplete = self.has_selected_vms
|
||||
#FIXME
|
||||
#this causes to run isComplete() twice, I don't know why
|
||||
self.select_vms_page.connect(self.select_vms_widget, SIGNAL("selected_changed()"), SIGNAL("completeChanged()"))
|
||||
|
||||
fill_devs_list(self)
|
||||
self.__init_restore_options__()
|
||||
|
||||
|
||||
def dev_combobox_activated(self, idx):
|
||||
dev_combobox_activated(self, idx)
|
||||
|
||||
|
||||
@pyqtSlot(name='on_select_path_button_clicked')
|
||||
def select_path_button_clicked(self):
|
||||
select_path_button_clicked(self)
|
||||
|
||||
def on_ignore_missing_toggled(self, checked):
|
||||
self.restore_options['use-default-template'] = checked
|
||||
self.restore_options['use-default-netvm'] = checked
|
||||
|
||||
def on_ignore_uname_mismatch_toggled(self, checked):
|
||||
self.restore_options['ignore-username-mismatch'] = checked
|
||||
|
||||
def on_skip_dom0_toggled(self, checked):
|
||||
self.restore_options['dom0-home'] = checked
|
||||
|
||||
|
||||
def __fill_vms_list__(self):
|
||||
if self.backup_vms_list != None:
|
||||
return
|
||||
|
||||
self.select_vms_widget.selected_list.clear()
|
||||
self.select_vms_widget.available_list.clear()
|
||||
|
||||
self.vms_to_restore = qubesutils.backup_restore_prepare(str(self.backup_dir), self.restore_options, self.qvm_collection)
|
||||
for vmname in self.vms_to_restore:
|
||||
self.select_vms_widget.available_list.addItem(vmname)
|
||||
|
||||
def __init_restore_options__(self):
|
||||
if not self.restore_options:
|
||||
self.restore_options = {}
|
||||
qubesutils.backup_restore_set_defaults(self.restore_options)
|
||||
|
||||
if 'use-default-template' in self.restore_options and 'use-default-netvm' in self.restore_options:
|
||||
val = self.restore_options['use-default-template'] and self.restore_options['use-default-netvm']
|
||||
self.ignore_missing.setChecked(val)
|
||||
else:
|
||||
self.ignore_missing.setChecked(False)
|
||||
|
||||
if 'ignore-username-mismatch' in self.restore_options:
|
||||
self.ignore_uname_mismatch.setChecked(self.restore_options['ignore-username-mismatch'])
|
||||
|
||||
if 'dom0-home' in self.restore_options:
|
||||
self.skip_dom0.setChecked(self.restore_options['dom0-home'])
|
||||
|
||||
|
||||
|
||||
def gather_output(self, s):
|
||||
self.func_output.append(s)
|
||||
|
||||
def restore_error_output(self, s):
|
||||
self.emit(SIGNAL("restore_progress(QString)"), '<font color="red">{0}</font>'.format(s))
|
||||
|
||||
|
||||
def restore_output(self, s):
|
||||
self.emit(SIGNAL("restore_progress(QString)"),'<font color="black">{0}</font>'.format(s))
|
||||
|
||||
|
||||
def __do_restore__(self, thread_monitor):
|
||||
err_msg = []
|
||||
self.qvm_collection.lock_db_for_writing()
|
||||
try:
|
||||
qubesutils.backup_restore_do(str(self.backup_dir), self.vms_to_restore, self.qvm_collection, self.restore_output, self.restore_error_output)
|
||||
except Exception as ex:
|
||||
err_msg.append(str(ex))
|
||||
|
||||
self.qvm_collection.unlock_db()
|
||||
if len(err_msg) > 0 :
|
||||
thread_monitor.set_error_msg('\n'.join(err_msg))
|
||||
self.emit(SIGNAL("restore_progress(QString)"),'<b><font color="red">{0}</font></b>'.format("Finished with errors!"))
|
||||
else:
|
||||
self.emit(SIGNAL("restore_progress(QString)"),'<font color="green">{0}</font>'.format("Finished successfully!"))
|
||||
|
||||
thread_monitor.set_finished()
|
||||
|
||||
|
||||
def current_page_changed(self, id):
|
||||
|
||||
if self.currentPage() is self.select_vms_page:
|
||||
self.__fill_vms_list__()
|
||||
|
||||
elif self.currentPage() is self.confirm_page:
|
||||
for v in self.excluded:
|
||||
self.vms_to_restore[v] = self.excluded[v]
|
||||
self.excluded = {}
|
||||
for i in range(self.select_vms_widget.available_list.count()):
|
||||
vmname = self.select_vms_widget.available_list.item(i).text()
|
||||
self.excluded[str(vmname)] = self.vms_to_restore[str(vmname)]
|
||||
del self.vms_to_restore[str(vmname)]
|
||||
|
||||
del self.func_output[:]
|
||||
qubesutils.backup_restore_print_summary(self.vms_to_restore, print_callback = self.gather_output)
|
||||
self.confirm_text_edit.setReadOnly(True)
|
||||
self.confirm_text_edit.setFontFamily("Monospace")
|
||||
self.confirm_text_edit.setText("\n".join(self.func_output))
|
||||
|
||||
|
||||
elif self.currentPage() is self.commit_page:
|
||||
self.button(self.CancelButton).setDisabled(True)
|
||||
self.button(self.FinishButton).setDisabled(True)
|
||||
|
||||
self.thread_monitor = ThreadMonitor()
|
||||
thread = threading.Thread (target= self.__do_restore__ , args=(self.thread_monitor,))
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
while not self.thread_monitor.is_finished():
|
||||
self.app.processEvents()
|
||||
time.sleep (0.1)
|
||||
|
||||
#if not self.thread_monitor.success:
|
||||
#QMessageBox.warning (None, "Backup error!", "ERROR: {1}".format(self.vm.name, self.thread_monitor.error_msg))
|
||||
|
||||
umount_device(self.dev_mount_path)
|
||||
self.button(self.FinishButton).setEnabled(True)
|
||||
|
||||
|
||||
|
||||
def has_selected_dir(self):
|
||||
return self.backup_dir != None
|
||||
|
||||
def has_selected_vms(self):
|
||||
return self.select_vms_widget.selected_list.count() > 0
|
||||
|
||||
|
||||
|
||||
# Bases on the original code by:
|
||||
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
|
||||
|
||||
def handle_exception( exc_type, exc_value, exc_traceback ):
|
||||
import sys
|
||||
import os.path
|
||||
import traceback
|
||||
|
||||
filename, line, dummy, dummy = traceback.extract_tb( exc_traceback ).pop()
|
||||
filename = os.path.basename( filename )
|
||||
error = "%s: %s" % ( exc_type.__name__, exc_value )
|
||||
|
||||
QMessageBox.critical(None, "Houston, we have a problem...",
|
||||
"Whoops. A critical error has occured. This is most likely a bug "
|
||||
"in Qubes Restore VMs application.<br><br>"
|
||||
"<b><i>%s</i></b>" % error +
|
||||
"at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
|
||||
% ( line, filename ))
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
global qubes_host
|
||||
qubes_host = QubesHost()
|
||||
|
||||
global app
|
||||
app = QApplication(sys.argv)
|
||||
app.setOrganizationName("The Qubes Project")
|
||||
app.setOrganizationDomain("http://qubes-os.org")
|
||||
app.setApplicationName("Qubes Restore VMs")
|
||||
|
||||
sys.excepthook = handle_exception
|
||||
|
||||
qvm_collection = QubesVmCollection()
|
||||
qvm_collection.lock_db_for_reading()
|
||||
qvm_collection.load()
|
||||
qvm_collection.unlock_db()
|
||||
|
||||
global restore_window
|
||||
restore_window = RestoreVMsWindow()
|
||||
|
||||
restore_window.show()
|
||||
|
||||
app.exec_()
|
||||
app.exit()
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
403
qubesmanager/settings.py
Normal file
@ -0,0 +1,403 @@
|
||||
#!/usr/bin/python2.6
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2012 Agnieszka Kostrzewa <agnieszka.kostrzewa@gmail.com>
|
||||
# Copyright (C) 2012 Marek Marczykowski <marmarek@mimuw.edu.pl>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
import sys
|
||||
import os
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtGui import *
|
||||
|
||||
from qubes.qubes import QubesVmCollection
|
||||
from qubes.qubes import QubesVmLabels
|
||||
from qubes.qubes import QubesException
|
||||
from qubes.qubes import qubes_appmenu_create_cmd
|
||||
from qubes.qubes import qubes_appmenu_remove_cmd
|
||||
from qubes.qubes import QubesDaemonPidfile
|
||||
from qubes.qubes import QubesHost
|
||||
from qubes.qubes import qrexec_client_path
|
||||
|
||||
import qubesmanager.resources_rc
|
||||
|
||||
from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
|
||||
|
||||
import subprocess
|
||||
import time
|
||||
import threading
|
||||
from operator import itemgetter
|
||||
|
||||
from ui_settingsdlg import *
|
||||
from multiselectwidget import *
|
||||
from appmenu_select import *
|
||||
from firewall import *
|
||||
|
||||
|
||||
class VMSettingsWindow(Ui_SettingsDialog, QDialog):
|
||||
tabs_indices = {"basic": 0,
|
||||
"advanced": 1,
|
||||
"firewall": 2,
|
||||
"devices": 3,
|
||||
"applications": 4,
|
||||
"services": 5,}
|
||||
|
||||
def __init__(self, vm, app, qvm_collection, init_page="basic", parent=None):
|
||||
super(VMSettingsWindow, self).__init__(parent)
|
||||
|
||||
self.app = app
|
||||
self.qvm_collection = qvm_collection
|
||||
self.vm = vm
|
||||
if self.vm.template_vm:
|
||||
self.source_vm = self.vm.template_vm
|
||||
else:
|
||||
self.source_vm = self.vm
|
||||
|
||||
self.setupUi(self)
|
||||
if init_page in self.tabs_indices:
|
||||
idx = self.tabs_indices[init_page]
|
||||
assert (idx in range(self.tabWidget.count()))
|
||||
self.tabWidget.setCurrentIndex(idx)
|
||||
|
||||
self.connect(self.buttonBox, SIGNAL("accepted()"), self.save_and_apply)
|
||||
self.connect(self.buttonBox, SIGNAL("rejected()"), self.reject)
|
||||
|
||||
self.tabWidget.currentChanged.connect(self.current_tab_changed)
|
||||
|
||||
###### basic tab
|
||||
self.__init_basic_tab__()
|
||||
|
||||
###### firewall tab
|
||||
|
||||
model = QubesFirewallRulesModel()
|
||||
model.set_vm(vm)
|
||||
self.set_fw_model(model)
|
||||
|
||||
|
||||
self.newRuleButton.clicked.connect(self.new_rule_button_pressed)
|
||||
self.editRuleButton.clicked.connect(self.edit_rule_button_pressed)
|
||||
self.deleteRuleButton.clicked.connect(self.delete_rule_button_pressed)
|
||||
self.policyAllowRadioButton.toggled.connect(self.policy_radio_toggled)
|
||||
self.dnsCheckBox.toggled.connect(self.dns_checkbox_toggled)
|
||||
self.icmpCheckBox.toggled.connect(self.icmp_checkbox_toggled)
|
||||
|
||||
####### devices tab
|
||||
self.dev_list = MultiSelectWidget(self)
|
||||
self.devices_layout.addWidget(self.dev_list)
|
||||
|
||||
####### apps tab
|
||||
if not vm.is_netvm():
|
||||
self.app_list = MultiSelectWidget(self)
|
||||
self.apps_layout.addWidget(self.app_list)
|
||||
self.AppListManager = AppmenuSelectManager(self.vm, self.app_list)
|
||||
else:
|
||||
self.tabWidget.setTabEnabled(self.tabs_indices["applications"], False)
|
||||
|
||||
def reject(self):
|
||||
self.done(0)
|
||||
|
||||
#needed not to close the dialog before applying changes
|
||||
def accept(self):
|
||||
pass
|
||||
|
||||
def save_and_apply(self):
|
||||
thread_monitor = ThreadMonitor()
|
||||
thread = threading.Thread (target=self.__save_changes__, args=(thread_monitor,))
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
progress = QProgressDialog ("Applying settings to <b>{0}</b>...".format(self.vm.name), "", 0, 0)
|
||||
progress.setCancelButton(None)
|
||||
progress.setModal(True)
|
||||
progress.show()
|
||||
|
||||
while not thread_monitor.is_finished():
|
||||
self.app.processEvents()
|
||||
time.sleep (0.1)
|
||||
|
||||
progress.hide()
|
||||
|
||||
if not thread_monitor.success:
|
||||
QMessageBox.warning (None, "Error while changing settings for {0}!", "ERROR: {1}".format(self.vm.name, thread_monitor.error_msg))
|
||||
|
||||
self.done(0)
|
||||
|
||||
def __save_changes__(self, thread_monitor):
|
||||
ret = self.__apply_basic_tab__()
|
||||
if len(ret) > 0 :
|
||||
thread_monitor.set_error_msg('\n'.join(ret))
|
||||
thread_monitor.set_finished()
|
||||
return
|
||||
#self.fw_model.apply_rules()
|
||||
self.AppListManager.save_appmenu_select_changes()
|
||||
thread_monitor.set_finished()
|
||||
|
||||
def current_tab_changed(self, idx):
|
||||
if idx == self.tabs_indices["firewall"]:
|
||||
if self.vm.netvm_vm is not None and not self.vm.netvm_vm.is_proxyvm():
|
||||
QMessageBox.warning (None, "VM configuration problem!", "The '{0}' AppVM is not network connected to a FirewallVM!<p>".format(self.vm.name) +\
|
||||
"You may edit the '{0}' VM firewall rules, but these will not take any effect until you connect it to a working Firewall VM.".format(self.vm.name))
|
||||
|
||||
|
||||
|
||||
######### basic tab
|
||||
|
||||
def __init_basic_tab__(self):
|
||||
self.vmname.setText(self.vm.name)
|
||||
|
||||
#self.qvm_collection.lock_db_for_reading()
|
||||
#self.qvm_collection.load()
|
||||
#self.qvm_collection.unlock_db()
|
||||
|
||||
self.label_list = QubesVmLabels.values()
|
||||
self.label_list.sort(key=lambda l: l.index)
|
||||
self.label_idx = 0
|
||||
for (i, label) in enumerate(self.label_list):
|
||||
if label == self.vm.label:
|
||||
self.label_idx = i
|
||||
self.vmlabel.insertItem(i, label.name)
|
||||
self.vmlabel.setItemIcon (i, QIcon(label.icon_path))
|
||||
self.vmlabel.setCurrentIndex(self.label_idx)
|
||||
|
||||
if not self.vm.is_template() and self.vm.template_vm is not None:
|
||||
template_vm_list = [vm for vm in self.qvm_collection.values() if not vm.internal and vm.is_template()]
|
||||
self.template_idx = 0
|
||||
for (i, vm) in enumerate(template_vm_list):
|
||||
text = vm.name
|
||||
if vm is self.qvm_collection.get_default_template_vm():
|
||||
text += " (default)"
|
||||
if vm.qid == self.vm.template_vm.qid:
|
||||
self.template_idx = i
|
||||
text += " (current)"
|
||||
self.template_name.insertItem(i, text)
|
||||
self.template_name.setCurrentIndex(self.template_idx)
|
||||
else:
|
||||
self.template_name.setEnabled(False)
|
||||
|
||||
if not self.vm.is_netvm():
|
||||
netvm_list = [vm for vm in self.qvm_collection.values() if not vm.internal and vm.is_netvm()]
|
||||
self.netvm_idx = 0
|
||||
for (i, vm) in enumerate(netvm_list):
|
||||
text = vm.name
|
||||
if vm is self.qvm_collection.get_default_netvm_vm():
|
||||
text += " (default)"
|
||||
if vm.qid == self.vm.netvm_vm.qid:
|
||||
self.netvm_idx = i
|
||||
text += " (current)"
|
||||
self.netVM.insertItem(i, text)
|
||||
self.netVM.setCurrentIndex(self.netvm_idx)
|
||||
else:
|
||||
self.netVM.setEnabled(False)
|
||||
|
||||
#self.vmname.selectAll()
|
||||
#self.vmname.setFocus()
|
||||
|
||||
def __apply_basic_tab__(self):
|
||||
msg = []
|
||||
|
||||
if self.vm.is_running():
|
||||
msg.append("Can't change settings of a running VM.")
|
||||
msg.append("telemele")
|
||||
return msg
|
||||
|
||||
# vmname changed
|
||||
vmname = str(self.vmname.text())
|
||||
if self.vm.name != vmname:
|
||||
if self.qvm_collection.get_vm_by_name(vmname) is not None:
|
||||
msg.append("A VM named <b>{0}</b> already exists in the system!".format(vmname))
|
||||
else:
|
||||
oldname = self.vm.name
|
||||
try:
|
||||
self.qvm_collection.lock_db_for_writing()
|
||||
self.vm.pre_rename(vmname)
|
||||
self.vm.set_name(vmname)
|
||||
self.vm.post_rename(oldname)
|
||||
self.qvm_collection.save()
|
||||
except Exception as ex:
|
||||
msg.append(str(ex))
|
||||
finally:
|
||||
self.qvm_collection.unlock_db()
|
||||
|
||||
#vm label changed
|
||||
if self.vmlabel.currentIndex() != self.label_idx:
|
||||
label = self.label_list[self.vmlabel.currentIndex()]
|
||||
self.qvm_collection.lock_db_for_writing()
|
||||
self.vm.label = label
|
||||
self.qvm_collection.save()
|
||||
self.qvm_collection.unlock_db()
|
||||
|
||||
return msg
|
||||
|
||||
# template_vm = template_vm_list[dialog.template_name.currentIndex()]
|
||||
# allow_networking = dialog.allow_networking.isChecked()
|
||||
|
||||
######### firewall tab related
|
||||
|
||||
def set_fw_model(self, model):
|
||||
self.fw_model = model
|
||||
self.rulesTreeView.setModel(model)
|
||||
self.rulesTreeView.header().setResizeMode(QHeaderView.ResizeToContents)
|
||||
self.rulesTreeView.header().setResizeMode(0, QHeaderView.Stretch)
|
||||
self.set_allow(model.allow)
|
||||
self.dnsCheckBox.setChecked(model.allowDns)
|
||||
self.icmpCheckBox.setChecked(model.allowIcmp)
|
||||
|
||||
def set_allow(self, allow):
|
||||
self.policyAllowRadioButton.setChecked(allow)
|
||||
self.policyDenyRadioButton.setChecked(not allow)
|
||||
|
||||
def policy_radio_toggled(self, on):
|
||||
self.fw_model.allow = self.policyAllowRadioButton.isChecked()
|
||||
|
||||
def dns_checkbox_toggled(self, on):
|
||||
self.fw_model.allowDns = on
|
||||
|
||||
def icmp_checkbox_toggled(self, on):
|
||||
self.fw_model.allowIcmp = on
|
||||
|
||||
def new_rule_button_pressed(self):
|
||||
dialog = NewFwRuleDlg()
|
||||
self.run_rule_dialog(dialog)
|
||||
|
||||
def edit_rule_button_pressed(self):
|
||||
dialog = NewFwRuleDlg()
|
||||
dialog.set_ok_enabled(True)
|
||||
selected = self.rulesTreeView.selectedIndexes()
|
||||
if len(selected) > 0:
|
||||
row = self.rulesTreeView.selectedIndexes().pop().row()
|
||||
address = self.fw_model.get_column_string(0, row).replace(' ', '')
|
||||
dialog.addressComboBox.setItemText(0, address)
|
||||
dialog.addressComboBox.setCurrentIndex(0)
|
||||
service = self.fw_model.get_column_string(1, row)
|
||||
dialog.serviceComboBox.setItemText(0, service)
|
||||
dialog.serviceComboBox.setCurrentIndex(0)
|
||||
self.run_rule_dialog(dialog, row)
|
||||
|
||||
def delete_rule_button_pressed(self):
|
||||
for i in set([index.row() for index in self.rulesTreeView.selectedIndexes()]):
|
||||
self.fw_model.removeChild(i)
|
||||
|
||||
def run_rule_dialog(self, dialog, row = None):
|
||||
if dialog.exec_():
|
||||
address = str(dialog.addressComboBox.currentText())
|
||||
service = str(dialog.serviceComboBox.currentText())
|
||||
port = None
|
||||
port2 = None
|
||||
|
||||
unmask = address.split("/", 1)
|
||||
if len(unmask) == 2:
|
||||
address = unmask[0]
|
||||
netmask = int(unmask[1])
|
||||
else:
|
||||
netmask = 32
|
||||
|
||||
if address == "*":
|
||||
address = "0.0.0.0"
|
||||
netmask = 0
|
||||
|
||||
if service == "*":
|
||||
service = "0"
|
||||
try:
|
||||
range = service.split("-", 1)
|
||||
if len(range) == 2:
|
||||
port = int(range[0])
|
||||
port2 = int(range[1])
|
||||
else:
|
||||
port = int(service)
|
||||
except (TypeError, ValueError) as ex:
|
||||
port = self.fw_model.get_service_port(service)
|
||||
|
||||
if port is not None:
|
||||
if port2 is not None and port2 <= port:
|
||||
QMessageBox.warning(None, "Invalid service ports range", "Port {0} is lower than port {1}.".format(port2, port))
|
||||
else:
|
||||
item = QubesFirewallRuleItem(address, netmask, port, port2)
|
||||
if row is not None:
|
||||
self.fw_model.setChild(row, item)
|
||||
else:
|
||||
self.fw_model.appendChild(item)
|
||||
else:
|
||||
QMessageBox.warning(None, "Invalid service name", "Service '{0} is unknown.".format(service))
|
||||
|
||||
|
||||
# Bases on the original code by:
|
||||
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
|
||||
|
||||
def handle_exception( exc_type, exc_value, exc_traceback ):
|
||||
import sys
|
||||
import os.path
|
||||
import traceback
|
||||
|
||||
filename, line, dummy, dummy = traceback.extract_tb( exc_traceback ).pop()
|
||||
filename = os.path.basename( filename )
|
||||
error = "%s: %s" % ( exc_type.__name__, exc_value )
|
||||
|
||||
QMessageBox.critical(None, "Houston, we have a problem...",
|
||||
"Whoops. A critical error has occured. This is most likely a bug "
|
||||
"in Qubes VM Settings application.<br><br>"
|
||||
"<b><i>%s</i></b>" % error +
|
||||
"at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
|
||||
% ( line, filename ))
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
global qubes_host
|
||||
qubes_host = QubesHost()
|
||||
|
||||
global app
|
||||
app = QApplication(sys.argv)
|
||||
app.setOrganizationName("The Qubes Project")
|
||||
app.setOrganizationDomain("http://qubes-os.org")
|
||||
app.setApplicationName("Qubes VM Settings")
|
||||
|
||||
sys.excepthook = handle_exception
|
||||
|
||||
qvm_collection = QubesVmCollection()
|
||||
qvm_collection.lock_db_for_reading()
|
||||
qvm_collection.load()
|
||||
qvm_collection.unlock_db()
|
||||
|
||||
vm = None
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
vm = qvm_collection.get_vm_by_name(sys.argv[1])
|
||||
if vm is None or vm.qid not in qvm_collection:
|
||||
QMessageBox.critical(None, "Qubes VM Settings Error",
|
||||
"A VM with the name '{0}' does not exist in the system.".format(sys.argv[1]))
|
||||
sys.exit(1)
|
||||
else:
|
||||
vms_list = [vm.name for vm in qvm_collection.values() if (vm.is_appvm() or vm.is_template())]
|
||||
vmname = QInputDialog.getItem(None, "Select VM", "Select VM:", vms_list, editable = False)
|
||||
if not vmname[1]:
|
||||
sys.exit(1)
|
||||
vm = qvm_collection.get_vm_by_name(vmname[0])
|
||||
|
||||
|
||||
global settings_window
|
||||
settings_window = VMSettingsWindow(vm, app, qvm_collection, "basic")
|
||||
|
||||
settings_window.show()
|
||||
|
||||
app.exec_()
|
||||
app.exit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
44
qubesmanager/thread_monitor.py
Normal file
@ -0,0 +1,44 @@
|
||||
#!/usr/bin/python2.6
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2011 Marek Marczykowski <marmarek@mimuw.edu.pl>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
from PyQt4.QtCore import *
|
||||
|
||||
import threading
|
||||
|
||||
class ThreadMonitor(QObject):
|
||||
def __init__(self):
|
||||
self.success = True
|
||||
self.error_msg = None
|
||||
self.event_finished = threading.Event()
|
||||
|
||||
def set_error_msg(self, error_msg):
|
||||
self.success = False
|
||||
self.error_msg = error_msg
|
||||
self.set_finished()
|
||||
|
||||
def is_finished(self):
|
||||
return self.event_finished.is_set()
|
||||
|
||||
def set_finished(self):
|
||||
self.event_finished.set()
|
||||
|
@ -1,22 +1,35 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file alias="qubes.png">icons/qubes.png</file>
|
||||
<file alias="appvm.png">icons/appvm.png</file>
|
||||
<file alias="netvm.png">icons/netvm.png</file>
|
||||
<file alias="networking.png">icons/networking.png</file>
|
||||
<file alias="dom0.png">icons/dom0.png</file>
|
||||
<file alias="storagevm.png">icons/storagevm.png</file>
|
||||
<file alias="templatevm.png">icons/templatevm.png</file>
|
||||
<file alias="updateable.png">icons/updateable.png</file>
|
||||
<file alias="home.png">icons/home.png</file>
|
||||
<file alias="root.png">icons/root.png</file>
|
||||
<file alias="createvm.png">icons/createvm.png</file>
|
||||
<file alias="removevm.png">icons/removevm.png</file>
|
||||
<file alias="shutdownvm.png">icons/shutdownvm.png</file>
|
||||
<file alias="resumevm.png">icons/resumevm.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="firewall.png">icons/firewall.png</file>
|
||||
</qresource>
|
||||
<RCC>
|
||||
<qresource>
|
||||
<file alias="mount.png">icons/mount.png</file>
|
||||
<file alias="pencil.png">icons/pencil.png</file>
|
||||
<file alias="redfirewall.png">icons/redfirewall.png</file>
|
||||
<file alias="edit.png">icons/edit.png</file>
|
||||
<file alias="add.png">icons/add.png</file>
|
||||
<file alias="flag-blue.png">icons/flag-blue.png</file>
|
||||
<file alias="flag-green.png">icons/flag-green.png</file>
|
||||
<file alias="flag-red.png">icons/flag-red.png</file>
|
||||
<file alias="flag-yellow.png">icons/flag-yellow.png</file>
|
||||
<file alias="remove.png">icons/remove.png</file>
|
||||
<file alias="on.png">icons/on.png</file>
|
||||
<file alias="appsprefs.png">icons/appsprefs.png</file>
|
||||
<file alias="newfirewall.png">icons/newfirewall.png</file>
|
||||
<file alias="qubes.png">icons/qubes.png</file>
|
||||
<file alias="appvm.png">icons/appvm.png</file>
|
||||
<file alias="netvm.png">icons/netvm.png</file>
|
||||
<file alias="networking.png">icons/networking.png</file>
|
||||
<file alias="dom0.png">icons/dom0.png</file>
|
||||
<file alias="storagevm.png">icons/storagevm.png</file>
|
||||
<file alias="templatevm.png">icons/templatevm.png</file>
|
||||
<file alias="updateable.png">icons/updateable.png</file>
|
||||
<file alias="home.png">icons/home.png</file>
|
||||
<file alias="root.png">icons/root.png</file>
|
||||
<file alias="createvm.png">icons/createvm.png</file>
|
||||
<file alias="removevm.png">icons/removevm.png</file>
|
||||
<file alias="shutdownvm.png">icons/shutdownvm.png</file>
|
||||
<file alias="resumevm.png">icons/resumevm.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="firewall.png">icons/firewall.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
229
restoredlg.ui
Normal file
@ -0,0 +1,229 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Restore</class>
|
||||
<widget class="QWizard" name="Restore">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>700</width>
|
||||
<height>399</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Qubes Restore VMs</string>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="English" country="UnitedStates"/>
|
||||
</property>
|
||||
<property name="options">
|
||||
<set>QWizard::NoBackButtonOnLastPage|QWizard::NoBackButtonOnStartPage</set>
|
||||
</property>
|
||||
<widget class="QWizardPage" name="select_dir_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Backup source location</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="dev_combobox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>dev1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>longdeviceblablabla</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>dev2</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>dev3</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Backup directory:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="dir_line_edit"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QToolButton" name="select_path_button">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="options_groupbox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Restore options</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="ignore_missing">
|
||||
<property name="toolTip">
|
||||
<string>Ignore missing templates or netvms, restore VMs anyway.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ignore missing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="skip_dom0">
|
||||
<property name="text">
|
||||
<string>skip dom0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="ignore_uname_mismatch">
|
||||
<property name="toolTip">
|
||||
<string>Ignore dom0 username mismatch while restoring homedir.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ignore username mismatch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>215</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWizardPage" name="select_vms_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="select_vms_groupbox">
|
||||
<property name="title">
|
||||
<string>VMs to restore</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="select_vms_layout"/>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWizardPage" name="confirm_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>false</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>You're about to perform the following actions:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="confirm_text_edit">
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A lot of info<br />A lot of info<br />A lot of info<br />A lot of info<br />A lot of info<br />A lot of info<br />A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A lot of info A lot of info A lot of info A lot of info A lot of info A lot of info<br />A lot of info</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>false</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>To continue press Next. </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWizardPage" name="commit_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="commit_text_edit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -33,12 +33,25 @@ cp qubes-appmenu-select $RPM_BUILD_ROOT/usr/bin
|
||||
mkdir -p $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager/
|
||||
cp qubesmanager/main.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/appmenu_select.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/backup.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/backup_utils.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/firewall.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/qrc_resources.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/global_settings.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/multiselectwidget.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/restore.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/settings.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/thread_monitor.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/resources_rc.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/__init__.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/ui_backupdlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/ui_editfwrulesdlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/ui_globalsettingsdlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/ui_mainwindow.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/ui_multiselectwidget.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/ui_newappvmdlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/ui_newfwruledlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/ui_editfwrulesdlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/ui_restoredlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
cp qubesmanager/ui_settingsdlg.py{,c,o} $RPM_BUILD_ROOT%{python_sitearch}/qubesmanager
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/share/applications
|
||||
cp qubes-manager.desktop $RPM_BUILD_ROOT/usr/share/applications
|
||||
@ -67,21 +80,60 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%{python_sitearch}/qubesmanager/appmenu_select.py
|
||||
%{python_sitearch}/qubesmanager/appmenu_select.pyc
|
||||
%{python_sitearch}/qubesmanager/appmenu_select.pyo
|
||||
%{python_sitearch}/qubesmanager/backup.py
|
||||
%{python_sitearch}/qubesmanager/backup.pyc
|
||||
%{python_sitearch}/qubesmanager/backup.pyo
|
||||
%{python_sitearch}/qubesmanager/backup_utils.py
|
||||
%{python_sitearch}/qubesmanager/backup_utils.pyc
|
||||
%{python_sitearch}/qubesmanager/backup_utils.pyo
|
||||
%{python_sitearch}/qubesmanager/firewall.py
|
||||
%{python_sitearch}/qubesmanager/firewall.pyc
|
||||
%{python_sitearch}/qubesmanager/firewall.pyo
|
||||
%{python_sitearch}/qubesmanager/qrc_resources.py
|
||||
%{python_sitearch}/qubesmanager/qrc_resources.pyc
|
||||
%{python_sitearch}/qubesmanager/qrc_resources.pyo
|
||||
%{python_sitearch}/qubesmanager/global_settings.py
|
||||
%{python_sitearch}/qubesmanager/global_settings.pyc
|
||||
%{python_sitearch}/qubesmanager/global_settings.pyo
|
||||
%{python_sitearch}/qubesmanager/multiselectwidget.py
|
||||
%{python_sitearch}/qubesmanager/multiselectwidget.pyc
|
||||
%{python_sitearch}/qubesmanager/multiselectwidget.pyo
|
||||
%{python_sitearch}/qubesmanager/restore.py
|
||||
%{python_sitearch}/qubesmanager/restore.pyc
|
||||
%{python_sitearch}/qubesmanager/restore.pyo
|
||||
%{python_sitearch}/qubesmanager/settings.py
|
||||
%{python_sitearch}/qubesmanager/settings.pyc
|
||||
%{python_sitearch}/qubesmanager/settings.pyo
|
||||
%{python_sitearch}/qubesmanager/thread_monitor.py
|
||||
%{python_sitearch}/qubesmanager/thread_monitor.pyc
|
||||
%{python_sitearch}/qubesmanager/thread_monitor.pyo
|
||||
%{python_sitearch}/qubesmanager/resources_rc.py
|
||||
%{python_sitearch}/qubesmanager/resources_rc.pyc
|
||||
%{python_sitearch}/qubesmanager/resources_rc.pyo
|
||||
%{python_sitearch}/qubesmanager/ui_backupdlg.py
|
||||
%{python_sitearch}/qubesmanager/ui_backupdlg.pyc
|
||||
%{python_sitearch}/qubesmanager/ui_backupdlg.pyo
|
||||
%{python_sitearch}/qubesmanager/ui_editfwrulesdlg.py
|
||||
%{python_sitearch}/qubesmanager/ui_editfwrulesdlg.pyc
|
||||
%{python_sitearch}/qubesmanager/ui_editfwrulesdlg.pyo
|
||||
%{python_sitearch}/qubesmanager/ui_globalsettingsdlg.py
|
||||
%{python_sitearch}/qubesmanager/ui_globalsettingsdlg.pyc
|
||||
%{python_sitearch}/qubesmanager/ui_globalsettingsdlg.pyo
|
||||
%{python_sitearch}/qubesmanager/ui_mainwindow.py
|
||||
%{python_sitearch}/qubesmanager/ui_mainwindow.pyc
|
||||
%{python_sitearch}/qubesmanager/ui_mainwindow.pyo
|
||||
%{python_sitearch}/qubesmanager/ui_multiselectwidget.py
|
||||
%{python_sitearch}/qubesmanager/ui_multiselectwidget.pyc
|
||||
%{python_sitearch}/qubesmanager/ui_multiselectwidget.pyo
|
||||
%{python_sitearch}/qubesmanager/ui_newappvmdlg.py
|
||||
%{python_sitearch}/qubesmanager/ui_newappvmdlg.pyc
|
||||
%{python_sitearch}/qubesmanager/ui_newappvmdlg.pyo
|
||||
%{python_sitearch}/qubesmanager/ui_newfwruledlg.py
|
||||
%{python_sitearch}/qubesmanager/ui_newfwruledlg.pyc
|
||||
%{python_sitearch}/qubesmanager/ui_newfwruledlg.pyo
|
||||
%{python_sitearch}/qubesmanager/ui_editfwrulesdlg.py
|
||||
%{python_sitearch}/qubesmanager/ui_editfwrulesdlg.pyc
|
||||
%{python_sitearch}/qubesmanager/ui_editfwrulesdlg.pyo
|
||||
%{python_sitearch}/qubesmanager/ui_restoredlg.py
|
||||
%{python_sitearch}/qubesmanager/ui_restoredlg.pyc
|
||||
%{python_sitearch}/qubesmanager/ui_restoredlg.pyo
|
||||
%{python_sitearch}/qubesmanager/ui_settingsdlg.py
|
||||
%{python_sitearch}/qubesmanager/ui_settingsdlg.pyc
|
||||
%{python_sitearch}/qubesmanager/ui_settingsdlg.pyo
|
||||
|
||||
|
||||
/usr/share/applications/qubes-manager.desktop
|
||||
|
807
settingsdlg.ui
Normal file
@ -0,0 +1,807 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsDialog</class>
|
||||
<widget class="QDialog" name="SettingsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>694</width>
|
||||
<height>483</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/root.png</normaloff>:/root.png</iconset>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="English" country="UnitedStates"/>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="basic_tab">
|
||||
<property name="locale">
|
||||
<locale language="English" country="UnitedStates"/>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Basic</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Name & label:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="vmname">
|
||||
<property name="text">
|
||||
<string>myappvm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Template:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="template_name"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>NetVM:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="netVM"/>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Include in backups by default</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Info</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="type_label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>AppVM</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Installed by RPM:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="rpm_label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Disk storage</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="priv_size">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>GB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Private storage max. size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>73</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="advanced_tab">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Advanced</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Memory/CPU</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Initial memory:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="mem_size">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>xx</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>MB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Max memory:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="max_mem_size">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>400</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>MB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>VCPUs no.:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="vcpus">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="include_in_balancing">
|
||||
<property name="text">
|
||||
<string>Include in memory balancing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_10">
|
||||
<property name="title">
|
||||
<string>Kernel</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>Kernel:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="kernel"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>Kernel opts:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="kernel_opts">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>[]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_11">
|
||||
<property name="title">
|
||||
<string>Paths</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>dir:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="dir_path">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>dir_path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>config:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="config_path">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>config_path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_23">
|
||||
<property name="text">
|
||||
<string>root img:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="root_img_path">
|
||||
<property name="text">
|
||||
<string>root_img_path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>root volatile img:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="volatile_img_path">
|
||||
<property name="text">
|
||||
<string>volatile_path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="text">
|
||||
<string>private img:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="private_img_path">
|
||||
<property name="text">
|
||||
<string>private_path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>88</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="firewall_tab">
|
||||
<attribute name="title">
|
||||
<string>Firewall rules</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="policyAllowRadioButton">
|
||||
<property name="text">
|
||||
<string>Allow network access except...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="policyDenyRadioButton">
|
||||
<property name="text">
|
||||
<string>Deny network access except...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMaximumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QTreeView" name="rulesTreeView">
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="uniformRowHeights">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="allColumnsShowFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>40</number>
|
||||
</attribute>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="icmpCheckBox">
|
||||
<property name="text">
|
||||
<string>Allow ICMP traffic</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="dnsCheckBox">
|
||||
<property name="text">
|
||||
<string>Allow DNS queries</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QPushButton" name="newRuleButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/add.png</normaloff>:/add.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="editRuleButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pencil.png</normaloff>:/pencil.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteRuleButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/remove.png</normaloff>:/remove.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="devices_tab">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Devices</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="devices_layout"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="apps_tab">
|
||||
<attribute name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/appsprefs.png</normaloff>:/appsprefs.png</iconset>
|
||||
</attribute>
|
||||
<attribute name="title">
|
||||
<string>Applications</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_7">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="apps_layout"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="services_tab">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Services</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLineEdit" name="service_lineEdit"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="add_button">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/add.png</normaloff>:/add.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" rowspan="2">
|
||||
<widget class="QListWidget" name="services_list">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ntpd</string>
|
||||
</property>
|
||||
<property name="checkState">
|
||||
<enum>Checked</enum>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>cupsd</string>
|
||||
</property>
|
||||
<property name="checkState">
|
||||
<enum>Checked</enum>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>meminfo</string>
|
||||
</property>
|
||||
<property name="checkState">
|
||||
<enum>Checked</enum>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Checked services will be turned on.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Unchecked services will be turned off.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Unlisted services will follow default VM's settings.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QPushButton" name="remove_button">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/remove.png</normaloff>:/remove.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="resources.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>SettingsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>SettingsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|