From a23692a29c5def34b0abe5a0f357cfaeb0ab64bf Mon Sep 17 00:00:00 2001
From: Pierre-Antoine Rouby <pierre-antoine.rouby@inrae.fr>
Date: Wed, 20 Mar 2024 15:07:50 +0100
Subject: [PATCH] MainWindow: Checker: Add worker.

---
 src/Checker/Checker.py           |  5 ++-
 src/Model/Geometry/Reach.py      |  2 +-
 src/Modules.py                   |  3 ++
 src/View/CheckList/Table.py      |  3 ++
 src/View/CheckList/Worker.py     | 35 +++++++++++++++++++++
 src/View/MainWindow.py           | 11 +++++--
 src/View/MainWindowTabChecker.py | 52 ++++++++++++++++++++++++++++++--
 src/View/Network/Window.py       | 18 ++++++-----
 8 files changed, 115 insertions(+), 14 deletions(-)

diff --git a/src/Checker/Checker.py b/src/Checker/Checker.py
index 328c3588..ae6f04a2 100644
--- a/src/Checker/Checker.py
+++ b/src/Checker/Checker.py
@@ -40,7 +40,7 @@ class STATUS(Enum):
 
     def __or__(self, y):
         v = [self, y]
-        res = self.OK
+        r = self.OK
 
         if self.UNKNOWN in v:
             r = self.UNKNOWN
@@ -60,6 +60,9 @@ class AbstractModelChecker(object):
         self._solver = "study"
         self._modules = Modules.NONE
 
+        self.reset()
+
+    def reset(self):
         self._status = STATUS.UNKNOWN
         self._summary = "Unknown"
 
diff --git a/src/Model/Geometry/Reach.py b/src/Model/Geometry/Reach.py
index d0f173a1..7458f3b1 100644
--- a/src/Model/Geometry/Reach.py
+++ b/src/Model/Geometry/Reach.py
@@ -111,7 +111,7 @@ class Reach(SQLSubModel):
     def _get_profiles_list(self):
         # Profiles list generator is type (int, Point) with the first
         # element the index of the Point in list
-        logger.info(f"Load profiles from reach {self.name}")
+        logger.debug(f"Load profiles from reach {self.name}")
         return list(
             map(
                 lambda p: p[1],
diff --git a/src/Modules.py b/src/Modules.py
index 6f7b1d76..973ee180 100644
--- a/src/Modules.py
+++ b/src/Modules.py
@@ -26,6 +26,9 @@ logger = logging.getLogger()
 class Modules(Flag):
     NONE = 0
 
+    # General
+    STUDY = auto()
+
     # Modelling
     NETWORK = auto()
     GEOMETRY = auto()
diff --git a/src/View/CheckList/Table.py b/src/View/CheckList/Table.py
index 5d210b93..b882eda2 100644
--- a/src/View/CheckList/Table.py
+++ b/src/View/CheckList/Table.py
@@ -75,6 +75,9 @@ class TableModel(PamhyrTableModel):
         return QVariant()
 
 class TabTableModel(PamhyrTableModel):
+    def _setup_lst(self):
+        self._lst = self._opt_data
+
     def compute_status(self, row, column):
         module = self._opt_data[row]
         solver = self._headers[column]
diff --git a/src/View/CheckList/Worker.py b/src/View/CheckList/Worker.py
index 5363b0e7..f17e055f 100644
--- a/src/View/CheckList/Worker.py
+++ b/src/View/CheckList/Worker.py
@@ -17,11 +17,14 @@
 # -*- coding: utf-8 -*-
 
 import time
+import logging
 
 from PyQt5.QtCore import (
     Qt, QObject, pyqtSlot, pyqtSignal
 )
 
+logger = logging.getLogger()
+
 
 class Worker(QObject):
     signalStatus = pyqtSignal(str)
@@ -46,3 +49,35 @@ class Worker(QObject):
             checker._run(self._study)
 
             self.signalStatus.emit("progress")
+
+class TabWorker(QObject):
+    signalStatus = pyqtSignal(str)
+
+    def __init__(self, study, checker_q, parent=None):
+        super(self.__class__, self).__init__(parent)
+
+        self._study = study
+        self._checker_q = checker_q
+
+    @property
+    def study(self):
+        return self._study
+
+
+    @study.setter
+    def study(self, study):
+        self._study = study
+
+    def process(self):
+        self._compute()
+
+    def _compute(self):
+        while True:
+            checker = self._checker_q.get()
+
+            if self._study == None:
+                self._checker_q.put(checker)
+                time.sleep(5)
+            else:
+                checker._run(self._study)
+                self.signalStatus.emit("progress")
diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py
index 81d2520f..ba2f46ed 100644
--- a/src/View/MainWindow.py
+++ b/src/View/MainWindow.py
@@ -394,11 +394,18 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
         for _, window in self.sub_win_list:
             window._propagated_update(key=keys)
 
+        self._tab_widget_checker.update(modules=keys)
+
     def update(self):
         self.set_title()
 
-        self._tab_widget_info.study = self._study
-        self._tab_widget_info.update()
+        if self._tab_widget_info.study != self._study:
+            self._tab_widget_info.study = self._study
+            self._tab_widget_info.update()
+
+        if self._tab_widget_checker.study != self._study:
+            self._tab_widget_checker.study = self._study
+            self._tab_widget_checker.update(modules = Modules.STUDY)
 
     #########
     # MODEL #
diff --git a/src/View/MainWindowTabChecker.py b/src/View/MainWindowTabChecker.py
index 1bbe8492..30cfb29f 100644
--- a/src/View/MainWindowTabChecker.py
+++ b/src/View/MainWindowTabChecker.py
@@ -18,8 +18,13 @@
 
 import logging
 
+from queue import Queue
 from tools import timer, trace, flatten
 
+from PyQt5.QtCore import (
+    QThread,
+)
+
 from PyQt5.QtWidgets import (
     QTableView,
 )
@@ -30,6 +35,7 @@ from Solver.Solvers import solver_type_list, solver_long_name
 
 from View.Tools.PamhyrWidget import PamhyrWidget
 from View.CheckList.Table import TabTableModel
+from View.CheckList.Worker import TabWorker
 
 logger = logging.getLogger()
 
@@ -45,11 +51,24 @@ class WidgetChecker(PamhyrWidget):
             parent=parent
         )
 
+        self.setup_worker()
         self.setup_solver_list()
         self.setup_checker_list()
         self.setup_table()
         self.setup_list()
 
+    def setup_worker(self):
+        self._worker_q = Queue()
+
+        self._worker = TabWorker(self._study, self._worker_q)
+        self._worker_thread = QThread()
+        self._worker.moveToThread(self._worker_thread)
+
+        self._worker.signalStatus.connect(self.update_thread)
+        self._worker_thread.started.connect(self._worker.process)
+
+        self._worker_thread.start()
+
     def setup_solver_list(self):
         self._solvers = list(
             map(
@@ -67,7 +86,10 @@ class WidgetChecker(PamhyrWidget):
         )
 
     def setup_table(self):
-        header = {'type': "Type", **solver_long_name}
+        header = {
+            'type': "Type", "study": "Study",
+            **solver_long_name
+        }
 
         table = self.find(QTableView, f"tableView_checker")
         self._table = TabTableModel(
@@ -88,6 +110,30 @@ class WidgetChecker(PamhyrWidget):
     def study(self, study):
         self._study = study
 
-    def update(self):
-        if self._study is None:
+    def _checkers_filtered(self, modules):
+        return filter(
+            lambda c: c._modules in modules,
+            self._checkers
+        )
+
+    def update_thread(self, key):
+        if key == "progress":
+            self._table.update()
+
+    def update(self, modules=Modules.NONE):
+        if modules is Modules.NONE:
             return
+
+        if Modules.STUDY in modules:
+            self._worker.study = self._study
+
+            for checker in self._checkers:
+                if self._study == None:
+                    checker.reset()
+                self._worker_q.put(checker)
+
+            return
+
+        for checker in self._checkers_filtered(modules):
+            checker.reset()
+            self._worker_q.put(checker)
diff --git a/src/View/Network/Window.py b/src/View/Network/Window.py
index bd0daee4..eab8cae0 100644
--- a/src/View/Network/Window.py
+++ b/src/View/Network/Window.py
@@ -36,6 +36,7 @@ from PyQt5.QtWidgets import (
     QUndoStack, QShortcut,
 )
 
+from Modules import Modules
 from Model.River import RiverNode, RiverReach, River
 
 from View.Tools.PamhyrWindow import PamhyrWindow
@@ -130,13 +131,13 @@ class NetworkWindow(PamhyrWindow):
         self._graph_layout.addWidget(self._graph_widget)
 
     def setup_connections(self):
-        self._nodes_model.dataChanged.connect(self._reachs_model.update)
+        self._nodes_model.dataChanged.connect(self.update)
         self._nodes_model.dataChanged.connect(self._graph_widget.rename_nodes)
         self._reachs_model.dataChanged.connect(
             self._graph_widget.display_update)
-        self._reachs_model.dataChanged.connect(self._nodes_model.update)
-        self._graph_widget.changeEdge.connect(self._reachs_model.update)
-        self._graph_widget.changeNode.connect(self._nodes_model.update)
+        self._reachs_model.dataChanged.connect(self.update)
+        self._graph_widget.changeEdge.connect(self.update)
+        self._graph_widget.changeNode.connect(self.update)
 
         self.find(QAction, "action_toolBar_add").setCheckable(True)
         self.find(QAction, "action_toolBar_add").triggered.connect(
@@ -204,12 +205,15 @@ class NetworkWindow(PamhyrWindow):
 
     def _undo(self):
         self._undo_stack.undo()
-        self._reachs_model.update()
-        self._nodes_model.update()
-        self._graph_widget.display_update()
+        self.update()
 
     def _redo(self):
         self._undo_stack.redo()
+        self.update()
+
+    def update(self):
         self._reachs_model.update()
         self._nodes_model.update()
         self._graph_widget.display_update()
+
+        self._propagate_update(key=Modules.NETWORK)
-- 
GitLab