def __init__(self, title): super(TabbedWindow, self).__init__() self.setMinimumSize(440, 540) self.create_status_bar() self.create_central_widget() self.create_menu() self.shown = False self.qnam = QNetworkAccessManager() self.http_reply = None self.in_manual_update_check = False self.faq_dialog = None self.about_dialog = None geometry = get_config_value('window_geometry') if geometry is not None: qt_geometry = QByteArray.fromBase64(geometry.encode('utf8')) self.restoreGeometry(qt_geometry) self.setWindowTitle(title) if not config_true( get_config_value('allow_multiple_instances', 'False')): self.init_named_pipe()
def delete_path(path): ''' Move directory or file in the recycle bin (or permanently delete it depending on the settings used) using the built in Windows File operations dialog ''' # Make sure we have an absolute path first if not os.path.isabs(path): path = os.path.abspath(path) shellcon = winutils.shellcon permanently_delete_files = config_true( get_config_value('permanently_delete_files', 'False')) if permanently_delete_files: flags = 0 else: flags = shellcon.FOF_ALLOWUNDO flags = (flags | shellcon.FOF_NOCONFIRMATION | shellcon.FOF_WANTNUKEWARNING) try: return winutils.delete(path, flags) except com_error: return False
def prune_auto_backups(self): max_auto_backups = max(int(get_config_value('max_auto_backups', '6')), 1) search_start = (_('auto') + '_').lower() backup_dir = os.path.join(self.game_dir, 'save_backups') if not os.path.isdir(backup_dir): return auto_backups = [] for entry in scandir(backup_dir): filename, ext = os.path.splitext(entry.name) if entry.is_file() and ext.lower() == '.zip': filename_lower = filename.lower() if filename_lower.startswith(search_start): auto_backups.append({ 'path': entry.path, 'modified': datetime.fromtimestamp(entry.stat().st_mtime) }) if len(auto_backups) >= max_auto_backups: # Remove backups to have a total of max_auto_backups - 1 auto_backups.sort(key=lambda x: x['modified']) remove_count = len(auto_backups) - max_auto_backups + 1 to_remove = auto_backups[:remove_count] for backup in to_remove: delete_path(backup['path'])
def showEvent(self, event): if not self.shown: if not config_true( get_config_value('prevent_version_check_launch', 'False')): self.in_manual_update_check = False self.check_new_launcher_version() self.shown = True
def init_single_instance(): if not config_true(get_config_value('allow_multiple_instances', 'False')): single_instance = SingleInstance() if single_instance.aleradyrunning(): write_named_pipe('cddagl_instance', b'dupe') sys.exit(0) return single_instance return None
def boe_changed(self, state): checked = state != Qt.Unchecked set_config_value('backup_on_end', str(checked)) keep_launcher_open = config_true(get_config_value('keep_launcher_open', 'False')) if not (checked and not keep_launcher_open): self.backup_on_end_warning_label.hide() else: self.backup_on_end_warning_label.show()
def klo_changed(self, state): checked = state != Qt.Unchecked set_config_value('keep_launcher_open', str(checked)) backup_on_end = (Qt.Checked if config_true( get_config_value('backup_on_end', 'False')) else Qt.Unchecked) backups_tab = self.get_main_tab().get_backups_tab() if not (backup_on_end and not checked): backups_tab.backup_on_end_warning_label.hide() else: backups_tab.backup_on_end_warning_label.show()
def get_preferred_locale(available_locales): preferred_locales = [] selected_locale = get_config_value('locale', None) if selected_locale == 'None': selected_locale = None if selected_locale is not None: preferred_locales.append(selected_locale) system_locale = get_ui_locale() if system_locale is not None: preferred_locales.append(system_locale) app_locale = Locale.negotiate(preferred_locales, available_locales) if app_locale is None: app_locale = 'en' else: app_locale = str(app_locale) return app_locale
def uld_changed(self, state): checked = state != Qt.Unchecked set_config_value('use_launcher_dir', str(checked)) main_app = QApplication.instance() central_widget = main_app.main_win.central_widget main_tab = central_widget.main_tab game_dir_group_box = main_tab.game_dir_group_box game_dir_group_box.dir_combo.setEnabled(not checked) game_dir_group_box.dir_change_button.setEnabled(not checked) game_dir_group_box.last_game_directory = None if getattr(sys, 'frozen', False) and checked: game_dir_group_box.set_dir_combo_value(get_cdda_uld_path()) else: game_directory = get_config_value('game_directory') if game_directory is None: game_directory = get_cdda_uld_path() game_dir_group_box.set_dir_combo_value(game_directory)
def lv_http_finished(self): redirect = self.http_reply.attribute( QNetworkRequest.RedirectionTargetAttribute) if redirect is not None: redirected_url = urljoin( self.http_reply.request().url().toString(), redirect.toString()) self.lv_html = BytesIO() request = QNetworkRequest(QUrl(redirected_url)) request.setRawHeader( b'User-Agent', b'CDDA-Game-Launcher/' + version.encode('utf8')) request.setRawHeader(b'Accept', cons.GITHUB_API_VERSION) self.http_reply = self.qnam.get(request) self.http_reply.finished.connect(self.lv_http_finished) self.http_reply.readyRead.connect(self.lv_http_ready_read) return status_code = self.http_reply.attribute( QNetworkRequest.HttpStatusCodeAttribute) if status_code != 200: reason = self.http_reply.attribute( QNetworkRequest.HttpReasonPhraseAttribute) url = self.http_reply.request().url().toString() logger.warning( _('Could not find launcher latest release when requesting {url}. Error: {error}' ).format(url=url, error=f'[HTTP {status_code}] ({reason})')) if self.in_manual_update_check: self.in_manual_update_check = False self.lv_html = None return self.lv_html.seek(0) try: latest_release = json.loads( TextIOWrapper(self.lv_html, encoding='utf8').read()) except json.decoder.JSONDecodeError: latest_release = {'cannot_decode': True} self.lv_html = None if 'name' not in latest_release: return if 'html_url' not in latest_release: return if 'tag_name' not in latest_release: return if 'assets' not in latest_release: return if 'body' not in latest_release: return version_text = latest_release['tag_name'] if version_text.startswith('v'): version_text = version_text[1:] latest_version = LooseVersion(version_text) if latest_version is None: return executable_url = None for file_asset in latest_release['assets']: if not 'name' in file_asset: continue if 'browser_download_url' not in file_asset: continue if file_asset['name'].endswith('.exe'): executable_url = file_asset['browser_download_url'] break if executable_url is None: return current_version = LooseVersion(version) if latest_version > current_version: markdown_desc = latest_release['body'] # Replace number signs with issue links number_pattern = ' \\#(?P<id>\\d+)' replacement_pattern = (' [#\\g<id>](' + cons.CDDAGL_ISSUE_URL_ROOT + '\\g<id>)') markdown_desc = re.sub(number_pattern, replacement_pattern, markdown_desc) html_desc = markdown.markdown(markdown_desc) release_html = (''' <h2><a href="{release_url}">{release_name}</a></h2>{description} ''').format(release_url=html.escape( latest_release['html_url']), release_name=html.escape(latest_release['name']), description=html_desc) no_launcher_version_check_checkbox = QCheckBox() no_launcher_version_check_checkbox.setText( _('Do not check ' 'for new version of the CDDA Game Launcher on launch')) check_state = (Qt.Checked if config_true( get_config_value('prevent_version_check_launch', 'False')) else Qt.Unchecked) no_launcher_version_check_checkbox.stateChanged.connect( self.nlvcc_changed) no_launcher_version_check_checkbox.setCheckState(check_state) launcher_update_msgbox = QMessageBox() launcher_update_msgbox.setWindowTitle(_('Launcher update')) launcher_update_msgbox.setText( _('You are using version ' '{version} but there is a new update for CDDA Game ' 'Launcher. Would you like to update?').format( version=version)) launcher_update_msgbox.setInformativeText(release_html) launcher_update_msgbox.addButton(_('Update the launcher'), QMessageBox.YesRole) launcher_update_msgbox.addButton(_('Not right now'), QMessageBox.NoRole) launcher_update_msgbox.setCheckBox( no_launcher_version_check_checkbox) launcher_update_msgbox.setIcon(QMessageBox.Question) if launcher_update_msgbox.exec() == 0: flags = Qt.WindowTitleHint | Qt.WindowCloseButtonHint launcher_update_dialog = (LauncherUpdateDialog( executable_url, version_text, self, flags)) launcher_update_dialog.exec() if launcher_update_dialog.updated: self.close() else: self.no_launcher_update_found()
def __init__(self): super(LauncherSettingsGroupBox, self).__init__() layout = QGridLayout() command_line_parameters_label = QLabel() layout.addWidget(command_line_parameters_label, 0, 0, Qt.AlignRight) self.command_line_parameters_label = command_line_parameters_label command_line_parameters_edit = QLineEdit() command_line_parameters_edit.setText( get_config_value('command.params', '')) command_line_parameters_edit.editingFinished.connect(self.clp_changed) layout.addWidget(command_line_parameters_edit, 0, 1) self.command_line_parameters_edit = command_line_parameters_edit keep_launcher_open_checkbox = QCheckBox() check_state = (Qt.Checked if config_true( get_config_value('keep_launcher_open', 'False')) else Qt.Unchecked) keep_launcher_open_checkbox.setCheckState(check_state) keep_launcher_open_checkbox.stateChanged.connect(self.klo_changed) layout.addWidget(keep_launcher_open_checkbox, 1, 0, 1, 2) self.keep_launcher_open_checkbox = keep_launcher_open_checkbox locale_group = QWidget() locale_group.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) locale_layout = QHBoxLayout() locale_layout.setContentsMargins(0, 0, 0, 0) locale_label = QLabel() locale_layout.addWidget(locale_label) self.locale_label = locale_label current_locale = get_config_value('locale', None) locale_combo = QComboBox() locale_combo.setSizeAdjustPolicy(QComboBox.AdjustToContents) locale_combo.addItem( _('System language or best match ({locale})').format( locale=get_ui_locale()), None) selected_index = 0 for index, locale in enumerate(get_available_locales( get_locale_path())): if locale == current_locale: selected_index = index + 1 locale = Locale.parse(locale) locale_name = locale.display_name english_name = locale.english_name if locale_name != english_name: formatted_name = f'{locale_name} - {english_name}' else: formatted_name = locale_name locale_combo.addItem(formatted_name, str(locale)) locale_combo.setCurrentIndex(selected_index) locale_combo.currentIndexChanged.connect(self.locale_combo_changed) locale_layout.addWidget(locale_combo) self.locale_combo = locale_combo locale_group.setLayout(locale_layout) layout.addWidget(locale_group, 2, 0, 1, 2) self.locale_group = locale_group self.locale_layout = locale_layout allow_mul_insts_checkbox = QCheckBox() check_state = (Qt.Checked if config_true( get_config_value('allow_multiple_instances', 'False')) else Qt.Unchecked) allow_mul_insts_checkbox.setCheckState(check_state) allow_mul_insts_checkbox.stateChanged.connect(self.ami_changed) layout.addWidget(allow_mul_insts_checkbox, 3, 0, 1, 2) self.allow_mul_insts_checkbox = allow_mul_insts_checkbox no_launcher_version_check_checkbox = QCheckBox() check_state = (Qt.Checked if config_true( get_config_value('prevent_version_check_launch', 'False')) else Qt.Unchecked) no_launcher_version_check_checkbox.setCheckState(check_state) no_launcher_version_check_checkbox.stateChanged.connect( self.nlvcc_changed) layout.addWidget(no_launcher_version_check_checkbox, 4, 0, 1, 2) self.no_launcher_version_check_checkbox = ( no_launcher_version_check_checkbox) self.setLayout(layout) self.set_text()
def __init__(self): super(UpdateSettingsGroupBox, self).__init__() layout = QGridLayout() prevent_save_move_checkbox = QCheckBox() check_state = (Qt.Checked if config_true( get_config_value('prevent_save_move', 'False')) else Qt.Unchecked) prevent_save_move_checkbox.setCheckState(check_state) prevent_save_move_checkbox.stateChanged.connect(self.psmc_changed) layout.addWidget(prevent_save_move_checkbox, 0, 0, 1, 3) self.prevent_save_move_checkbox = prevent_save_move_checkbox keep_archive_copy_checkbox = QCheckBox() check_state = (Qt.Checked if config_true( get_config_value('keep_archive_copy', 'False')) else Qt.Unchecked) keep_archive_copy_checkbox.setCheckState(check_state) keep_archive_copy_checkbox.stateChanged.connect(self.kacc_changed) layout.addWidget(keep_archive_copy_checkbox, 1, 0) self.keep_archive_copy_checkbox = keep_archive_copy_checkbox keep_archive_directory_line = QLineEdit() keep_archive_directory_line.setText( get_config_value('archive_directory', '')) keep_archive_directory_line.editingFinished.connect( self.ka_directory_changed) layout.addWidget(keep_archive_directory_line, 1, 1) self.keep_archive_directory_line = keep_archive_directory_line ka_dir_change_button = QToolButton() ka_dir_change_button.setText('...') ka_dir_change_button.clicked.connect(self.set_ka_directory) layout.addWidget(ka_dir_change_button, 1, 2) self.ka_dir_change_button = ka_dir_change_button arb_timer = QTimer() arb_timer.setInterval( int(get_config_value('auto_refresh_builds_minutes', '30')) * 1000 * 60) arb_timer.timeout.connect(self.arb_timeout) self.arb_timer = arb_timer if config_true(get_config_value('auto_refresh_builds', 'False')): arb_timer.start() arb_group = QWidget() arb_group.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) arb_layout = QHBoxLayout() arb_layout.setContentsMargins(0, 0, 0, 0) auto_refresh_builds_checkbox = QCheckBox() check_state = (Qt.Checked if config_true( get_config_value('auto_refresh_builds', 'False')) else Qt.Unchecked) auto_refresh_builds_checkbox.setCheckState(check_state) auto_refresh_builds_checkbox.stateChanged.connect(self.arbc_changed) arb_layout.addWidget(auto_refresh_builds_checkbox) self.auto_refresh_builds_checkbox = auto_refresh_builds_checkbox arb_min_spinbox = QSpinBox() arb_min_spinbox.setMinimum(5) arb_min_spinbox.setValue( int(get_config_value('auto_refresh_builds_minutes', '30'))) arb_min_spinbox.valueChanged.connect(self.ams_changed) arb_layout.addWidget(arb_min_spinbox) self.arb_min_spinbox = arb_min_spinbox arb_min_label = QLabel() arb_layout.addWidget(arb_min_label) self.arb_min_label = arb_min_label arb_group.setLayout(arb_layout) layout.addWidget(arb_group, 2, 0, 1, 3) self.arb_group = arb_group self.arb_layout = arb_layout remove_previous_version_checkbox = QCheckBox() check_state = (Qt.Checked if config_true( get_config_value('remove_previous_version', 'False')) else Qt.Unchecked) remove_previous_version_checkbox.setCheckState(check_state) remove_previous_version_checkbox.stateChanged.connect( self.rpvc_changed) layout.addWidget(remove_previous_version_checkbox, 3, 0, 1, 3) self.remove_previous_version_checkbox = ( remove_previous_version_checkbox) permanently_delete_files_checkbox = QCheckBox() check_state = (Qt.Checked if config_true( get_config_value('permanently_delete_files', 'False')) else Qt.Unchecked) permanently_delete_files_checkbox.setCheckState(check_state) permanently_delete_files_checkbox.stateChanged.connect( self.prfc_changed) layout.addWidget(permanently_delete_files_checkbox, 4, 0, 1, 3) self.permanently_delete_files_checkbox = ( permanently_delete_files_checkbox) self.setLayout(layout) self.set_text()
def __init__(self): super(BackupsTab, self).__init__() self.game_dir = None self.update_backups_timer = None self.after_backup = None self.after_update_backups = None self.extracting_backup = False self.manual_backup = False self.backup_searching = False self.backup_compressing = False self.compressing_timer = None current_backups_gb = QGroupBox() self.current_backups_gb = current_backups_gb current_backups_gb_layout = QGridLayout() current_backups_gb.setLayout(current_backups_gb_layout) self.current_backups_gb_layout = current_backups_gb_layout backups_table = QTableWidget() backups_table.setColumnCount(8) backups_table.setSelectionBehavior(QAbstractItemView.SelectRows) backups_table.setSelectionMode(QAbstractItemView.SingleSelection) backups_table.verticalHeader().setVisible(False) backups_table.horizontalHeader().sortIndicatorChanged.connect( self.backups_table_header_sort) backups_table.itemSelectionChanged.connect( self.backups_table_selection_changed) current_backups_gb_layout.addWidget(backups_table, 0, 0, 1, 3) self.backups_table = backups_table columns_width = get_config_value('backups_columns_width', None) if columns_width is not None: columns_width = json.loads(columns_width) for index, value in enumerate(columns_width): if index < self.backups_table.columnCount(): self.backups_table.setColumnWidth(index, value) restore_button = QPushButton() restore_button.clicked.connect(self.restore_button_clicked) restore_button.setEnabled(False) current_backups_gb_layout.addWidget(restore_button, 1, 0) self.restore_button = restore_button refresh_list_button = QPushButton() refresh_list_button.setEnabled(False) refresh_list_button.clicked.connect(self.refresh_list_button_clicked) current_backups_gb_layout.addWidget(refresh_list_button, 1, 1) self.refresh_list_button = refresh_list_button delete_button = QPushButton() delete_button.clicked.connect(self.delete_button_clicked) delete_button.setEnabled(False) current_backups_gb_layout.addWidget(delete_button, 1, 2) self.delete_button = delete_button do_not_backup_previous_cb = QCheckBox() check_state = (Qt.Checked if config_true(get_config_value( 'do_not_backup_previous', 'False')) else Qt.Unchecked) do_not_backup_previous_cb.setCheckState(check_state) do_not_backup_previous_cb.stateChanged.connect(self.dnbp_changed) current_backups_gb_layout.addWidget(do_not_backup_previous_cb, 2, 0, 1, 3) self.do_not_backup_previous_cb = do_not_backup_previous_cb manual_backups_gb = QGroupBox() self.manual_backups_gb = manual_backups_gb manual_backups_layout = QGridLayout() manual_backups_gb.setLayout(manual_backups_layout) self.manual_backups_layout = manual_backups_layout name_label = QLabel() manual_backups_layout.addWidget(name_label, 0, 0, Qt.AlignRight) self.name_label = name_label name_le = QLineEdit() name_le.setText(get_config_value('last_manual_backup_name', '')) manual_backups_layout.addWidget(name_le, 0, 1) self.name_le = name_le backup_current_button = QPushButton() backup_current_button.setEnabled(False) backup_current_button.clicked.connect(self.backup_current_clicked) manual_backups_layout.addWidget(backup_current_button, 1, 0, 1, 2) self.backup_current_button = backup_current_button automatic_backups_gb = QGroupBox() automatic_backups_layout = QGridLayout() automatic_backups_gb.setLayout(automatic_backups_layout) self.automatic_backups_layout = automatic_backups_layout self.automatic_backups_gb = automatic_backups_gb backup_on_launch_cb = QCheckBox() check_state = (Qt.Checked if config_true(get_config_value( 'backup_on_launch', 'False')) else Qt.Unchecked) backup_on_launch_cb.setCheckState(check_state) backup_on_launch_cb.stateChanged.connect(self.bol_changed) automatic_backups_layout.addWidget(backup_on_launch_cb, 0, 0) self.backup_on_launch_cb = backup_on_launch_cb backup_on_end_cb = QCheckBox() check_state = (Qt.Checked if config_true(get_config_value( 'backup_on_end', 'False')) else Qt.Unchecked) backup_on_end_cb.setCheckState(check_state) backup_on_end_cb.stateChanged.connect(self.boe_changed) automatic_backups_layout.addWidget(backup_on_end_cb, 1, 0) self.backup_on_end_cb = backup_on_end_cb backup_on_end = check_state keep_launcher_open = config_true(get_config_value('keep_launcher_open', 'False')) backup_on_end_warning_label = QLabel() icon = QApplication.style().standardIcon(QStyle.SP_MessageBoxWarning) backup_on_end_warning_label.setPixmap(icon.pixmap(16, 16)) if not (backup_on_end and not keep_launcher_open): backup_on_end_warning_label.hide() automatic_backups_layout.addWidget(backup_on_end_warning_label, 1, 1) self.backup_on_end_warning_label = backup_on_end_warning_label backup_before_update_cb = QCheckBox() check_state = (Qt.Checked if config_true(get_config_value( 'backup_before_update', 'False')) else Qt.Unchecked) backup_before_update_cb.setCheckState(check_state) backup_before_update_cb.stateChanged.connect(self.bbu_changed) automatic_backups_layout.addWidget(backup_before_update_cb, 2, 0) self.backup_before_update_cb = backup_before_update_cb mab_group = QWidget() mab_group.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) mab_layout = QHBoxLayout() mab_layout.setContentsMargins(0, 0, 0, 0) max_auto_backups_label = QLabel() mab_layout.addWidget(max_auto_backups_label) self.max_auto_backups_label = max_auto_backups_label max_auto_backups_spinbox = QSpinBox() max_auto_backups_spinbox.setMinimum(1) max_auto_backups_spinbox.setMaximum(1000) max_auto_backups_spinbox.setValue(int(get_config_value( 'max_auto_backups', '6'))) max_auto_backups_spinbox.valueChanged.connect(self.mabs_changed) mab_layout.addWidget(max_auto_backups_spinbox) self.max_auto_backups_spinbox = max_auto_backups_spinbox mab_group.setLayout(mab_layout) automatic_backups_layout.addWidget(mab_group, 3, 0, 1, 2) self.mab_group = mab_group self.mab_layout = mab_layout layout = QGridLayout() layout.addWidget(current_backups_gb, 0, 0, 1, 2) layout.addWidget(manual_backups_gb, 1, 0) layout.addWidget(automatic_backups_gb, 1, 1) self.setLayout(layout) self.set_text()
def restore_button_clicked(self): class WaitingThread(QThread): completed = pyqtSignal() def __init__(self, wthread): super(WaitingThread, self).__init__() self.wthread = wthread def __del__(self): self.wait() def run(self): self.wthread.wait() self.completed.emit() if self.backup_searching: if (self.compressing_timer is not None and self.compressing_timer.isActive()): self.compressing_timer.stop() self.backup_searching = False self.finish_backup_saves() main_window = self.get_main_window() status_bar = main_window.statusBar() status_bar.showMessage(_('Restore backup cancelled')) self.restore_button.setText(_('Restore backup')) elif self.backup_compressing: if self.compress_thread is not None: self.backup_current_button.setEnabled(False) self.compress_thread.quit() def completed(): self.finish_backup_saves() delete_path(self.backup_path) self.compress_thread = None waiting_thread = WaitingThread(self.compress_thread) waiting_thread.completed.connect(completed) self.waiting_thread = waiting_thread waiting_thread.start() else: self.finish_backup_saves() delete_path(self.backup_path) self.compress_thread = None self.backup_compressing = False main_window = self.get_main_window() status_bar = main_window.statusBar() status_bar.showMessage(_('Restore backup cancelled')) self.restore_button.setText(_('Restore backup')) elif self.extracting_backup: if self.extracting_thread is not None: self.restore_button.setEnabled(False) self.extracting_thread.quit() def completed(): save_dir = os.path.join(self.game_dir, 'save') delete_path(save_dir) if self.temp_save_dir is not None: retry_rename(self.temp_save_dir, save_dir) self.temp_save_dir = None self.finish_restore_backup() self.extracting_thread = None waiting_thread = WaitingThread(self.extracting_thread) waiting_thread.completed.connect(completed) self.waiting_thread = waiting_thread waiting_thread.start() else: self.finish_restore_backup() self.extracting_thread = None self.extracting_backup = False main_window = self.get_main_window() status_bar = main_window.statusBar() status_bar.showMessage(_('Restore backup cancelled')) else: selection_model = self.backups_table.selectionModel() if selection_model is None or not selection_model.hasSelection(): return selected = selection_model.currentIndex() table_item = self.backups_table.item(selected.row(), 0) selected_info = self.backups[table_item] if not os.path.isfile(selected_info['path']): return backup_previous = not config_true(get_config_value( 'do_not_backup_previous', 'False')) if backup_previous: ''' If restoring the before_last_restore, we rename it to make sure we make a proper backup first. ''' model = selection_model.model() backup_name = model.data(model.index(selected.row(), 0)) before_last_restore_name = _('before_last_restore') if backup_name.lower() == before_last_restore_name.lower(): backup_dir = os.path.join(self.game_dir, 'save_backups') name_lower = backup_name.lower() name_key = alphanum_key(name_lower) max_counter = 1 for entry in scandir(backup_dir): filename, ext = os.path.splitext(entry.name) if ext.lower() == '.zip': filename_lower = filename.lower() filename_key = alphanum_key(filename_lower) counter = filename_key[-1:][0] if len(filename_key) > 1 and isinstance(counter, int): filename_key = filename_key[:-1] if name_key == filename_key: max_counter = max(max_counter, counter) new_backup_name = (before_last_restore_name + str(max_counter + 1)) new_backup_path = os.path.join(backup_dir, new_backup_name + '.zip') if not retry_rename(selected_info['path'], new_backup_path): return selected_info['path'] = new_backup_path def next_step(): self.restore_backup() self.after_backup = next_step self.backup_saves(before_last_restore_name, True) self.restore_button.setEnabled(True) self.restore_button.setText(_('Cancel restore backup')) else: self.restore_backup()