def __init__(self, parent=None): super().__init__() self.setupUi(self) self.setWindowTitle('Vorta for Borg Backup') self.app = parent self.setWindowIcon(get_colored_icon("icon")) self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint | QtCore.Qt.WindowMinimizeButtonHint) self.createStartBtn = LoadingButton(self.tr("Start Backup")) self.gridLayout.addWidget(self.createStartBtn, 0, 0, 1, 1) self.createStartBtn.setGif(get_asset("icons/loading")) # Use previous window state previous_window_width = SettingsModel.get(key='previous_window_width') previous_window_height = SettingsModel.get( key='previous_window_height') self.resize(int(previous_window_width.str_value), int(previous_window_height.str_value)) # Select previously used profile, if available prev_profile_id = SettingsModel.get(key='previous_profile_id') self.current_profile = BackupProfileModel.get_or_none( id=prev_profile_id.str_value) if self.current_profile is None: self.current_profile = BackupProfileModel.select().order_by( 'name').first() # Load tab models self.repoTab = RepoTab(self.repoTabSlot) self.sourceTab = SourceTab(self.sourceTabSlot) self.archiveTab = ArchiveTab(self.archiveTabSlot, app=self.app) self.scheduleTab = ScheduleTab(self.scheduleTabSlot) self.miscTab = MiscTab(self.miscTabSlot) self.miscTab.set_borg_details(borg_compat.version, borg_compat.path) self.tabWidget.setCurrentIndex(0) self.repoTab.repo_changed.connect( self.archiveTab.populate_from_profile) self.repoTab.repo_changed.connect( self.scheduleTab.populate_from_profile) self.repoTab.repo_added.connect(self.archiveTab.list_action) self.createStartBtn.clicked.connect(self.app.create_backup_action) self.cancelButton.clicked.connect(self.app.backup_cancelled_event.emit) QShortcut(QKeySequence("Ctrl+W"), self).activated.connect(self.on_close_window) QShortcut(QKeySequence("Ctrl+Q"), self).activated.connect(self.on_close_window) self.app.backup_started_event.connect(self.backup_started_event) self.app.backup_finished_event.connect(self.backup_finished_event) self.app.backup_log_event.connect(self.set_log) self.app.backup_progress_event.connect(self.set_progress) self.app.backup_cancelled_event.connect(self.backup_cancelled_event) # Init profile list self.populate_profile_selector() self.profileSelector.currentIndexChanged.connect( self.profile_select_action) self.profileRenameButton.clicked.connect(self.profile_rename_action) self.profileExportButton.clicked.connect(self.profile_export_action) self.profileDeleteButton.clicked.connect(self.profile_delete_action) profile_add_menu = QMenu() profile_add_menu.addAction(self.tr('Import from file...'), self.profile_import_action) self.profileAddButton.setMenu(profile_add_menu) self.profileAddButton.clicked.connect(self.profile_add_action) # OS-specific startup options: if not get_network_status_monitor().is_network_status_available(): # Hide Wifi-rule section in schedule tab. self.scheduleTab.wifiListLabel.hide() self.scheduleTab.wifiListWidget.hide() self.scheduleTab.page_2.hide() self.scheduleTab.toolBox.removeItem(1) # Connect to existing thread. if self.app.jobs_manager.is_worker_running(): self.createStartBtn.setEnabled(False) self.createStartBtn.start() self.cancelButton.setEnabled(True) self.set_icons()
def prepare(cls, profile): """ `borg create` is called from different places and needs some preparation. Centralize it here and return the required arguments to the caller. """ ret = super().prepare(profile) if not ret['ok']: return ret else: ret['ok'] = False # Set back to False, so we can do our own checks here. n_backup_folders = SourceFileModel.select().count() if n_backup_folders == 0: ret['message'] = trans_late('messages', 'Add some folders to back up first.') return ret network_status_monitor = get_network_status_monitor() current_wifi = network_status_monitor.get_current_wifi() if current_wifi is not None: wifi_is_disallowed = WifiSettingModel.select().where( (WifiSettingModel.ssid == current_wifi) & ( WifiSettingModel.allowed == False # noqa ) & (WifiSettingModel.profile == profile)) if wifi_is_disallowed.count() > 0 and profile.repo.is_remote_repo( ): ret['message'] = trans_late('messages', 'Current Wifi is not allowed.') return ret if profile.repo.is_remote_repo() and profile.dont_run_on_metered_networks \ and network_status_monitor.is_network_metered(): ret['message'] = trans_late( 'messages', 'Not running backup over metered connection.') return ret ret['profile'] = profile ret['repo'] = profile.repo # Run user-supplied pre-backup command if cls.pre_post_backup_cmd(ret) != 0: ret['message'] = trans_late( 'messages', 'Pre-backup command returned non-zero exit code.') return ret if not profile.repo.is_remote_repo() and not os.path.exists( profile.repo.url): ret['message'] = trans_late('messages', 'Repo folder not mounted or moved.') return ret if 'zstd' in profile.compression and not borg_compat.check('ZSTD'): ret['message'] = trans_late( 'messages', 'Your current Borg version does not support ZStd compression.') return ret cmd = [ 'borg', 'create', '--list', '--progress', '--info', '--log-json', '--json', '--filter=AM', '-C', profile.compression, ] # Add excludes # Partly inspired by borgmatic/borgmatic/borg/create.py if profile.exclude_patterns is not None: exclude_dirs = [] for p in profile.exclude_patterns.split('\n'): if p.strip(): expanded_directory = os.path.expanduser(p.strip()) exclude_dirs.append(expanded_directory) if exclude_dirs: pattern_file = tempfile.NamedTemporaryFile('w', delete=False) pattern_file.write('\n'.join(exclude_dirs)) pattern_file.flush() cmd.extend(['--exclude-from', pattern_file.name]) if profile.exclude_if_present is not None: for f in profile.exclude_if_present.split('\n'): if f.strip(): cmd.extend(['--exclude-if-present', f.strip()]) # Add repo url and source dirs. new_archive_name = format_archive_name(profile, profile.new_archive_name) cmd.append(f"{profile.repo.url}::{new_archive_name}") for f in SourceFileModel.select().where( SourceFileModel.profile == profile.id): cmd.append(f.dir) ret['message'] = trans_late('messages', 'Starting backup...') ret['ok'] = True ret['cmd'] = cmd return ret