Merge branch 'new-backups'
This commit is contained in:
		
						commit
						fda7180d16
					
				
							
								
								
									
										104
									
								
								backupdlg.ui
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								backupdlg.ui
									
									
									
									
									
								
							@ -6,7 +6,7 @@
 | 
			
		||||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>700</width>
 | 
			
		||||
    <width>650</width>
 | 
			
		||||
    <height>399</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
@ -148,21 +148,21 @@
 | 
			
		||||
   </layout>
 | 
			
		||||
  </widget>
 | 
			
		||||
  <widget class="QWizardPage" name="select_dir_page">
 | 
			
		||||
   <layout class="QHBoxLayout" name="horizontalLayout">
 | 
			
		||||
    <item>
 | 
			
		||||
   <layout class="QGridLayout" name="gridLayout_5">
 | 
			
		||||
    <item row="0" column="0">
 | 
			
		||||
     <widget class="QGroupBox" name="groupBox">
 | 
			
		||||
      <property name="title">
 | 
			
		||||
       <string>Backup destination directory</string>
 | 
			
		||||
      </property>
 | 
			
		||||
      <layout class="QGridLayout" name="gridLayout">
 | 
			
		||||
       <item row="0" column="0">
 | 
			
		||||
       <item row="1" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Device:</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="0" column="1">
 | 
			
		||||
       <item row="1" column="2">
 | 
			
		||||
        <widget class="QComboBox" name="dev_combobox">
 | 
			
		||||
         <property name="sizePolicy">
 | 
			
		||||
          <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
 | 
			
		||||
@ -192,23 +192,93 @@
 | 
			
		||||
         </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">
 | 
			
		||||
       <item row="4" column="2">
 | 
			
		||||
        <widget class="QLineEdit" name="dir_line_edit"/>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="1" column="2">
 | 
			
		||||
       <item row="4" column="3">
 | 
			
		||||
        <widget class="QToolButton" name="select_path_button">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>...</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="2" column="2">
 | 
			
		||||
        <widget class="QComboBox" name="appvm_combobox"/>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="2" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_5">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Target AppVM:</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="4" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_2">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Backup directory or VM command:</string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="wordWrap">
 | 
			
		||||
          <bool>true</bool>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
      </layout>
 | 
			
		||||
     </widget>
 | 
			
		||||
    </item>
 | 
			
		||||
    <item row="1" column="0">
 | 
			
		||||
     <widget class="QGroupBox" name="groupBox_2">
 | 
			
		||||
      <property name="title">
 | 
			
		||||
       <string>Backup security</string>
 | 
			
		||||
      </property>
 | 
			
		||||
      <layout class="QFormLayout" name="formLayout">
 | 
			
		||||
       <item row="2" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_12">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string><html><head/><body><p>Encryption / Verification<br/>passphrase:</p></body></html></string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="0" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_10">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Encrypt backup:</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="0" column="1">
 | 
			
		||||
        <widget class="QCheckBox" name="encryption_checkbox">
 | 
			
		||||
         <property name="layoutDirection">
 | 
			
		||||
          <enum>Qt::LeftToRight</enum>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string/>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="checked">
 | 
			
		||||
          <bool>true</bool>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="5" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_11">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string><html><head/><body><p>Reenter passphrase:</p></body></html></string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="2" column="1">
 | 
			
		||||
        <widget class="QLineEdit" name="passphrase_line_edit">
 | 
			
		||||
         <property name="echoMode">
 | 
			
		||||
          <enum>QLineEdit::Password</enum>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="5" column="1">
 | 
			
		||||
        <widget class="QLineEdit" name="passphrase_line_edit_verify">
 | 
			
		||||
         <property name="echoMode">
 | 
			
		||||
          <enum>QLineEdit::Password</enum>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
      </layout>
 | 
			
		||||
     </widget>
 | 
			
		||||
    </item>
 | 
			
		||||
@ -238,8 +308,8 @@
 | 
			
		||||
       <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="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html></string>
 | 
			
		||||
</style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;">
 | 
			
		||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"><br /></p></body></html></string>
 | 
			
		||||
      </property>
 | 
			
		||||
     </widget>
 | 
			
		||||
    </item>
 | 
			
		||||
@ -264,7 +334,7 @@ p, li { white-space: pre-wrap; }
 | 
			
		||||
  <widget class="QWizardPage" name="commit_page">
 | 
			
		||||
   <layout class="QVBoxLayout" name="verticalLayout_3">
 | 
			
		||||
    <item>
 | 
			
		||||
     <widget class="QLabel" name="label_8">
 | 
			
		||||
     <widget class="QLabel" name="progress_status">
 | 
			
		||||
      <property name="font">
 | 
			
		||||
       <font>
 | 
			
		||||
        <pointsize>9</pointsize>
 | 
			
		||||
 | 
			
		||||
@ -31,6 +31,7 @@ from qubes.qubes import QubesVmCollection
 | 
			
		||||
from qubes.qubes import QubesException
 | 
			
		||||
from qubes.qubes import QubesDaemonPidfile
 | 
			
		||||
from qubes.qubes import QubesHost
 | 
			
		||||
from qubes import backup
 | 
			
		||||
from qubes import qubesutils
 | 
			
		||||
 | 
			
		||||
import qubesmanager.resources_rc
 | 
			
		||||
@ -65,9 +66,9 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
			
		||||
        self.shutdown_vm_func = shutdown_vm_func
 | 
			
		||||
 | 
			
		||||
        self.dev_mount_path = None
 | 
			
		||||
        self.backup_dir = None
 | 
			
		||||
        self.backup_location = None
 | 
			
		||||
        self.func_output = []
 | 
			
		||||
        self.excluded = []
 | 
			
		||||
        self.selected_vms = []
 | 
			
		||||
 | 
			
		||||
        for vm in self.qvm_collection.values():
 | 
			
		||||
            if vm.qid == 0:
 | 
			
		||||
@ -78,8 +79,9 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
			
		||||
 | 
			
		||||
        self.setupUi(self)
 | 
			
		||||
 | 
			
		||||
        self.progress_status.text = "Backup in progress..."
 | 
			
		||||
        self.show_running_vms_warning(False)
 | 
			
		||||
        self.dir_line_edit.setReadOnly(True)
 | 
			
		||||
        self.dir_line_edit.setReadOnly(False)
 | 
			
		||||
 | 
			
		||||
        self.select_vms_widget = MultiSelectWidget(self)
 | 
			
		||||
        self.verticalLayout.insertWidget(1, self.select_vms_widget)
 | 
			
		||||
@ -92,17 +94,31 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
			
		||||
        self.shutdown_running_vms_button.clicked.connect(self.shutdown_all_running_selected)
 | 
			
		||||
        self.connect(self.dev_combobox, SIGNAL("activated(int)"), self.dev_combobox_activated)
 | 
			
		||||
        self.connect(self, SIGNAL("backup_progress(int)"), self.progress_bar.setValue)
 | 
			
		||||
        self.dir_line_edit.connect(self.dir_line_edit, SIGNAL("textChanged(QString)"), self.backup_location_changed)
 | 
			
		||||
 | 
			
		||||
        self.select_vms_page.isComplete = self.has_selected_vms
 | 
			
		||||
        self.select_dir_page.isComplete = self.has_selected_dir
 | 
			
		||||
        self.select_dir_page.isComplete = self.has_selected_dir_and_pass
 | 
			
		||||
        #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.select_vms_page.connect(
 | 
			
		||||
                self.select_vms_widget,
 | 
			
		||||
                SIGNAL("selected_changed()"),
 | 
			
		||||
                SIGNAL("completeChanged()"))
 | 
			
		||||
        self.passphrase_line_edit.connect(
 | 
			
		||||
                self.passphrase_line_edit,
 | 
			
		||||
                SIGNAL("textChanged(QString)"),
 | 
			
		||||
                self.backup_location_changed)
 | 
			
		||||
        self.passphrase_line_edit_verify.connect(
 | 
			
		||||
                self.passphrase_line_edit_verify,
 | 
			
		||||
                SIGNAL("textChanged(QString)"),
 | 
			
		||||
                self.backup_location_changed)
 | 
			
		||||
 | 
			
		||||
        self.total_size = 0
 | 
			
		||||
        self.__fill_vms_list__()
 | 
			
		||||
        fill_devs_list(self)
 | 
			
		||||
 | 
			
		||||
        fill_appvms_list(self)
 | 
			
		||||
 | 
			
		||||
    def show_running_vms_warning(self, show):
 | 
			
		||||
        self.running_vms_warning.setVisible(show)
 | 
			
		||||
        self.shutdown_running_vms_button.setVisible(show)
 | 
			
		||||
@ -114,7 +130,7 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
			
		||||
            if vm.qid == 0:
 | 
			
		||||
                local_user = grp.getgrnam('qubes').gr_mem[0]
 | 
			
		||||
                home_dir = pwd.getpwnam(local_user).pw_dir
 | 
			
		||||
                self.size = qubesutils.get_disk_usage(home_dir)
 | 
			
		||||
                self.size = backup.get_disk_usage(home_dir)
 | 
			
		||||
            else:
 | 
			
		||||
                self.size = self.get_vm_size(vm)
 | 
			
		||||
            super(BackupVMsWindow.VmListItem, self).__init__(vm.name+ " (" + qubesutils.size_to_human(self.size) + ")")
 | 
			
		||||
@ -210,7 +226,6 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
			
		||||
 | 
			
		||||
            progress.hide()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def get_running_vms(self):
 | 
			
		||||
        names = []
 | 
			
		||||
        vms = []
 | 
			
		||||
@ -221,28 +236,38 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
			
		||||
                vms.append(item.vm)
 | 
			
		||||
        return (names, vms)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    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.selected_list.count()):
 | 
			
		||||
                if self.check_running() == True:
 | 
			
		||||
                    QMessageBox.information(None, "Wait!", "Some selected VMs are running. Running VMs can not be backuped. Please shut them down or remove them from the list.")
 | 
			
		||||
                    return False
 | 
			
		||||
            if self.check_running():
 | 
			
		||||
                QMessageBox.information(None, "Wait!", "Some selected VMs are running. Running VMs can not be backuped. Please shut them down or remove them from the list.")
 | 
			
		||||
                return False
 | 
			
		||||
 | 
			
		||||
            del self.excluded[:]
 | 
			
		||||
            for i in range(self.select_vms_widget.available_list.count()):
 | 
			
		||||
                vmname =  self.select_vms_widget.available_list.item(i).vm.name
 | 
			
		||||
                self.excluded.append(vmname)
 | 
			
		||||
            self.selected_vms = []
 | 
			
		||||
            for i in range(self.select_vms_widget.selected_list.count()):
 | 
			
		||||
                self.selected_vms.append(self.select_vms_widget.selected_list.item(i).vm)
 | 
			
		||||
 | 
			
		||||
        elif self.currentPage() is self.select_dir_page:
 | 
			
		||||
            if not self.backup_location:
 | 
			
		||||
                QMessageBox.information(None, "Wait!", "Enter backup target location first.")
 | 
			
		||||
                return False
 | 
			
		||||
            if self.appvm_combobox.currentIndex() == 0 and \
 | 
			
		||||
                   not os.path.isdir(self.backup_location):
 | 
			
		||||
                QMessageBox.information(None, "Wait!",
 | 
			
		||||
                        "Selected directory do not exists or not a directory (%s)." % self.backup_location)
 | 
			
		||||
                return False
 | 
			
		||||
            if not len(self.passphrase_line_edit.text()):
 | 
			
		||||
                QMessageBox.information(None, "Wait!", "Enter passphrase for backup encryption/verification first.")
 | 
			
		||||
                return False
 | 
			
		||||
            if self.passphrase_line_edit.text() != self.passphrase_line_edit_verify.text():
 | 
			
		||||
                QMessageBox.information(None, "Wait!", "Enter the same passphrase in both fields.")
 | 
			
		||||
                return False
 | 
			
		||||
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
@ -250,21 +275,21 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
			
		||||
        self.func_output.append(s)
 | 
			
		||||
 | 
			
		||||
    def update_progress_bar(self, value):
 | 
			
		||||
        if value == 100:
 | 
			
		||||
            self.emit(SIGNAL("backup_progress(int)"), value)
 | 
			
		||||
 | 
			
		||||
    def check_backup_progress(self, initial_usage, total_backup_size):
 | 
			
		||||
        du = qubesutils.get_disk_usage(self.backup_dir)
 | 
			
		||||
        done = du - initial_usage
 | 
			
		||||
        percent = int((float(done)/total_backup_size)*100)
 | 
			
		||||
        return percent
 | 
			
		||||
        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)
 | 
			
		||||
            backup.backup_do(str(self.backup_location),
 | 
			
		||||
                    self.files_to_backup,
 | 
			
		||||
                    str(self.passphrase_line_edit.text()),
 | 
			
		||||
                    progress_callback=self.update_progress_bar,
 | 
			
		||||
                    encrypt=self.encryption_checkbox.isChecked(),
 | 
			
		||||
                    appvm=self.target_appvm)
 | 
			
		||||
            #simulate_long_lasting_proces(10, self.update_progress_bar)
 | 
			
		||||
        except Exception as ex:
 | 
			
		||||
            print "Exception:",ex
 | 
			
		||||
            msg.append(str(ex))
 | 
			
		||||
 | 
			
		||||
        if len(msg) > 0 :
 | 
			
		||||
@ -275,11 +300,21 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
			
		||||
 | 
			
		||||
    def current_page_changed(self, id):
 | 
			
		||||
        if self.currentPage() is self.confirm_page:
 | 
			
		||||
 | 
			
		||||
            self.target_appvm = None
 | 
			
		||||
            if self.appvm_combobox.currentIndex() != 0:   #An existing appvm chosen
 | 
			
		||||
                self.target_appvm = self.qvm_collection.get_vm_by_name(
 | 
			
		||||
                        self.appvm_combobox.currentText())
 | 
			
		||||
 | 
			
		||||
            del self.func_output[:]
 | 
			
		||||
            try:
 | 
			
		||||
                self.files_to_backup = qubesutils.backup_prepare(str(self.backup_dir), exclude_list = self.excluded, print_callback = self.gather_output)
 | 
			
		||||
                self.files_to_backup = backup.backup_prepare(
 | 
			
		||||
                        self.selected_vms,
 | 
			
		||||
                        print_callback = self.gather_output,
 | 
			
		||||
                        hide_vm_names=self.encryption_checkbox.isChecked())
 | 
			
		||||
            except Exception as ex:
 | 
			
		||||
                QMessageBox.critical(None, "Error while prepering backup.", "ERROR: {0}".format(ex))
 | 
			
		||||
                print "Exception:",ex
 | 
			
		||||
                QMessageBox.critical(None, "Error while preparing backup.", "ERROR: {0}".format(ex))
 | 
			
		||||
 | 
			
		||||
            self.textEdit.setReadOnly(True)
 | 
			
		||||
            self.textEdit.setFontFamily("Monospace")
 | 
			
		||||
@ -289,7 +324,6 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
			
		||||
            self.button(self.FinishButton).setDisabled(True)
 | 
			
		||||
            self.button(self.CancelButton).setDisabled(True)
 | 
			
		||||
            self.thread_monitor = ThreadMonitor()
 | 
			
		||||
            initial_usage = qubesutils.get_disk_usage(self.backup_dir)
 | 
			
		||||
            thread = threading.Thread (target= self.__do_backup__ , args=(self.thread_monitor,))
 | 
			
		||||
            thread.daemon = True
 | 
			
		||||
            thread.start()
 | 
			
		||||
@ -299,15 +333,13 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
			
		||||
            while not self.thread_monitor.is_finished():
 | 
			
		||||
                self.app.processEvents()
 | 
			
		||||
                time.sleep (0.1)
 | 
			
		||||
                counter += 1
 | 
			
		||||
                if counter == 20:
 | 
			
		||||
                    progress = self.check_backup_progress(initial_usage, self.total_size)
 | 
			
		||||
                    self.progress_bar.setValue(progress)
 | 
			
		||||
                    counter = 0
 | 
			
		||||
 | 
			
		||||
            if not self.thread_monitor.success:
 | 
			
		||||
                QMessageBox.warning (None, "Backup error!", "ERROR: {1}".format(self.vm.name, self.thread_monitor.error_msg))
 | 
			
		||||
 | 
			
		||||
                self.progress_status.setText = "Backup error."
 | 
			
		||||
                QMessageBox.warning (None, "Backup error!", "ERROR: {}".format(self.thread_monitor.error_msg))
 | 
			
		||||
            else:
 | 
			
		||||
                self.progress_bar.setValue(100)
 | 
			
		||||
                self.progress_status.setText = "Backup finished."
 | 
			
		||||
            if self.dev_mount_path != None:
 | 
			
		||||
                umount_device(self.dev_mount_path)
 | 
			
		||||
            self.button(self.FinishButton).setEnabled(True)
 | 
			
		||||
@ -315,23 +347,19 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
			
		||||
 | 
			
		||||
    def reject(self):
 | 
			
		||||
        #cancell clicked while the backup is in progress.
 | 
			
		||||
        #calling kill on cp.
 | 
			
		||||
        #calling kill on tar.
 | 
			
		||||
        if self.currentPage() is self.commit_page:
 | 
			
		||||
            manager_pid = os.getpid()
 | 
			
		||||
            cp_pid_cmd = ["ps" ,"--ppid", str(manager_pid)]
 | 
			
		||||
            pid = None
 | 
			
		||||
            archive_pid_cmd = ["ps" ,"--ppid", str(manager_pid)]
 | 
			
		||||
 | 
			
		||||
            while not self.thread_monitor.is_finished():
 | 
			
		||||
                cp_pid = subprocess.Popen(cp_pid_cmd, stdout = subprocess.PIPE)
 | 
			
		||||
                output = cp_pid.stdout.read().split("\n")
 | 
			
		||||
                archive_pid = subprocess.Popen(archive_pid_cmd, stdout = subprocess.PIPE)
 | 
			
		||||
                output = archive_pid.stdout.readlines()
 | 
			
		||||
 | 
			
		||||
                for l in output:
 | 
			
		||||
                    if l.endswith("cp"):
 | 
			
		||||
                        pid = l.split(" ")[1]
 | 
			
		||||
                        break
 | 
			
		||||
                if pid != None:
 | 
			
		||||
                    os.kill(int(pid), signal.SIGTERM)
 | 
			
		||||
                    break
 | 
			
		||||
                    if l.strip().endswith("tar"):
 | 
			
		||||
                        os.kill(int(l.split(" ")[0]), signal.SIGTERM)
 | 
			
		||||
                time.sleep(0.1)
 | 
			
		||||
 | 
			
		||||
        if self.dev_mount_path != None:
 | 
			
		||||
            umount_device(self.dev_mount_path)
 | 
			
		||||
@ -341,10 +369,16 @@ class BackupVMsWindow(Ui_Backup, QWizard):
 | 
			
		||||
    def has_selected_vms(self):
 | 
			
		||||
        return self.select_vms_widget.selected_list.count() > 0
 | 
			
		||||
 | 
			
		||||
    def has_selected_dir(self):
 | 
			
		||||
        return self.backup_dir != None
 | 
			
		||||
            
 | 
			
		||||
    def has_selected_dir_and_pass(self):
 | 
			
		||||
        if not len(self.passphrase_line_edit.text()):
 | 
			
		||||
            return False
 | 
			
		||||
        if self.passphrase_line_edit.text() != self.passphrase_line_edit_verify.text():
 | 
			
		||||
            return False
 | 
			
		||||
        return self.backup_location != None
 | 
			
		||||
 | 
			
		||||
    def backup_location_changed(self, new_dir = None):
 | 
			
		||||
        self.backup_location = str(self.dir_line_edit.text())
 | 
			
		||||
        self.select_dir_page.emit(SIGNAL("completeChanged()"))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Bases on the original code by:
 | 
			
		||||
 | 
			
		||||
@ -75,6 +75,20 @@ def umount_device(dev_mount_path):
 | 
			
		||||
            if button == QMessageBox.Ok:
 | 
			
		||||
                return dev_mount_path
 | 
			
		||||
 | 
			
		||||
def fill_appvms_list(dialog):
 | 
			
		||||
    dialog.appvm_combobox.clear()
 | 
			
		||||
    dialog.appvm_combobox.addItem("dom0")
 | 
			
		||||
 | 
			
		||||
    dialog.appvm_combobox.setCurrentIndex(0) #current selected is null ""
 | 
			
		||||
 | 
			
		||||
    for vm in dialog.qvm_collection.values():
 | 
			
		||||
        if vm.is_appvm() and vm.internal:
 | 
			
		||||
            continue
 | 
			
		||||
        if vm.is_template() and vm.installed_by_rpm:
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        if vm.is_running() and vm.qid != 0:
 | 
			
		||||
            dialog.appvm_combobox.addItem(vm.name)
 | 
			
		||||
 | 
			
		||||
def fill_devs_list(dialog):
 | 
			
		||||
    dialog.dev_combobox.clear()
 | 
			
		||||
@ -107,7 +121,7 @@ def dev_combobox_activated(dialog, idx):
 | 
			
		||||
    #there was a change
 | 
			
		||||
 | 
			
		||||
    dialog.dir_line_edit.setText("")
 | 
			
		||||
    dialog.backup_dir = None
 | 
			
		||||
    dialog.backup_location = None
 | 
			
		||||
 | 
			
		||||
    if dialog.dev_mount_path != None:
 | 
			
		||||
        dialog.dev_mount_path = umount_device(dialog.dev_mount_path)
 | 
			
		||||
@ -147,28 +161,37 @@ def dev_combobox_activated(dialog, idx):
 | 
			
		||||
    if dialog.dev_mount_path != None:
 | 
			
		||||
      # Initialize path with root of mounted device
 | 
			
		||||
      dialog.dir_line_edit.setText(dialog.dev_mount_path)
 | 
			
		||||
      dialog.backup_dir = dialog.dev_mount_path
 | 
			
		||||
      dialog.backup_location = dialog.dev_mount_path
 | 
			
		||||
 | 
			
		||||
    dialog.select_dir_page.emit(SIGNAL("completeChanged()"))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def select_path_button_clicked(dialog):
 | 
			
		||||
    dialog.backup_dir = dialog.dir_line_edit.text()
 | 
			
		||||
def select_path_button_clicked(dialog, select_file = False):
 | 
			
		||||
    dialog.backup_location = dialog.dir_line_edit.text()
 | 
			
		||||
    file_dialog = QFileDialog()
 | 
			
		||||
    file_dialog.setReadOnly(True)
 | 
			
		||||
 | 
			
		||||
    if dialog.dev_mount_path != None:
 | 
			
		||||
        new_path = file_dialog.getExistingDirectory(dialog, "Select backup directory.", dialog.dev_mount_path)
 | 
			
		||||
    if select_file:
 | 
			
		||||
        file_dialog_function = file_dialog.getOpenFileName
 | 
			
		||||
    else:
 | 
			
		||||
        new_path = file_dialog.getExistingDirectory(dialog, "Select backup directory.", "~")
 | 
			
		||||
        file_dialog_function = file_dialog.getExistingDirectory
 | 
			
		||||
 | 
			
		||||
    if new_path:
 | 
			
		||||
    new_appvm = None
 | 
			
		||||
    new_path = None
 | 
			
		||||
    if dialog.appvm_combobox.currentIndex() != 0:   #An existing appvm chosen
 | 
			
		||||
        new_appvm = str(dialog.appvm_combobox.currentText())
 | 
			
		||||
    elif dialog.dev_mount_path != None:
 | 
			
		||||
        new_path = file_dialog_function(dialog, "Select backup location.", dialog.dev_mount_path)
 | 
			
		||||
    else:
 | 
			
		||||
        new_path = file_dialog_function(dialog, "Select backup location.", "~")
 | 
			
		||||
 | 
			
		||||
    if new_path != None:
 | 
			
		||||
        dialog.dir_line_edit.setText(new_path)
 | 
			
		||||
        dialog.backup_dir = new_path
 | 
			
		||||
        dialog.backup_location = new_path
 | 
			
		||||
 | 
			
		||||
    if (new_path or new_appvm) and len(dialog.backup_location) > 0:
 | 
			
		||||
        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)
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,7 @@ 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
 | 
			
		||||
@ -39,18 +40,19 @@ import time
 | 
			
		||||
from operator import itemgetter
 | 
			
		||||
from thread_monitor import *
 | 
			
		||||
 | 
			
		||||
from qubes import backup
 | 
			
		||||
from qubes import qubesutils
 | 
			
		||||
 | 
			
		||||
from ui_restoredlg import *
 | 
			
		||||
from multiselectwidget import *
 | 
			
		||||
 | 
			
		||||
from backup_utils import *
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
from multiprocessing import Queue
 | 
			
		||||
from multiprocessing.queues import Empty
 | 
			
		||||
 | 
			
		||||
class RestoreVMsWindow(Ui_Restore, QWizard):
 | 
			
		||||
 | 
			
		||||
    __pyqtSignals__ = ("restore_progress(int)",)
 | 
			
		||||
    __pyqtSignals__ = ("restore_progress(int)","backup_progress(int)")
 | 
			
		||||
 | 
			
		||||
    def __init__(self, app, qvm_collection, blk_manager, parent=None):
 | 
			
		||||
        super(RestoreVMsWindow, self).__init__(parent)
 | 
			
		||||
@ -60,10 +62,11 @@ class RestoreVMsWindow(Ui_Restore, QWizard):
 | 
			
		||||
        self.blk_manager = blk_manager
 | 
			
		||||
 | 
			
		||||
        self.dev_mount_path = None
 | 
			
		||||
        self.backup_dir = None
 | 
			
		||||
        self.backup_location = None
 | 
			
		||||
        self.restore_options = None
 | 
			
		||||
        self.backup_vms_list = None
 | 
			
		||||
        self.func_output = []
 | 
			
		||||
        self.feedback_queue = Queue()
 | 
			
		||||
 | 
			
		||||
        self.excluded = {}
 | 
			
		||||
 | 
			
		||||
@ -82,14 +85,17 @@ class RestoreVMsWindow(Ui_Restore, QWizard):
 | 
			
		||||
        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.connect(self, SIGNAL("backup_progress(int)"), self.progress_bar.setValue)
 | 
			
		||||
 | 
			
		||||
        self.select_dir_page.isComplete = self.has_selected_dir
 | 
			
		||||
        self.select_vms_page.isComplete = self.has_selected_vms
 | 
			
		||||
        self.confirm_page.isComplete = self.all_vms_good
 | 
			
		||||
        #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)
 | 
			
		||||
        fill_appvms_list(self)
 | 
			
		||||
        self.__init_restore_options__()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -98,7 +104,7 @@ class RestoreVMsWindow(Ui_Restore, QWizard):
 | 
			
		||||
 | 
			
		||||
    @pyqtSlot(name='on_select_path_button_clicked')
 | 
			
		||||
    def select_path_button_clicked(self):
 | 
			
		||||
        select_path_button_clicked(self)
 | 
			
		||||
        select_path_button_clicked(self, True)
 | 
			
		||||
 | 
			
		||||
    def on_ignore_missing_toggled(self, checked):
 | 
			
		||||
        self.restore_options['use-default-template'] = checked
 | 
			
		||||
@ -118,14 +124,35 @@ class RestoreVMsWindow(Ui_Restore, QWizard):
 | 
			
		||||
        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)
 | 
			
		||||
        self.target_appvm = None
 | 
			
		||||
        if self.appvm_combobox.currentIndex() != 0:   #An existing appvm chosen
 | 
			
		||||
            self.target_appvm = self.qvm_collection.get_vm_by_name(
 | 
			
		||||
                    str(self.appvm_combobox.currentText()))
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            self.restore_tmpdir, qubes_xml = backup.backup_restore_header(
 | 
			
		||||
                    str(self.backup_location),
 | 
			
		||||
                    str(self.passphrase_line_edit.text()),
 | 
			
		||||
                    encrypted=self.encryption_checkbox.isChecked(),
 | 
			
		||||
                    appvm=self.target_appvm)
 | 
			
		||||
            self.vms_to_restore = backup.backup_restore_prepare(
 | 
			
		||||
                    str(self.backup_location),
 | 
			
		||||
                    os.path.join(self.restore_tmpdir, qubes_xml),
 | 
			
		||||
                    str(self.passphrase_line_edit.text()),
 | 
			
		||||
                    options=self.restore_options,
 | 
			
		||||
                    host_collection=self.qvm_collection,
 | 
			
		||||
                    encrypt=self.encryption_checkbox.isChecked(),
 | 
			
		||||
                    appvm=self.target_appvm)
 | 
			
		||||
 | 
			
		||||
            for vmname in self.vms_to_restore:
 | 
			
		||||
                self.select_vms_widget.available_list.addItem(vmname)
 | 
			
		||||
        except QubesException as ex:
 | 
			
		||||
            QMessageBox.warning (None, "Restore error!", str(ex))
 | 
			
		||||
 | 
			
		||||
    def __init_restore_options__(self):
 | 
			
		||||
        if not self.restore_options:
 | 
			
		||||
            self.restore_options = {}
 | 
			
		||||
            qubesutils.backup_restore_set_defaults(self.restore_options)
 | 
			
		||||
            backup.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']
 | 
			
		||||
@ -139,25 +166,36 @@ class RestoreVMsWindow(Ui_Restore, QWizard):
 | 
			
		||||
        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))
 | 
			
		||||
        
 | 
			
		||||
        self.feedback_queue.put((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))
 | 
			
		||||
        self.feedback_queue.put((SIGNAL("restore_progress(QString)"),'<font color="black">{0}</font>'.format(s)))
 | 
			
		||||
 | 
			
		||||
    def update_progress_bar(self, value):
 | 
			
		||||
        print "progress %d" % value
 | 
			
		||||
        self.feedback_queue.put((SIGNAL("backup_progress(int)"), value))
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
            backup.backup_restore_do(
 | 
			
		||||
                    str(self.backup_location),
 | 
			
		||||
                    self.restore_tmpdir,
 | 
			
		||||
                    str(self.passphrase_line_edit.text()),
 | 
			
		||||
                    self.vms_to_restore,
 | 
			
		||||
                    self.qvm_collection,
 | 
			
		||||
                    encrypted=self.encryption_checkbox.isChecked(),
 | 
			
		||||
                    appvm=self.target_appvm,
 | 
			
		||||
                    print_callback=self.restore_output,
 | 
			
		||||
                    error_callback=self.restore_error_output,
 | 
			
		||||
                    progress_callback=self.update_progress_bar)
 | 
			
		||||
        except Exception as ex:
 | 
			
		||||
            print "Exception:",ex
 | 
			
		||||
            err_msg.append(str(ex))
 | 
			
		||||
 | 
			
		||||
        self.qvm_collection.unlock_db()
 | 
			
		||||
@ -169,7 +207,6 @@ class RestoreVMsWindow(Ui_Restore, QWizard):
 | 
			
		||||
 | 
			
		||||
        thread_monitor.set_finished()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
    def current_page_changed(self, id):
 | 
			
		||||
 | 
			
		||||
        if self.currentPage() is self.select_vms_page:
 | 
			
		||||
@ -185,11 +222,13 @@ class RestoreVMsWindow(Ui_Restore, QWizard):
 | 
			
		||||
                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)
 | 
			
		||||
            backup.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))
 | 
			
		||||
 | 
			
		||||
            self.confirm_page.emit(SIGNAL("completeChanged()"))
 | 
			
		||||
 | 
			
		||||
        elif self.currentPage() is self.commit_page:
 | 
			
		||||
            self.button(self.CancelButton).setDisabled(True)
 | 
			
		||||
@ -203,23 +242,34 @@ class RestoreVMsWindow(Ui_Restore, QWizard):
 | 
			
		||||
            while not self.thread_monitor.is_finished():
 | 
			
		||||
                self.app.processEvents()
 | 
			
		||||
                time.sleep (0.1)
 | 
			
		||||
                try:
 | 
			
		||||
                    for (signal,data) in iter(self.feedback_queue.get_nowait,None):
 | 
			
		||||
                        self.emit(signal,data)
 | 
			
		||||
                except Empty:
 | 
			
		||||
                    pass
 | 
			
		||||
 | 
			
		||||
            #if not self.thread_monitor.success:
 | 
			
		||||
                #QMessageBox.warning (None, "Backup error!", "ERROR: {1}".format(self.vm.name, self.thread_monitor.error_msg))
 | 
			
		||||
 | 
			
		||||
            if self.dev_mount_path != None:
 | 
			
		||||
                umount_device(self.dev_mount_path)
 | 
			
		||||
            self.progress_bar.setValue(100)
 | 
			
		||||
            self.button(self.FinishButton).setEnabled(True)
 | 
			
		||||
 | 
			
		||||
    def all_vms_good(self):
 | 
			
		||||
        for vminfo in self.vms_to_restore.values():
 | 
			
		||||
            if not vminfo['good-to-go']:
 | 
			
		||||
                print vminfo['vm'].name, str(vminfo)
 | 
			
		||||
                return False
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def reject(self):
 | 
			
		||||
        if self.dev_mount_path != None:
 | 
			
		||||
            umount_device(self.dev_mount_path)
 | 
			
		||||
        self.done(0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def has_selected_dir(self):
 | 
			
		||||
        return self.backup_dir != None
 | 
			
		||||
        return self.backup_location != None
 | 
			
		||||
 | 
			
		||||
    def has_selected_vms(self):
 | 
			
		||||
        return self.select_vms_widget.selected_list.count() > 0
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										232
									
								
								restoredlg.ui
									
									
									
									
									
								
							
							
						
						
									
										232
									
								
								restoredlg.ui
									
									
									
									
									
								
							@ -20,83 +20,21 @@
 | 
			
		||||
   <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>
 | 
			
		||||
   <layout class="QGridLayout" name="gridLayout_3">
 | 
			
		||||
    <item row="3" column="0">
 | 
			
		||||
     <spacer name="verticalSpacer">
 | 
			
		||||
      <property name="orientation">
 | 
			
		||||
       <enum>Qt::Vertical</enum>
 | 
			
		||||
      </property>
 | 
			
		||||
      <property name="title">
 | 
			
		||||
       <string>Backup source location</string>
 | 
			
		||||
      <property name="sizeHint" stdset="0">
 | 
			
		||||
       <size>
 | 
			
		||||
        <width>20</width>
 | 
			
		||||
        <height>215</height>
 | 
			
		||||
       </size>
 | 
			
		||||
      </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>
 | 
			
		||||
     </spacer>
 | 
			
		||||
    </item>
 | 
			
		||||
    <item>
 | 
			
		||||
    <item row="1" column="0">
 | 
			
		||||
     <widget class="QGroupBox" name="options_groupbox">
 | 
			
		||||
      <property name="font">
 | 
			
		||||
       <font>
 | 
			
		||||
@ -138,18 +76,127 @@
 | 
			
		||||
      </layout>
 | 
			
		||||
     </widget>
 | 
			
		||||
    </item>
 | 
			
		||||
    <item>
 | 
			
		||||
     <spacer name="verticalSpacer">
 | 
			
		||||
      <property name="orientation">
 | 
			
		||||
       <enum>Qt::Vertical</enum>
 | 
			
		||||
    <item row="0" column="0">
 | 
			
		||||
     <widget class="QGroupBox" name="groupBox_2">
 | 
			
		||||
      <property name="font">
 | 
			
		||||
       <font>
 | 
			
		||||
        <weight>50</weight>
 | 
			
		||||
        <bold>false</bold>
 | 
			
		||||
       </font>
 | 
			
		||||
      </property>
 | 
			
		||||
      <property name="sizeHint" stdset="0">
 | 
			
		||||
       <size>
 | 
			
		||||
        <width>20</width>
 | 
			
		||||
        <height>215</height>
 | 
			
		||||
       </size>
 | 
			
		||||
      <property name="title">
 | 
			
		||||
       <string>Backup source location</string>
 | 
			
		||||
      </property>
 | 
			
		||||
     </spacer>
 | 
			
		||||
      <layout class="QGridLayout" name="gridLayout">
 | 
			
		||||
       <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="6" column="1">
 | 
			
		||||
        <widget class="QLineEdit" name="dir_line_edit"/>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="6" column="2">
 | 
			
		||||
        <widget class="QToolButton" name="select_path_button">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>...</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="6" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_2">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Backup directory:</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <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="1" column="1">
 | 
			
		||||
        <widget class="QComboBox" name="appvm_combobox"/>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="1" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_3">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>AppVM:</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
      </layout>
 | 
			
		||||
     </widget>
 | 
			
		||||
    </item>
 | 
			
		||||
    <item row="2" column="0">
 | 
			
		||||
     <widget class="QGroupBox" name="groupBox">
 | 
			
		||||
      <property name="title">
 | 
			
		||||
       <string>Security options</string>
 | 
			
		||||
      </property>
 | 
			
		||||
      <layout class="QGridLayout" name="gridLayout_4">
 | 
			
		||||
       <item row="0" column="1">
 | 
			
		||||
        <widget class="QCheckBox" name="encryption_checkbox">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string/>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="0" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_4">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Encrypted backup:</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="1" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_5">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string><html><head/><body><p>Decryption / Verification<br/>passphrase:</p></body></html></string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="1" column="1">
 | 
			
		||||
        <widget class="QLineEdit" name="passphrase_line_edit">
 | 
			
		||||
         <property name="echoMode">
 | 
			
		||||
          <enum>QLineEdit::Password</enum>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
      </layout>
 | 
			
		||||
     </widget>
 | 
			
		||||
    </item>
 | 
			
		||||
   </layout>
 | 
			
		||||
  </widget>
 | 
			
		||||
@ -189,8 +236,8 @@
 | 
			
		||||
       <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="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html></string>
 | 
			
		||||
</style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;">
 | 
			
		||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"><br /></p></body></html></string>
 | 
			
		||||
      </property>
 | 
			
		||||
     </widget>
 | 
			
		||||
    </item>
 | 
			
		||||
@ -217,6 +264,19 @@ p, li { white-space: pre-wrap; }
 | 
			
		||||
    <item>
 | 
			
		||||
     <widget class="QTextEdit" name="commit_text_edit"/>
 | 
			
		||||
    </item>
 | 
			
		||||
    <item>
 | 
			
		||||
     <widget class="QProgressBar" name="progress_bar">
 | 
			
		||||
      <property name="value">
 | 
			
		||||
       <number>0</number>
 | 
			
		||||
      </property>
 | 
			
		||||
      <property name="textVisible">
 | 
			
		||||
       <bool>false</bool>
 | 
			
		||||
      </property>
 | 
			
		||||
      <property name="format">
 | 
			
		||||
       <string/>
 | 
			
		||||
      </property>
 | 
			
		||||
     </widget>
 | 
			
		||||
    </item>
 | 
			
		||||
   </layout>
 | 
			
		||||
  </widget>
 | 
			
		||||
 </widget>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user