From 71aed9ba0efda0a7abe87d4587a0ad463c84fa84 Mon Sep 17 00:00:00 2001 From: real-yfprojects Date: Mon, 18 Apr 2022 18:53:46 +0200 Subject: [PATCH] Keep GUI responsive while processing diff results. * src/vorta/views/archive_tab.py (ArchiveTab.list_diff_result): Start `ParseThread` that does the processing and creates the dialog. * src/vorta/views/archive_tab.py (ArchiveTab.show_diff_result): Implement method showing `DiffResultDialog`. * src/vorta/views/diff_result.py (ParseThread): Move processing of diff results to this thread. --- src/vorta/views/archive_tab.py | 33 +++++++++++++++++------- src/vorta/views/diff_result.py | 46 ++++++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/vorta/views/archive_tab.py b/src/vorta/views/archive_tab.py index 3c33963b..c31f4d0e 100644 --- a/src/vorta/views/archive_tab.py +++ b/src/vorta/views/archive_tab.py @@ -31,6 +31,8 @@ from vorta.views.extract_dialog import ExtractDialog from vorta.views.source_tab import SizeItem from vorta.views.utils import get_colored_icon +from .diff_result import DiffTree, ParseThread + uifile = get_asset('UI/archivetab.ui') ArchiveTabUI, ArchiveTabBase = uic.loadUiType(uifile) @@ -865,15 +867,28 @@ class ArchiveTab(ArchiveTabBase, ArchiveTabUI, BackupProfileMixin): name=result['params']['archive_name_newer']) archive_older = ArchiveModel.get( name=result['params']['archive_name_older']) - window = DiffResultDialog(result['data'], - archive_newer, archive_older, - result['params']['json_lines']) - self._toggle_all_buttons(True) - window.setParent(self) - window.setWindowFlags(Qt.WindowType.Window) - window.setWindowModality(Qt.WindowModality.NonModal) - self._resultwindow = window # for testing - window.show() + self._set_status(self.tr("Processing diff results.")) + + model = DiffTree() + + self._t = ParseThread(result['data'], result['params']['json_lines'], + model) + self._t.finished.connect(lambda: self.show_diff_result( + archive_newer, archive_older, model)) + self._t.start() + + def show_diff_result(self, archive_newer, archive_older, model): + self._t = None + + # show dialog + self._toggle_all_buttons(True) + self._set_status('') + window = DiffResultDialog(archive_newer, archive_older, model) + window.setParent(self) + window.setWindowFlags(Qt.WindowType.Window) + window.setWindowModality(Qt.WindowModality.NonModal) + self._resultwindow = window # for testing + window.show() def rename_action(self): profile = self.profile() diff --git a/src/vorta/views/diff_result.py b/src/vorta/views/diff_result.py index a2079f27..06dc0836 100644 --- a/src/vorta/views/diff_result.py +++ b/src/vorta/views/diff_result.py @@ -7,7 +7,7 @@ from pathlib import PurePath from typing import List, Optional, Tuple from PyQt5 import uic -from PyQt5.QtCore import QMimeData, QModelIndex, QPoint, Qt, QUrl +from PyQt5.QtCore import QMimeData, QModelIndex, QPoint, Qt, QThread, QUrl from PyQt5.QtGui import QColor, QKeySequence from PyQt5.QtWidgets import (QApplication, QHeaderView, QMenu, QShortcut, QTreeView) @@ -24,33 +24,53 @@ DiffResultUI, DiffResultBase = uic.loadUiType(uifile) logger = logging.getLogger(__name__) -class DiffResultDialog(DiffResultBase, DiffResultUI): - """Display the results of `borg diff`.""" +class ParseThread(QThread): + """A thread parsing diff results.""" - def __init__(self, fs_data, archive_newer, archive_older, json_lines): + def __init__(self, + fs_data: str, + json_lines: bool, + model: 'DiffTree', + parent=None): """Init.""" - super().__init__() - self.setupUi(self) - - self.model = DiffTree(self) + super().__init__(parent) + self.model = model + self.fs_data = fs_data + self.json_lines = json_lines + def run(self) -> None: + """Do the work""" # Older version do not support json output - if json_lines: + if self.json_lines: # If fs_data is already a dict, then there was just a single json-line # and the default handler already parsed into json dict, otherwise # fs_data is a str, and needs to be split and parsed into json dicts - if isinstance(fs_data, dict): - lines = [fs_data] + if isinstance(self.fs_data, dict): + lines = [self.fs_data] else: lines = [ - json.loads(line) for line in fs_data.split('\n') if line + json.loads(line) for line in self.fs_data.split('\n') + if line ] parse_diff_json(lines, self.model) else: - lines = [line for line in fs_data.split('\n') if line] + lines = [line for line in self.fs_data.split('\n') if line] parse_diff_lines(lines, self.model) + +class DiffResultDialog(DiffResultBase, DiffResultUI): + """Display the results of `borg diff`.""" + + def __init__(self, archive_newer: str, archive_older: str, + model: 'DiffTree'): + """Init.""" + super().__init__() + self.setupUi(self) + + self.model = model + self.model.setParent(self) + self.treeView: QTreeView self.treeView.setUniformRowHeights( True) # Allows for scrolling optimizations.