diff --git a/src/Checker/Study.py b/src/Checker/Study.py index d0b84f21775ae33ec42eaed0d0b08da32cae9106..c650e45a7f8bb9b3507aea1764532f984f38417c 100644 --- a/src/Checker/Study.py +++ b/src/Checker/Study.py @@ -34,3 +34,41 @@ class StudyNetworkReachChecker(AbstractModelChecker): self._summary = "ok" self._status = STATUS.OK return True + + +class DummyOK(AbstractModelChecker): + def __init__(self): + super(DummyOK, self).__init__() + + self._name = _translate("Checker", "Dummy ok") + self._description = _translate("Checker", "Dummy ok") + + def run(self, study): + self._summary = "ok" + self._status = STATUS.OK + return True + + +class DummyWARNING(AbstractModelChecker): + def __init__(self): + super(DummyWARNING, self).__init__() + + self._name = _translate("Checker", "Dummy warning") + self._description = _translate("Checker", "Dummy warning") + + def run(self, study): + self._summary = "Warning detected" + self._status = STATUS.WARNING + return True + +class DummyERROR(AbstractModelChecker): + def __init__(self): + super(DummyERROR, self).__init__() + + self._name = _translate("Checker", "Dummy error") + self._description = _translate("Checker", "Dummy error") + + def run(self, study): + self._summary = "Error detected" + self._status = STATUS.ERROR + return True diff --git a/src/Model/Study.py b/src/Model/Study.py index 5cc485c2245cd7a8c53ac8b679edf4beecd9b9aa..9ee9e5f1f8bd2dc1ccbab8cc3fcbf815491df818 100644 --- a/src/Model/Study.py +++ b/src/Model/Study.py @@ -36,6 +36,9 @@ class Study(Serializable): def checkers(cls): lst = [ StudyNetworkReachChecker(), + DummyOK(), + DummyWARNING(), + DummyERROR(), ] return lst diff --git a/src/View/CheckList/Window.py b/src/View/CheckList/Window.py index c83bda9e2317bf750f3e96ad9eca04ea76a42dc0..85244d4864cf0a7897e462abe7d2e7ee7653c882 100644 --- a/src/View/CheckList/Window.py +++ b/src/View/CheckList/Window.py @@ -1,8 +1,5 @@ # -*- coding: utf-8 -*- -import time -import threading - from tools import trace, timer from View.ASubWindow import ASubMainWindow @@ -14,8 +11,8 @@ from PyQt5.QtGui import ( from PyQt5.QtCore import ( Qt, QVariant, QAbstractTableModel, - QCoreApplication, QModelIndex, pyqtSlot, - QRect, + QCoreApplication, QModelIndex, QRect, QThread, + pyqtSlot, pyqtSignal, ) from PyQt5.QtWidgets import ( @@ -23,22 +20,18 @@ from PyQt5.QtWidgets import ( QFileDialog, QTableView, QAbstractItemView, QUndoStack, QShortcut, QAction, QItemDelegate, QComboBox, QVBoxLayout, QHeaderView, QTabWidget, - QProgressBar, + QProgressBar, QLabel, ) from View.CheckList.Table import TableModel +from View.CheckList.Worker import Worker _translate = QCoreApplication.translate -def _run_checker_list(study, checker_list, parent): - parent.start_compute() - for checker in checker_list: - time.sleep(1) - checker.run(study) - parent.progress() - parent.end_compute() - class CheckListWindow(ASubMainWindow, ListedSubWindow): + + signalStatus = pyqtSignal(str) + def __init__(self, title="Check list", study=None, config=None, solver=None, parent=None): @@ -61,6 +54,7 @@ class CheckListWindow(ASubMainWindow, ListedSubWindow): self.setup_progress_bar() self.setup_connections() self.setup_thread() + self.setup_statusbar() def setup_table(self): table = self.find(QTableView, f"tableView") @@ -87,44 +81,86 @@ class CheckListWindow(ASubMainWindow, ListedSubWindow): self.find(QPushButton, "pushButton_cancel").clicked.connect(self.reject) def setup_thread(self): - self._t1 = threading.Thread( - target=_run_checker_list, - args=(self._study, self._checker_list, self,) - ) - self._t1.start() + self._worker = Worker(self._study, self._checker_list) + self._worker_thread = QThread() + self._worker.moveToThread(self._worker_thread) + + # Connect any worker signals + self._worker.signalStatus.connect(self.update) + self._worker_thread.started.connect(self._worker.process) + + self._worker_thread.start() + + def retry(self): + self._worker_thread.terminate() + self._worker_thread.wait() + + self.find(QPushButton, "pushButton_retry").setEnabled(False) + self.find(QPushButton, "pushButton_ok").setEnabled(False) + + self.setup_thread() + + def _compute_status(self): + ok = len(list(filter(lambda c: c.is_ok(), self._checker_list))) + warning = len(list(filter(lambda c: c.is_warning(), self._checker_list))) + error = len(list(filter(lambda c: c.is_error(), self._checker_list))) + + return ok, warning, error + + def _compute_status_label(self): + ok, warning, error = self._compute_status() + return (f"<font color=\"Green\">Ok: {ok} </font> |" + + f"<font color=\"Yellow\">Warning: {warning} </font> |" + + f"<font color=\"Red\">Error: {error}</font>") + + def setup_statusbar(self): + txt = self._compute_status_label() + self._status_label = QLabel(txt) + self.statusbar.addPermanentWidget(self._status_label) + + def update_statusbar(self): + txt = self._compute_status_label() + self._status_label.setText(txt) def progress(self): self._p += 1 self._progress.setValue(self._p) - # self._table.update() + self._table.update() def start_compute(self): self._p = 0 self._progress.setValue(self._p) + def info_compute(self, str): + self.statusbar.showMessage(str, 3000) + def end_compute(self): self._table.layoutChanged.emit() self.find(QPushButton, "pushButton_retry").setEnabled(True) - errors = list(filter(lambda c: c.is_error(), self._checker_list)) - if len(errors) == 0: + errors = any(filter(lambda c: c.is_error(), self._checker_list)) + if errors: self.find(QPushButton, "pushButton_ok").setEnabled(True) - def end(self): - # self._t1.join() - self.close() + self.update_statusbar() - def retry(self): - self._t1.join() - self._t1 = threading.Thread( - target=_run_checker_list, - args=(self._study, self._checker_list, self,) - ) + def update(self, key:str): + if key == "start": + self.start_compute() + self.info_compute("Starting ...") + elif key == "end": + self.info_compute("Finish") + self.end_compute() + elif key == "progress": + self.progress() + else: + self.info_compute(key) - self.find(QPushButton, "pushButton_retry").setEnabled(False) - self.find(QPushButton, "pushButton_ok").setEnabled(False) + self.update_statusbar() - self._t1.start() + def end(self): + # self._worker.join()b + self.close() def reject(self): print("cancel") diff --git a/src/View/CheckList/Worker.py b/src/View/CheckList/Worker.py new file mode 100644 index 0000000000000000000000000000000000000000..dfde09310e3f40a60262219c1263394c938d240a --- /dev/null +++ b/src/View/CheckList/Worker.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- + +import time + +from PyQt5.QtCore import ( + Qt, QObject, pyqtSlot, pyqtSignal +) + +class Worker(QObject): + signalStatus = pyqtSignal(str) + + def __init__(self, study, checker_list, parent=None): + super(self.__class__, self).__init__(parent) + + self._study = study + self._checker_list = checker_list + + def process(self): + self.signalStatus.emit('start') + self._compute() + self.signalStatus.emit('end') + + def _compute(self): + for checker in self._checker_list: + self.signalStatus.emit(checker.name) + + time.sleep(1) + checker.run(self._study) + + self.signalStatus.emit("progress")