From 51031e7359582e3f1db19eda5bda11ec26f57b42 Mon Sep 17 00:00:00 2001
From: Pierre-Antoine Rouby <pierre-antoine.rouby@inrae.fr>
Date: Tue, 19 Mar 2024 09:05:52 +0100
Subject: [PATCH] Pamhyr: Add pamhyr modules flags enum and checker status OR
 operator.

---
 src/Checker/Checker.py               | 27 ++++++++++++++--
 src/Modules.py                       | 46 ++++++++++++++++++++++++++++
 src/View/Frictions/Window.py         |  8 +++--
 src/View/Geometry/Profile/Window.py  |  3 +-
 src/View/Geometry/Window.py          |  7 +++--
 src/View/InitialConditions/Window.py |  8 +++--
 src/View/MainWindow.py               | 25 ++++++++-------
 src/View/Tools/PamhyrWindow.py       | 10 +++---
 src/View/Translate.py                |  4 +--
 9 files changed, 107 insertions(+), 31 deletions(-)
 create mode 100644 src/Modules.py

diff --git a/src/Checker/Checker.py b/src/Checker/Checker.py
index 60cd948c..d0bff2c4 100644
--- a/src/Checker/Checker.py
+++ b/src/Checker/Checker.py
@@ -16,16 +16,39 @@
 
 # -*- coding: utf-8 -*-
 
-from enum import Enum
+import logging
 
+from enum import Enum
 from Model.Except import NotImplementedMethodeError
 
+logger = logging.getLogger()
+
 
 class STATUS(Enum):
-    UNKNOWN = -1
     OK = 0
     WARNING = 1
     ERROR = 2
+    UNKNOWN = 999
+
+    def __eq__(self, y):
+        return self.value == y.value
+
+    def __gt__(self, y):
+        return self.value > y.value
+
+    def __or__(self, y):
+        v = [self, y]
+        res = self.OK
+
+        if self.UNKNOWN in v:
+            r = self.UNKNOWN
+        if self.ERROR in v:
+            r = self.ERROR
+        if self.WARNING in v:
+            r = self.WARNING
+
+        logger.debug(f"CHECKER: STATUS: {self} | {y} = {r}")
+        return r
 
 
 class AbstractModelChecker(object):
diff --git a/src/Modules.py b/src/Modules.py
new file mode 100644
index 00000000..d7107c37
--- /dev/null
+++ b/src/Modules.py
@@ -0,0 +1,46 @@
+# Modules.py -- Pamhyr
+# Copyright (C) 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 enum import Flag, auto
+
+logger = logging.getLogger()
+
+
+class Modules(Flag):
+    NONE = 0
+
+    # Modelling
+    NETWORK = auto()
+    GEOMETRY = auto()
+    BOUNDARY_CONDITION = auto()
+    LATERAL_CONTRIBUTION = auto()
+    FRICTION = auto()
+    INITIAL_CONDITION = auto()
+    HYDRAULIC_STRUCTURES = auto()
+    RESERVOIR = auto()
+    SEDIMENT_LAYER = auto()
+    RESULT = auto()
+
+    # Display
+    WINDOW_LIST = auto()
+
+    @classmethod
+    def all(cls):
+        return ~cls.NONE
diff --git a/src/View/Frictions/Window.py b/src/View/Frictions/Window.py
index ba2fa098..a1922ddf 100644
--- a/src/View/Frictions/Window.py
+++ b/src/View/Frictions/Window.py
@@ -39,6 +39,8 @@ from PyQt5.QtWidgets import (
     QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
 )
 
+from Modules import Modules
+
 from View.Frictions.UndoCommand import (
     PasteCommand, DuplicateCommand,
 )
@@ -181,10 +183,10 @@ class FrictionsWindow(PamhyrWindow):
 
     def update(self):
         self._set_current_reach()
-        # self._propagate_update(key="friction")
+        # self._propagate_update(key=Modules.FRICTION)
 
-    def _propagated_update(self, key=None):
-        if key != "geometry":
+    def _propagated_update(self, key=Modules(0)):
+        if Modules.GEOMETRY not in key:
             return
 
         self.update_plot()
diff --git a/src/View/Geometry/Profile/Window.py b/src/View/Geometry/Profile/Window.py
index 0ca3cbd3..9a274c9f 100644
--- a/src/View/Geometry/Profile/Window.py
+++ b/src/View/Geometry/Profile/Window.py
@@ -22,6 +22,7 @@ import csv
 from time import time
 
 from tools import trace, timer
+from Modules import Modules
 
 from PyQt5.QtGui import (
     QKeySequence,
@@ -134,7 +135,7 @@ class ProfileWindow(PamhyrWindow):
 
     def update(self):
         self.update_plot()
-        self._propagate_update(key="geometry")
+        self._propagate_update(key=Modules.GEOMETRY)
 
     def update_plot(self):
         self._tablemodel.blockSignals(True)
diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py
index 8aef38fb..17affaf3 100644
--- a/src/View/Geometry/Window.py
+++ b/src/View/Geometry/Window.py
@@ -40,6 +40,7 @@ from PyQt5.QtWidgets import (
     QLabel, QAbstractItemView,
 )
 
+from Modules import Modules
 from Model.Except import ExternFileMissingError
 
 from View.Tools.PamhyrWindow import PamhyrWindow
@@ -223,10 +224,10 @@ class GeometryWindow(PamhyrWindow):
         self.changed_slider_value()
 
         if propagate:
-            self._propagate_update(key="geometry")
+            self._propagate_update(key=Modules.GEOMETRY)
 
-    def _propagated_update(self, key=None):
-        if key != "network":
+    def _propagated_update(self, key=Modules(0)):
+        if Modules.NETWORK not in key:
             return
 
         self._update(propagate=False)
diff --git a/src/View/InitialConditions/Window.py b/src/View/InitialConditions/Window.py
index fb3361bc..74262f5a 100644
--- a/src/View/InitialConditions/Window.py
+++ b/src/View/InitialConditions/Window.py
@@ -39,6 +39,8 @@ from PyQt5.QtWidgets import (
     QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
 )
 
+from Modules import Modules
+
 from View.InitialConditions.UndoCommand import (
     SetCommand, AddCommand, DelCommand,
     SortCommand, MoveCommand, PasteCommand,
@@ -183,14 +185,14 @@ class InitialConditionsWindow(PamhyrWindow):
 
     def update(self):
         self._update_plot()
-        self._propagate_update(key="initial_condition")
+        self._propagate_update(key=Modules.INITIAL_CONDITION)
 
     def _update_plot(self):
         self.plot_1.draw()
         self.plot_2.draw()
 
-    def _propagated_update(self, key=None):
-        if key != "geometry":
+    def _propagated_update(self, key=Modules(0)):
+        if Modules.GEOMETRY not in key:
             return
 
         self.update()
diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py
index f8763814..0fcccd51 100644
--- a/src/View/MainWindow.py
+++ b/src/View/MainWindow.py
@@ -38,6 +38,8 @@ from PyQt5.QtWidgets import (
 )
 from PyQt5.uic import loadUi
 
+from Modules import Modules
+
 from View.Tools.ASubWindow import WindowToolKit
 from View.Tools.ListedSubWindow import ListedSubWindow
 from View.DummyWindow import DummyWindow
@@ -359,27 +361,24 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
         )
 
     def _init_propagation_keys(self):
-        self._propagation_keys = set()
+        self._propagation_keys = Modules(0)
 
-    def _propagate_update(self, key=None):
-        self._propagation_keys.add(key)
+    def _propagate_update(self, key=Modules(0)):
+        self._propagation_keys |= key
         logger.debug(f"Propagation keys: {self._propagation_keys}")
 
     def _do_propagate_update(self):
         self.update()
 
-        keys = self._propagation_keys.copy()
+        keys = self._propagation_keys
         self._init_propagation_keys()
 
-        for key in keys:
-            if key == "window_list":
-                logger.debug(f"Update window list")
-                self._do_update_window_list()
-                continue
+        if Modules.WINDOW_LIST in keys:
+            self._do_update_window_list()
 
-            logger.debug(f"Propagation of {key}")
-            for _, window in self.sub_win_list:
-                window._propagated_update(key=key)
+        logger.debug(f"Propagation of {keys}")
+        for _, window in self.sub_win_list:
+            window._propagated_update(key=keys)
 
     def update(self):
         self.set_title()
@@ -631,7 +630,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
             return
 
     def _update_window_list(self):
-        self._propagation_keys.add("window_list")
+        self._propagation_keys |= Modules.WINDOW_LIST
 
     def _do_update_window_list(self):
         menu = self.findChild(QMenu, "menu_windows")
diff --git a/src/View/Tools/PamhyrWindow.py b/src/View/Tools/PamhyrWindow.py
index 7555d5fb..7e8a01df 100644
--- a/src/View/Tools/PamhyrWindow.py
+++ b/src/View/Tools/PamhyrWindow.py
@@ -26,6 +26,8 @@ from PyQt5.QtWidgets import (
     QUndoStack, QShortcut,
 )
 
+from Modules import Modules
+
 from View.Tools.ASubWindow import ASubMainWindow, ASubWindow
 from View.Tools.ListedSubWindow import ListedSubWindow
 
@@ -103,13 +105,13 @@ class PamhyrWindowTools(object):
         """
         self._set_title()
 
-    def _propagate_update(self, key=None):
+    def _propagate_update(self, key=Modules(0)):
         logger.debug(f"_propagate_update({key}) to {self._parent}")
         if self._parent is not None:
             self._parent._propagate_update(key=key)
 
-    def _propagated_update(self, key=None):
-        if key is None:
+    def _propagated_update(self, key=Modules(0)):
+        if key is Modules(0):
             return
 
         # Update ...
@@ -174,7 +176,7 @@ class PamhyrWindow(ASubMainWindow, ListedSubWindow, PamhyrWindowTools):
 
     def closeEvent(self, event):
         self._close_sub_window()
-        self._propagate_update("window_list")
+        self._propagate_update(Modules.WINDOW_LIST)
 
         super(PamhyrWindow, self).closeEvent(event)
 
diff --git a/src/View/Translate.py b/src/View/Translate.py
index bf94adcd..8ca10513 100644
--- a/src/View/Translate.py
+++ b/src/View/Translate.py
@@ -38,7 +38,7 @@ class CommonWordTranslate(PamhyrTranslate):
 
         self._dict["reach"] = _translate("CommonWord", "Reach")
         self._dict["reaches"] = _translate("CommonWord", "Reaches")
-        self._dict["cross_section"] = _translate("CommonWord", "Coss-section")
+        self._dict["cross_section"] = _translate("CommonWord", "Cross-section")
         self._dict["main_channel"] = _translate("CommonWord", "Main channel")
         self._dict["floodway"] = _translate("CommonWord", "Floodway")
 
@@ -76,7 +76,7 @@ class MainTranslate(UnitTranslate):
         super(MainTranslate, self).__init__()
 
         self._dict["tab_info_name"] = _translate(
-            "MainWindow", "Info"
+            "MainWindow", "Summary"
         )
 
         self._dict["open_debug"] = _translate(
-- 
GitLab