diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index ff57e77a549888db177cdc51065e0a6682445549..11ac20f490bccad224d25d433b7f520b2a9c4108 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -62,6 +62,7 @@ from View.SolverParameters.Window import SolverParametersWindow from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow from View.CheckList.Window import CheckListWindow from View.Results.Window import ResultsWindow +from View.Results.ReadingResultsDialog import ReadingResultsDialog from View.Debug.Window import ReplWindow # Optional internal display of documentation for make the application @@ -966,15 +967,20 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): sol.show() def open_solver_results(self, solver, results=None): + def reading_fn(): + self._tmp_results = results + # If no specific results, get last results if results is None: - results = self._last_results + def reading_fn(): + self._tmp_results = self._last_results if self._last_results is None: - results = solver.results( - self._study, - self._solver_workdir(solver), - ) + def reading_fn(): + self._tmp_results = solver.results( + self._study, + self._solver_workdir(solver), + ) # Open from file if type(results) is str: @@ -982,11 +988,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): name = os.path.basename(results).replace(".BIN", "") - results = solver.results( - self._study, - os.path.dirname(results), - name=name - ) + def reading_fn(): + self._tmp_results = solver.results( + self._study, + os.path.dirname(results), + name=name + ) + + dlg = ReadingResultsDialog(reading_fn=reading_fn, parent=self) + dlg.exec_() + results = self._tmp_results # No results available if results is None: diff --git a/src/View/Results/ReadingResultsDialog.py b/src/View/Results/ReadingResultsDialog.py new file mode 100644 index 0000000000000000000000000000000000000000..84fa17ea6744dec8397cab1af096f06cb824d30b --- /dev/null +++ b/src/View/Results/ReadingResultsDialog.py @@ -0,0 +1,117 @@ +# ReadingResultsDialog.py -- Pamhyr +# Copyright (C) 2023-2024 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +# -*- coding: utf-8 -*- + +import logging + +from tools import logger_exception + +from View.Tools.PamhyrWindow import PamhyrDialog +from View.Results.translate import ResultsTranslate + +from PyQt5.QtGui import ( + QKeySequence, +) + +from PyQt5.QtCore import ( + Qt, QVariant, QAbstractTableModel, QTimer, + QObject, pyqtSlot, pyqtSignal, QThread, +) + +from PyQt5.QtWidgets import ( + QLabel, +) + +logger = logging.getLogger() + + +class Worker(QObject): + signalStatus = pyqtSignal(str) + + def __init__(self, reading_fn, parent=None): + super(self.__class__, self).__init__(parent) + + self._reading_fn = reading_fn + + def process(self): + self._reading_fn() + self.signalStatus.emit('end') + + +class ReadingResultsDialog(PamhyrDialog): + _pamhyr_ui = "DialogReadingResults" + _pamhyr_name = "Reading results" + + _spin = ["-", "\\", "|", "/"] + + def __init__(self, reading_fn, parent=None): + trad = ResultsTranslate() + super(ReadingResultsDialog, self).__init__( + title=trad[self._pamhyr_name], + trad=trad, + options=[], + parent=parent + ) + + self._reading_fn = reading_fn + + self._init_default_values() + + self.setup_timer() + self.setup_worker() + + self._timer.start(150) + self._worker_thread.start() + + def _init_default_values(self): + self._spinner_step = 0 + + self.set_label_text("label_spinner", self._spin[0]) + + def setup_worker(self): + self._worker = Worker(self._reading_fn) + self._worker_thread = QThread(parent=self) + self._worker.moveToThread(self._worker_thread) + + self._worker.signalStatus.connect(self.close) + self._worker_thread.started.connect(self._worker.process) + + def setup_timer(self): + self._timer = QTimer(self) + self._timer.timeout.connect(self.update_spinner) + + def update_spinner(self): + self._spinner_step += 1 + self._spinner_step %= len(self._spin) + + self.set_label_text( + "label_spinner", + self._spin[self._spinner_step] + ) + + def end_worker(self): + self._worker_thread.terminate() + self._worker_thread.wait() + + def close(self): + try: + self._timer.stop() + self.end_worker() + except Exception as e: + logger_exception(e) + + super().close() diff --git a/src/View/Results/translate.py b/src/View/Results/translate.py index 5f28c7f8ed78222303bcd453a66baea72783cab8..a42d8638dbe6704449afd75680cc104e46e79aaa 100644 --- a/src/View/Results/translate.py +++ b/src/View/Results/translate.py @@ -28,6 +28,9 @@ class ResultsTranslate(MainTranslate): super(ResultsTranslate, self).__init__() self._dict["Results"] = _translate("Results", "Results") + self._dict["Reading results"] = _translate( + "Results", "Reading results" + ) self._dict['day'] = _translate("Results", "day") self._dict['days'] = _translate("Results", "days") diff --git a/src/View/RunSolver/Window.py b/src/View/RunSolver/Window.py index 2e09066862c2cc974e8e89db4999fd8b7cd7b3e7..87f859e1dd02b6679461a2a44569152b873611f2 100644 --- a/src/View/RunSolver/Window.py +++ b/src/View/RunSolver/Window.py @@ -44,6 +44,7 @@ from PyQt5.QtWidgets import ( ) from View.RunSolver.Log.Window import SolverLogFileWindow +from View.Results.ReadingResultsDialog import ReadingResultsDialog try: from signal import SIGTERM, SIGSTOP, SIGCONT @@ -275,14 +276,18 @@ class SolverLogWindow(PamhyrWindow): def _update_get_results(self): if self._results is None: - try: - self._results = self._solver.results( - self._study, self._workdir, qlog=self._output - ) - self._parent.set_results(self._solver, self._results) - except Exception as e: - logger.error(f"Failed to open results") - logger_exception(e) + def reading_fn(): + try: + self._results = self._solver.results( + self._study, self._workdir, qlog=self._output + ) + self._parent.set_results(self._solver, self._results) + except Exception as e: + logger.error(f"Failed to open results") + logger_exception(e) + + dlg = ReadingResultsDialog(reading_fn=reading_fn, parent=self) + dlg.exec_() def _update_logs_all(self): while self._output.qsize() != 0: @@ -352,9 +357,13 @@ class SolverLogWindow(PamhyrWindow): def results(self): if self._results is None: - self._results = self._solver.results( - self._study, self._workdir, qlog=self._output - ) + def reading_fn(): + self._results = self._solver.results( + self._study, self._workdir, qlog=self._output + ) + + dlg = ReadingResultsDialog(reading_fn=reading_fn, parent=self) + dlg.exec_() self._parent.set_results(self._solver, self._results) self._parent.open_solver_results(self._solver, self._results) diff --git a/src/View/ui/DialogReadingResults.ui b/src/View/ui/DialogReadingResults.ui new file mode 100644 index 0000000000000000000000000000000000000000..f93ea2a650916a49b2e5ff70d71f0f573170ba87 --- /dev/null +++ b/src/View/ui/DialogReadingResults.ui @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Dialog</class> + <widget class="QDialog" name="Dialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>205</width> + <height>42</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Read results:</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_spinner"> + <property name="font"> + <font> + <family>Ubuntu Mono</family> + <pointsize>12</pointsize> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>.</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui>