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 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 dl_progress(self, bytes_read, total_bytes): self.progress_bar.setMaximum(total_bytes) self.progress_bar.setValue(bytes_read) self.download_speed_count += 1 self.size_value_label.setText('{bytes_read}/{total_bytes}'.format( bytes_read=sizeof_fmt(bytes_read), total_bytes=sizeof_fmt(total_bytes))) if self.download_speed_count % 5 == 0: delta_bytes = bytes_read - self.download_last_bytes_read delta_time = datetime.utcnow() - self.download_last_read bytes_secs = delta_bytes / delta_time.total_seconds() self.speed_value_label.setText( _('{bytes_sec}/s').format(bytes_sec=sizeof_fmt(bytes_secs))) self.download_last_bytes_read = bytes_read self.download_last_read = datetime.utcnow()
def completed_extract(): self.extract_size += self.next_extract_file.file_size self.extracting_progress_bar.setValue(self.extract_size) self.extracting_size_label.setText( '{bytes_read}/{total_bytes}'.format( bytes_read=sizeof_fmt(self.extract_size), total_bytes=sizeof_fmt(self.total_extract_size))) delta_bytes = self.extract_size - self.last_extract_bytes delta_time = datetime.utcnow() - self.last_extract if delta_time.total_seconds() == 0: delta_time = timedelta.resolution bytes_secs = delta_bytes / delta_time.total_seconds() self.extracting_speed_label.setText( _('{bytes_sec}/s').format(bytes_sec=sizeof_fmt(bytes_secs))) self.last_extract_bytes = self.extract_size self.last_extract = datetime.utcnow() extract_next_file()
def size_query_finished(self): if (not self.http_reply_aborted and self.http_reply.attribute( QNetworkRequest.HttpStatusCodeAttribute) == 200 and self.http_reply.hasRawHeader(b'Content-Length')): content_length = int(self.http_reply.rawHeader(b'Content-Length')) self.current_repo_info['size'] = content_length 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()] if selected_info is self.current_repo_info: self.size_le.setText(sizeof_fmt(content_length)) else: 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()] if selected_info is self.current_repo_info: self.size_le.setText(_('Unknown'))
def timeout(): if self.backup_scan is None: self.backup_scan = scandir(self.save_dir) else: try: entry = next(self.backup_scan) if entry.is_file(): self.compressing_label.setText( _('Found {filename} in {path}').format( filename=entry.name, path=os.path.dirname(entry.path))) self.backup_files.append(entry.path) self.total_backup_size += entry.stat().st_size self.backup_file_sizes[entry.path ] = entry.stat().st_size self.total_files += 1 elif entry.is_dir(): self.next_backup_scans.append(entry.path) except StopIteration: try: self.backup_scan = scandir( self.next_backup_scans.popleft()) except IndexError: self.backup_searching = False self.backup_compressing = True self.compressing_label.setText( _('Compressing save files')) compressing_speed_label = QLabel() compressing_speed_label.setText(_('{bytes_sec}/s' ).format(bytes_sec=sizeof_fmt(0))) status_bar.addWidget(compressing_speed_label) self.compressing_speed_label = ( compressing_speed_label) compressing_size_label = QLabel() compressing_size_label.setText( '{bytes_read}/{total_bytes}' .format(bytes_read=sizeof_fmt(0), total_bytes=sizeof_fmt(self.total_backup_size)) ) status_bar.addWidget(compressing_size_label) self.compressing_size_label = ( compressing_size_label) progress_bar = QProgressBar() progress_bar.setRange(0, self.total_backup_size) progress_bar.setValue(0) status_bar.addWidget(progress_bar) self.compressing_progress_bar = progress_bar self.comp_size = 0 self.comp_files = 0 self.last_comp_bytes = 0 self.last_comp = datetime.utcnow() self.next_backup_file = None if self.compressing_timer is not None: self.compressing_timer.stop() self.compressing_timer = None self.backup_saves_step2()
def restore_backup(self): 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] model = selection_model.model() backup_name = model.data(model.index(selected.row(), 0)) if not os.path.isfile(selected_info['path']): return main_window = self.get_main_window() status_bar = main_window.statusBar() self.temp_save_dir = None save_dir = os.path.join(self.game_dir, 'save') if os.path.isdir(save_dir): temp_save_dir = os.path.join(self.game_dir, 'save-{0}'.format( '%08x' % random.randrange(16**8))) while os.path.exists(temp_save_dir): temp_save_dir = os.path.join(self.game_dir, 'save-{0}'.format( '%08x' % random.randrange(16**8))) if not retry_rename(save_dir, temp_save_dir): status_bar.showMessage(_('Could not rename the save directory')) return self.temp_save_dir = temp_save_dir elif os.path.isfile(save_dir): if not delete_path(save_dir): status_bar.showMessage(_('Could not remove the save file')) return # Extract the backup archive self.extracting_backup = True self.extract_dir = self.game_dir status_bar.clearMessage() status_bar.busy += 1 self.total_extract_size = selected_info['actual_size'] extracting_label = QLabel() extracting_label.setText(_('Extracting backup')) status_bar.addWidget(extracting_label, 100) self.extracting_label = extracting_label extracting_speed_label = QLabel() extracting_speed_label.setText(_('{bytes_sec}/s' ).format(bytes_sec=sizeof_fmt(0))) status_bar.addWidget(extracting_speed_label) self.extracting_speed_label = extracting_speed_label extracting_size_label = QLabel() extracting_size_label.setText( '{bytes_read}/{total_bytes}' .format(bytes_read=sizeof_fmt(0), total_bytes=sizeof_fmt(self.total_extract_size)) ) status_bar.addWidget(extracting_size_label) self.extracting_size_label = ( extracting_size_label) progress_bar = QProgressBar() progress_bar.setRange(0, self.total_extract_size) progress_bar.setValue(0) status_bar.addWidget(progress_bar) self.extracting_progress_bar = progress_bar self.extract_size = 0 self.extract_files = 0 self.last_extract_bytes = 0 self.last_extract = datetime.utcnow() self.next_backup_file = None self.disable_tab() self.get_main_tab().disable_tab() self.get_soundpacks_tab().disable_tab() self.get_settings_tab().disable_tab() self.get_mods_tab().disable_tab() self.get_backups_tab().disable_tab() self.restore_button.setEnabled(True) self.restore_button.setText(_('Cancel restore backup')) class ExtractingThread(QThread): completed = pyqtSignal() def __init__(self, zfile, element, dir): super(ExtractingThread, self).__init__() self.zfile = zfile self.element = element self.dir = dir def __del__(self): self.wait() def run(self): self.zfile.extract(self.element, self.dir) self.completed.emit() 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 completed_extract(): self.extract_size += self.next_extract_file.file_size self.extracting_progress_bar.setValue(self.extract_size) self.extracting_size_label.setText( '{bytes_read}/{total_bytes}' .format(bytes_read=sizeof_fmt(self.extract_size), total_bytes=sizeof_fmt(self.total_extract_size)) ) delta_bytes = self.extract_size - self.last_extract_bytes delta_time = datetime.utcnow() - self.last_extract if delta_time.total_seconds() == 0: delta_time = timedelta.resolution bytes_secs = delta_bytes / delta_time.total_seconds() self.extracting_speed_label.setText(_('{bytes_sec}/s' ).format(bytes_sec=sizeof_fmt(bytes_secs))) self.last_extract_bytes = self.extract_size self.last_extract = datetime.utcnow() extract_next_file() self.extracting_zipfile = zipfile.ZipFile(selected_info['path']) self.extracting_infolist = deque(self.extracting_zipfile.infolist()) extract_next_file()
def timeout(): try: entry = next(self.backups_scan) filename, ext = os.path.splitext(entry.name) if ext.lower() == '.zip': uncompressed_size = 0 character_count = 0 worlds_set = set() try: with zipfile.ZipFile(entry.path) as zfile: for info in zfile.infolist(): if not info.filename.startswith('save/'): return uncompressed_size += info.file_size path_items = info.filename.split('/') if len(path_items) == 3: save_file = path_items[-1] if save_file.endswith('.sav'): character_count += 1 if save_file in cons.WORLD_FILES: worlds_set.add(path_items[1]) except zipfile.BadZipFile: pass # We found a valid backup compressed_size = entry.stat().st_size modified_date = datetime.fromtimestamp( entry.stat().st_mtime) formated_date = format_datetime(modified_date, format='short', locale=self.app_locale) arrow_date = arrow.get(entry.stat().st_mtime) human_delta = arrow_date.humanize(arrow.utcnow(), locale=self.app_locale) row_index = self.backups_table.rowCount() self.backups_table.insertRow(row_index) flags = (Qt.ItemIsSelectable | Qt.ItemIsEnabled) if uncompressed_size == 0: compression_ratio = 0 else: compression_ratio = 1.0 - (compressed_size / uncompressed_size) rounded_ratio = round(compression_ratio, 4) ratio_percent = format_percent(rounded_ratio, format='#.##%', locale=self.app_locale) if self.previous_selection is not None: if entry.path == self.previous_selection: self.previous_selection_index = row_index fields = ( (filename, alphanum_key(filename)), (human_delta, modified_date), (str(len(worlds_set)), len(worlds_set)), (str(character_count), character_count), (sizeof_fmt(uncompressed_size), uncompressed_size), (sizeof_fmt(compressed_size), compressed_size), (ratio_percent, compression_ratio), (formated_date, modified_date) ) for index, value in enumerate(fields): item = SortEnabledTableWidgetItem(value[0], value[1]) item.setFlags(flags) self.backups_table.setItem(row_index, index, item) if index == 0: self.backups[item] = { 'path': entry.path, 'actual_size': uncompressed_size } except StopIteration: self.update_backups_timer.stop() if self.previous_selection_index is not None: selection_model = self.backups_table.selectionModel() model = selection_model.model() first_index = model.index(self.previous_selection_index, 0) last_index = model.index(self.previous_selection_index, self.backups_table.columnCount() - 1) row_selection = QItemSelection(first_index, last_index) selection_model.select(row_selection, QItemSelectionModel.Select) selection_model.setCurrentIndex(first_index, QItemSelectionModel.Select) self.backups_table.sortItems(1, Qt.DescendingOrder) self.backups_table.horizontalHeader().setSortIndicatorShown( True) if self.after_update_backups is not None: self.after_update_backups() self.after_update_backups = None