def backup_next_file(): try: if self.backup_compressing: next_file = self.backup_files.popleft() relpath = os.path.relpath(next_file, self.game_dir) self.next_backup_file = next_file self.compressing_label.setText( _('Compressing {filename}').format(filename=relpath)) compress_thread = CompressThread(self.backup_file, next_file, relpath) compress_thread.completed.connect(completed_compress) self.compress_thread = compress_thread compress_thread.start() except IndexError: self.backup_compressing = False self.compress_thread = None self.finish_backup_saves() main_window = self.get_main_window() status_bar = main_window.statusBar() if self.after_backup is not None: self.after_update_backups = self.after_backup self.after_backup = None else: status_bar.showMessage(_('Saves backup completed')) self.update_backups_table()
def extract_next_file(): try: if self.extracting_backup: extracting_element = self.extracting_infolist.popleft() self.extracting_label.setText(_('Extracting {filename}' ).format(filename=extracting_element.filename)) self.next_extract_file = extracting_element extracting_thread = ExtractingThread( self.extracting_zipfile, extracting_element, self.extract_dir) extracting_thread.completed.connect(completed_extract) self.extracting_thread = extracting_thread extracting_thread.start() except IndexError: self.extracting_backup = False self.extracting_thread = None self.finish_restore_backup() main_window = self.get_main_window() status_bar = main_window.statusBar() status_bar.showMessage(_('{backup_name} backup restored' ).format(backup_name=backup_name))
def move_new_soundpack(self): # Find the soundpack in the self.extract_dir # Move the soundpack from that location into self.soundpacks_dir self.moving_new_soundpack = True main_window = self.get_main_window() status_bar = main_window.statusBar() status_bar.showMessage(_('Finding the soundpack')) next_scans = deque() current_scan = scandir(self.extract_dir) soundpack_dir = None while True: try: entry = next(current_scan) if entry.is_dir(): next_scans.append(entry.path) elif entry.is_file(): dirname, basename = os.path.split(entry.path) if basename == 'soundpack.txt': soundpack_dir = dirname entry = None break except StopIteration: if len(next_scans) > 0: current_scan = scandir(next_scans.popleft()) else: break for item in current_scan: pass if soundpack_dir is None: status_bar.showMessage(_('Soundpack installation cancelled - There ' 'is no soundpack in the downloaded archive')) delete_path(self.extract_dir) self.moving_new_soundpack = False self.finish_install_new_soundpack() else: soundpack_dir_name = os.path.basename(soundpack_dir) target_dir = os.path.join(self.soundpacks_dir, soundpack_dir_name) if os.path.exists(target_dir): status_bar.showMessage(_('Soundpack installation cancelled - ' 'There is already a {basename} directory in ' '{soundpacks_dir}').format(basename=soundpack_dir_name, soundpacks_dir=self.soundpacks_dir)) else: shutil.move(soundpack_dir, self.soundpacks_dir) status_bar.showMessage(_('Soundpack installation completed')) delete_path(self.extract_dir) self.moving_new_soundpack = False self.game_dir_changed(self.game_dir) self.finish_install_new_soundpack()
def create_menu(self): file_menu = QMenu(_('&File')) self.menuBar().addMenu(file_menu) self.file_menu = file_menu exit_action = QAction(_('E&xit'), self, triggered=self.close) file_menu.addAction(exit_action) self.exit_action = exit_action help_menu = QMenu(_('&Help')) self.menuBar().addMenu(help_menu) self.help_menu = help_menu if getattr(sys, 'frozen', False): update_action = QAction(_('&Check for update'), self, triggered=self.manual_update_check) self.update_action = update_action self.help_menu.addAction(update_action) self.help_menu.addSeparator() about_action = QAction(_('&About CDDA Game Launcher'), self, triggered=self.show_about_dialog) self.about_action = about_action self.help_menu.addAction(about_action)
def installed_clicked(self): selection_model = self.installed_lv.selectionModel() if selection_model is not None and selection_model.hasSelection(): selected = selection_model.currentIndex() selected_info = self.soundpacks[selected.row()] self.viewname_le.setText(selected_info['VIEW']) self.name_le.setText(selected_info['NAME']) self.path_label.setText(_('Path:')) self.path_le.setText(selected_info['path']) self.size_le.setText(sizeof_fmt(selected_info['size'])) self.homepage_tb.setText('') if selected_info['enabled']: self.disable_existing_button.setText(_('Disable')) else: self.disable_existing_button.setText(_('Enable')) if not self.tab_disabled: self.disable_existing_button.setEnabled(True) self.delete_existing_button.setEnabled(True) self.install_new_button.setEnabled(False) repository_selection = self.repository_lv.selectionModel() if repository_selection is not None: repository_selection.clearSelection()
def set_download_path(self): options = QFileDialog.DontResolveSymlinks selected_file, selected_filter = QFileDialog.getOpenFileName(self, _('Downloaded archive'), self.download_path_le.text(), _('Archive files {formats}').format(formats='(*.zip *.rar *.7z)'), options=options) if selected_file: self.download_path_le.setText(clean_qt_path(selected_file))
def repository_clicked(self): selection_model = self.repository_lv.selectionModel() if selection_model is not None and selection_model.hasSelection(): selected = selection_model.currentIndex() selected_info = self.repo_soundpacks[selected.row()] self.viewname_le.setText(selected_info['viewname']) self.name_le.setText(selected_info['name']) if selected_info['type'] == 'direct_download': self.path_label.setText(_('Url:')) self.path_le.setText(selected_info['url']) self.homepage_tb.setText('<a href="{url}">{url}</a>'.format( url=html.escape(selected_info['homepage']))) if 'size' not in selected_info: if not (self.current_repo_info is not None and self.http_reply is not None and self.http_reply.isRunning() and self.current_repo_info is selected_info): if (self.http_reply is not None and self.http_reply.isRunning()): self.http_reply_aborted = True self.http_reply.abort() self.http_reply_aborted = False self.size_le.setText(_('Getting remote size')) self.current_repo_info = selected_info request = QNetworkRequest(QUrl(selected_info['url'])) request.setRawHeader(b'User-Agent', cons.FAKE_USER_AGENT) self.http_reply = self.qnam.head(request) self.http_reply.finished.connect( self.size_query_finished) else: self.size_le.setText(sizeof_fmt(selected_info['size'])) elif selected_info['type'] == 'browser_download': self.path_label.setText(_('Url:')) self.path_le.setText(selected_info['url']) self.homepage_tb.setText('<a href="{url}">{url}</a>'.format( url=html.escape(selected_info['homepage']))) if 'size' in selected_info: self.size_le.setText(sizeof_fmt(selected_info['size'])) else: self.size_le.setText(_('Unknown')) if (self.soundpacks_dir is not None and os.path.isdir(self.soundpacks_dir) and not self.tab_disabled): self.install_new_button.setEnabled(True) self.disable_existing_button.setEnabled(False) self.delete_existing_button.setEnabled(False) installed_selection = self.installed_lv.selectionModel() if installed_selection is not None: installed_selection.clearSelection()
def set_text(self): self.file_menu.setTitle(_('&File')) self.exit_action.setText(_('E&xit')) self.help_menu.setTitle(_('&Help')) if getattr(sys, 'frozen', False): self.update_action.setText(_('&Check for update')) self.about_action.setText(_('&About CDDA Game Launcher')) if self.about_dialog is not None: self.about_dialog.set_text() self.central_widget.set_text()
def no_launcher_update_found(self): if self.in_manual_update_check: up_to_date_msgbox = QMessageBox() up_to_date_msgbox.setWindowTitle(_('Up to date')) up_to_date_msgbox.setText( _('The CDDA Game Launcher is up to date.')) up_to_date_msgbox.setIcon(QMessageBox.Information) up_to_date_msgbox.exec() self.in_manual_update_check = False
def set_text(self): self.setWindowTitle(_('About CDDA Game Launcher')) self.ok_button.setText(_('OK')) m = _('<p>CDDA Game Launcher version {version}</p>').format(version=version) m += _('<p>Get the latest release' ' <a href="https://github.com/remyroy/CDDA-Game-Launcher/releases">on GitHub</a>.' '</p>') m += _('<p>Please report any issue' ' <a href="https://github.com/remyroy/CDDA-Game-Launcher/issues/new">on GitHub</a>.' '</p>') bitcoin_text = r'3N2BRM61bZLuFRHjSj2Lhtw6DrwPUGeTvV' bitcoin_link = r'bitcoin:3N2BRM61bZLuFRHjSj2Lhtw6DrwPUGeTvV' ether_link = r'https://etherscan.io/address/0xdb731476e913d75061a78105c3d1b5a7a03aa21b' ether_text = r'0xdb731476e913d75061a78105c3d1b5a7a03aa21b' m += _('<p>If you like the CDDA Game Launcher, you can buy me a beer by:</p>' '<p>donating bitcoins to <a href="{bitcoin_link}">{bitcoin_text}</a></p>' '<p><img src="btc-qr.png" /></p>' '<p>or by donating ethers to <a href="{ether_link}">{ether_text}</a></p>' '<p><img src="eth-qr.png" /></p>').format(bitcoin_text=bitcoin_text, bitcoin_link=bitcoin_link, ether_link=ether_link, ether_text=ether_text) m += _('<p>Thanks to the following people for their efforts in' ' translating the CDDA Game Launcher</p>' '<ul>' '<li>Russian: Daniel from <a href="http://cataclysmdda.ru/">cataclysmdda.ru</a>' ' and Night_Pryanik' '</li>' '<li>Italian: Rettiliano Verace from' ' <a href="http://emigrantebestemmiante.blogspot.com">Emigrante Bestemmiante</a>' '</li>' '<li>French: Rémy Roy</li>' '<li>Spanish: KurzedMetal</li>' '</ul>') m += _('<p>Thanks to <a href="http://mattahan.deviantart.com/">Paul Davey aka Mattahan</a>' ' for the permission to use his artwork for the launcher icon.</p>') m += _('<p>This software is distributed under the MIT License. That means this is' ' 100% free software, completely free to use, modify and/or distribute.' ' If you like more details check the following boring legal stuff...</p>') m += '<p>Copyright (c) 2015-2020 Rémy Roy</p>' m += ('<p>Permission is hereby granted, free of charge, to any person obtaining a copy' ' of this software and associated documentation files (the "Software"), to deal' ' in the Software without restriction, including without limitation the rights' ' to use, copy, modify, merge, publish, distribute, sublicense, and/or sell' ' copies of the Software, and to permit persons to whom the Software is' ' furnished to do so, subject to the following conditions:</p>' '<p>The above copyright notice and this permission notice shall be included in' ' all copies or substantial portions of the Software.</p>' '<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR' ' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,' ' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE' ' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER' ' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,' ' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE' ' SOFTWARE.</p>') self.text_content.setHtml(m)
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 finish_backup_saves(self): if self.backup_file is not None: self.backup_file.close() main_window = self.get_main_window() status_bar = main_window.statusBar() status_bar.removeWidget(self.compressing_label) if self.compressing_progress_bar is not None: status_bar.removeWidget(self.compressing_progress_bar) if self.compressing_speed_label is not None: status_bar.removeWidget(self.compressing_speed_label) if self.compressing_size_label is not None: status_bar.removeWidget(self.compressing_size_label) status_bar.busy -= 1 self.enable_tab() self.get_main_tab().enable_tab() self.get_soundpacks_tab().enable_tab() self.get_settings_tab().enable_tab() self.get_mods_tab().enable_tab() self.get_backups_tab().enable_tab() if self.manual_backup: self.manual_backup = False self.backup_current_button.setText(_('Backup current saves'))
def finish_restore_backup(self): main_window = self.get_main_window() status_bar = main_window.statusBar() status_bar.removeWidget(self.extracting_label) status_bar.removeWidget(self.extracting_speed_label) status_bar.removeWidget(self.extracting_size_label) status_bar.removeWidget(self.extracting_progress_bar) status_bar.busy -= 1 self.extracting_backup = False if self.extracting_zipfile is not None: self.extracting_zipfile.close() if self.temp_save_dir is not None: delete_path(self.temp_save_dir) self.enable_tab() self.get_main_tab().enable_tab() self.get_soundpacks_tab().enable_tab() self.get_settings_tab().enable_tab() self.get_mods_tab().enable_tab() self.get_backups_tab().enable_tab() self.restore_button.setText(_('Restore backup')) self.get_main_tab().game_dir_group_box.update_saves()
def set_text(self): self.setTabText(self.indexOf(self.main_tab), _('Main')) self.setTabText(self.indexOf(self.backups_tab), _('Backups')) self.setTabText(self.indexOf(self.mods_tab), _('Mods')) #self.setTabText(self.indexOf(self.tilesets_tab), _('Tilesets')) self.setTabText(self.indexOf(self.soundpacks_tab), _('Soundpacks')) #self.setTabText(self.indexOf(self.fonts_tab), _('Fonts')) self.setTabText(self.indexOf(self.settings_tab), _('Settings')) self.main_tab.set_text() self.backups_tab.set_text() self.mods_tab.set_text() #self.tilesets_tab.set_text() self.soundpacks_tab.set_text() #self.fonts_tab.set_text() self.settings_tab.set_text()
def init_logging(): logger = logging.getLogger('cddagl') logger.setLevel(logging.INFO) local_app_data = os.environ.get('LOCALAPPDATA', os.environ.get('APPDATA')) if local_app_data is None or not os.path.isdir(local_app_data): local_app_data = '' logging_dir = os.path.join(local_app_data, 'CDDA Game Launcher') if not os.path.isdir(logging_dir): os.makedirs(logging_dir) logging_file = os.path.join(logging_dir, 'app.log') handler = RotatingFileHandler(logging_file, encoding='utf8', maxBytes=cons.MAX_LOG_SIZE, backupCount=cons.MAX_LOG_FILES) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) handler = logging.StreamHandler() logger.addHandler(handler) logger.info( _('CDDA Game Launcher started: {version}').format(version=version))
def add_soundpack(self, soundpack_info): index = self.soundpacks_model.rowCount() self.soundpacks_model.insertRows(self.soundpacks_model.rowCount(), 1) disabled_text = '' if not soundpack_info['enabled']: disabled_text = _(' (Disabled)') self.soundpacks_model.setData(self.soundpacks_model.index(index), soundpack_info['VIEW'] + disabled_text)
def set_ka_directory(self): options = QFileDialog.DontResolveSymlinks | QFileDialog.ShowDirsOnly directory = QFileDialog.getExistingDirectory(self, _('Archive directory'), self.keep_archive_directory_line.text(), options=options) if directory: self.keep_archive_directory_line.setText(clean_qt_path(directory)) self.ka_directory_changed()
def delete_existing(self): selection_model = self.installed_lv.selectionModel() if selection_model is None or not selection_model.hasSelection(): return selected = selection_model.currentIndex() selected_info = self.soundpacks[selected.row()] confirm_msgbox = QMessageBox() confirm_msgbox.setWindowTitle(_('Delete soundpack')) confirm_msgbox.setText(_('This will delete the soundpack directory. It ' 'cannot be undone.')) confirm_msgbox.setInformativeText(_('Are you sure you want to ' 'delete the {view} soundpack?').format(view=selected_info['VIEW'])) confirm_msgbox.addButton(_('Delete the soundpack'), QMessageBox.YesRole) confirm_msgbox.addButton(_('I want to keep the soundpack'), QMessageBox.NoRole) confirm_msgbox.setIcon(QMessageBox.Warning) if confirm_msgbox.exec() == 0: main_window = self.get_main_window() status_bar = main_window.statusBar() if not delete_path(selected_info['path']): status_bar.showMessage(_('Soundpack deletion cancelled')) else: self.soundpacks_model.removeRows(selected.row(), 1) self.soundpacks.remove(selected_info) status_bar.showMessage(_('Soundpack deleted'))
def log_exception(extype, value, tb): tb_io = StringIO() traceback.print_tb(tb, file=tb_io) logger.critical( _('Global error:\nLauncher version: {version}\nType: ' '{extype}\nValue: {value}\nTraceback:\n{traceback}').format( version=cddagl.__version__, extype=str(extype), value=str(value), traceback=tb_io.getvalue()))
def sizeof_fmt(num, suffix=None): if suffix is None: suffix = _('B') for unit in [ '', _('Ki'), _('Mi'), _('Gi'), _('Ti'), _('Pi'), _('Ei'), _('Zi') ]: if abs(num) < 1024.0: return "%3.1f %s%s" % (num, unit, suffix) num /= 1024.0 return "%.1f %s%s" % (num, _('Yi'), suffix)
def install_clicked(self): choosen_file = self.download_path_le.text() if not os.path.isfile(choosen_file): filenotfound_msgbox = QMessageBox() filenotfound_msgbox.setWindowTitle(_('File not found')) text = (_( '{filepath} is not an existing file on your system. ' 'Make sure to download the archive with your browser. Make ' 'sure to select the downloaded archive afterwards.')).format( filepath=choosen_file) filenotfound_msgbox.setText(text) filenotfound_msgbox.addButton(_('I will try again'), QMessageBox.AcceptRole) filenotfound_msgbox.setIcon(QMessageBox.Warning) filenotfound_msgbox.exec() return self.downloaded_path = choosen_file self.done(1)
def set_text(self): self.file_menu.setTitle(_('&File')) self.exit_action.setText(_('E&xit')) self.help_menu.setTitle(_('&Help')) self.faq_action.setText(_('&Frequently asked questions (FAQ)')) self.game_issue_action.setText(_('&Game issue')) self.update_action.setText(_('&Check for update')) self.about_action.setText(_('&About CDDA Game Launcher')) if self.about_dialog is not None: self.about_dialog.set_text() self.central_widget.set_text()
def disable_existing(self): selection_model = self.installed_lv.selectionModel() if selection_model is None or not selection_model.hasSelection(): return selected = selection_model.currentIndex() selected_info = self.soundpacks[selected.row()] if selected_info['enabled']: config_file = os.path.join(selected_info['path'], 'soundpack.txt') new_config_file = os.path.join(selected_info['path'], 'soundpack.txt.disabled') try: shutil.move(config_file, new_config_file) selected_info['enabled'] = False self.soundpacks_model.setData(selected, selected_info['VIEW'] + _(' (Disabled)')) self.disable_existing_button.setText(_('Enable')) except OSError as e: main_window = self.get_main_window() status_bar = main_window.statusBar() status_bar.showMessage(str(e)) else: config_file = os.path.join(selected_info['path'], 'soundpack.txt.disabled') new_config_file = os.path.join(selected_info['path'], 'soundpack.txt') try: shutil.move(config_file, new_config_file) selected_info['enabled'] = True self.soundpacks_model.setData(selected, selected_info['VIEW']) self.disable_existing_button.setText(_('Disable')) except OSError as e: main_window = self.get_main_window() status_bar = main_window.statusBar() status_bar.showMessage(str(e))
def init_logging(): logger = logging.getLogger('cddagl') logger.setLevel(logging.INFO) local_app_data = os.environ.get('LOCALAPPDATA', os.environ.get('APPDATA')) if local_app_data is None or not os.path.isdir(local_app_data): local_app_data = '' logging_dir = os.path.join(local_app_data, 'CDDA Game Launcher') if not os.path.isdir(logging_dir): os.makedirs(logging_dir) logging_file = os.path.join(logging_dir, 'app.log') handler = RotatingFileHandler(logging_file, encoding='utf8', maxBytes=cons.MAX_LOG_SIZE, backupCount=cons.MAX_LOG_FILES) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) if not getattr(sys, 'frozen', False): handler = logging.StreamHandler() logger.addHandler(handler) else: '''class LoggerWriter: def __init__(self, logger, level, imp=None): self.logger = logger self.level = level self.imp = imp def __getattr__(self, attr): return getattr(self.imp, attr) def write(self, message): if message != '\n': self.logger.log(self.level, message) sys._stdout = sys.stdout sys._stderr = sys.stderr sys.stdout = LoggerWriter(logger, logging.INFO, sys._stdout) sys.stderr = LoggerWriter(logger, logging.ERROR, sys._stderr)''' logger.info( _('CDDA Game Launcher started: {version}').format(version=version))
def timeout(): self.extracting_progress_bar.setValue(self.extracting_index) if self.extracting_index == len(self.extracting_infolist): self.extracting_timer.stop() main_window = self.get_main_window() status_bar = main_window.statusBar() status_bar.removeWidget(self.extracting_label) status_bar.removeWidget(self.extracting_progress_bar) status_bar.busy -= 1 self.extracting_new_soundpack = False self.extracting_zipfile.close() self.extracting_zipfile = None if self.downloaded_file.lower().endswith('.7z'): self.extracting_archive = None if self.install_type == 'direct_download': download_dir = os.path.dirname(self.downloaded_file) delete_path(download_dir) self.move_new_soundpack() else: extracting_element = self.extracting_infolist[ self.extracting_index] self.extracting_label.setText( _('Extracting {0}').format(extracting_element.filename)) if self.downloaded_file.lower().endswith('.7z'): destination = os.path.join( self.extract_dir, *extracting_element.filename.split('/')) dest_dir = os.path.dirname(destination) if not os.path.isdir(dest_dir): os.makedirs(dest_dir) with open(destination, 'wb') as f: f.write(extracting_element.read()) else: self.extracting_zipfile.extract(extracting_element, self.extract_dir) self.extracting_index += 1
def set_text(self): self.command_line_parameters_label.setText( _('Command line parameters:')) self.keep_launcher_open_checkbox.setText( _('Keep the launcher opened after launching the game')) self.locale_label.setText(_('Language:')) self.locale_combo.setItemText(0, _('System language or best match ({locale})').format( locale=get_ui_locale())) self.allow_mul_insts_checkbox.setText(_('Allow multiple instances of ' 'the launcher to be started')) if getattr(sys, 'frozen', False): self.use_launcher_dir_checkbox.setText(_('Use the launcher ' 'directory as the game directory')) self.no_launcher_version_check_checkbox.setText(_('Do not check ' 'for new version of the CDDA Game Launcher on launch')) self.setTitle(_('Launcher'))
def finish_install_new_soundpack(self): self.installing_new_soundpack = False self.installed_lv.setEnabled(True) self.repository_lv.setEnabled(True) self.install_new_button.setText(_('Install this soundpack')) self.get_main_tab().enable_tab() self.get_mods_tab().enable_tab() self.get_settings_tab().enable_tab() self.get_backups_tab().enable_tab() if self.close_after_install: self.get_main_window().close()
def handle_exception(extype, value, tb): logger = logging.getLogger('cddagl') tb_io = StringIO() traceback.print_tb(tb, file=tb_io) logger.critical( _('Global error:\n' 'Launcher version: {version}\n' 'Type: {extype}\n' 'Value: {value}\n' 'Traceback:\n{traceback}').format(version=version, extype=str(extype), value=str(value), traceback=tb_io.getvalue())) ui_exception(extype, value, tb)
def set_text(self): self.prevent_save_move_checkbox.setText( _('Do not copy or move the save directory')) self.prevent_save_move_checkbox.setToolTip( _('If your save directory size is ' 'large, it might take a long time to copy it during the update ' 'process.\nThis option might help you speed the whole thing but ' 'your previous version will lack the save directory.')) self.keep_archive_copy_checkbox.setText( _('Keep a copy of the downloaded ' 'archive in the following directory:')) self.auto_refresh_builds_checkbox.setText( _('Automatically refresh builds list every')) self.arb_min_label.setText(_('minutes')) self.remove_previous_version_checkbox.setText( _('Remove previous version after update (not recommended)')) self.permanently_delete_files_checkbox.setText( _('Permanently delete files instead of moving them in the recycle ' 'bin (not recommended)')) self.setTitle(_('Update/Installation'))
def retry_rename(src, dst): while os.path.exists(src): try: os.rename(src, dst) except OSError as e: retry_msgbox = QMessageBox() retry_msgbox.setWindowTitle(_('Cannot rename file')) process = None if e.filename is not None: process = find_process_with_file_handle(e.filename) text = _(''' <p>The launcher failed to rename the following file: {src} to {dst}</p> <p>When trying to rename or access {filename}, the launcher raised the following error: {error}</p> ''').format( src=html.escape(src), dst=html.escape(dst), filename=html.escape(e.filename), error=html.escape(e.strerror)) if process is None: text = text + _(''' <p>No process seems to be using that file.</p> ''') else: text = text + _(''' <p>The process <strong>{image_file_name} ({pid})</strong> is currently using that file. You might need to end it if you want to retry.</p> ''').format(image_file_name=process['image_file_name'], pid=process['pid']) retry_msgbox.setText(text) retry_msgbox.setInformativeText(_('Do you want to retry renaming ' 'this file?')) retry_msgbox.addButton(_('Retry renaming the file'), QMessageBox.YesRole) retry_msgbox.addButton(_('Cancel the operation'), QMessageBox.NoRole) retry_msgbox.setIcon(QMessageBox.Critical) if retry_msgbox.exec() == 1: return False return True