From 191ea58fb1d1d08e083124ad3e10ab523861e9a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20M=C3=BCller?= Date: Thu, 30 Nov 2023 11:10:01 +0100 Subject: [PATCH] enh: prevent GUI from locking when transferring large file --- CHANGELOG | 1 + mpl_data_cast/gui/main.py | 33 +++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f645250..2e6e7c2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ 0.6.0 - feat: generalize GUI to use all recipes + - enh: prevent GUI from locking when transferring large file - enh: re-use tree count information for transfer progress bar - enh: display the actual directory tree instead of a table - enh: compute file hash while copying, avoiding reading data twice diff --git a/mpl_data_cast/gui/main.py b/mpl_data_cast/gui/main.py index 785e130..c56503e 100644 --- a/mpl_data_cast/gui/main.py +++ b/mpl_data_cast/gui/main.py @@ -3,7 +3,9 @@ import signal import pathlib import sys +import threading import traceback +from typing import Dict import dclab import h5py @@ -151,10 +153,20 @@ def on_task_transfer(self) -> None: self.widget_output.path) tree_counter = self.widget_input.tree_counter - with Callback(self, tree_counter) as path_callback: + with CastingCallback(self, tree_counter) as callback: + # run the casting operation in a separate thread + caster = CastingThread(rp, callback=callback) + caster.start() - result = rp.cast(path_callback=path_callback) - self.widget_output.trigger_recount_objects() + while not caster.result: + QtWidgets.QApplication.processEvents( + QtCore.QEventLoop.ProcessEventsFlag.AllEvents, 300) + time.sleep(.1) + + caster.join() + result = caster.result + + self.widget_output.trigger_recount_objects() if result["success"]: self.progressBar.setValue(100) @@ -177,7 +189,7 @@ def on_task_transfer(self) -> None: self.pushButton_transfer.setEnabled(True) -class Callback: +class CastingCallback: """Makes it possible to execute code everytime a file was processed. Used for updating the progress bar and calculating the processing rate.""" @@ -208,11 +220,20 @@ def __call__(self, path) -> None: # go to undetermined state self.gui.progressBar.setRange(0, 0) - QtWidgets.QApplication.processEvents( - QtCore.QEventLoop.ProcessEventsFlag.AllEvents, 300) self.counter += 1 +class CastingThread(threading.Thread): + def __init__(self, rp, callback, *args, **kwargs): + super(CastingThread, self).__init__(*args, **kwargs) + self.rp = rp + self.callback = callback + self.result = {} + + def run(self): + self.result = self.rp.cast(callback=self.callback) + + def excepthook(etype, value, trace) -> None: """ Handler for all unhandled exceptions.