From 07cefceed8b3faa603ac437c374f192cb9aaed35 Mon Sep 17 00:00:00 2001
From: Pierre-Antoine Rouby <pierre-antoine.rouby@inrae.fr>
Date: Wed, 28 Feb 2024 15:40:57 +0100
Subject: [PATCH] Network: Add reservoir shortcut at network edit.

---
 src/Model/Network/Graph.py           |  6 +++++
 src/Model/Tools/PamhyrList.py        |  3 +++
 src/View/Network/ContextMenu.py      | 28 +++++++++++++++++--
 src/View/Network/GraphWidget.py      | 13 +++++++--
 src/View/Network/Window.py           | 40 +++++++++++++++++++++++++++-
 src/View/Network/translate.py        |  9 +++++++
 src/View/Reservoir/Edit/Plot.py      |  2 +-
 src/View/Reservoir/Edit/Translate.py |  2 +-
 src/View/Reservoir/UndoCommand.py    | 22 +++++++++++++++
 src/View/Translate.py                |  2 +-
 10 files changed, 119 insertions(+), 8 deletions(-)

diff --git a/src/Model/Network/Graph.py b/src/Model/Network/Graph.py
index 4b154840..df48f03d 100644
--- a/src/Model/Network/Graph.py
+++ b/src/Model/Network/Graph.py
@@ -220,6 +220,12 @@ class Graph(object):
             True
         )
 
+    def is_internal_node(self, node):
+        return not (
+            self.is_upstream_node(node) or
+            self.is_downstream_node(node)
+        )
+
     def is_enable_node(self, node):
         return reduce(
             lambda acc, e: (
diff --git a/src/Model/Tools/PamhyrList.py b/src/Model/Tools/PamhyrList.py
index 4ae98dee..024273cd 100644
--- a/src/Model/Tools/PamhyrList.py
+++ b/src/Model/Tools/PamhyrList.py
@@ -67,6 +67,9 @@ class PamhyrModelList(SQLSubModel):
     def __len__(self):
         return len(self.lst)
 
+    def index(self, el):
+        return self._lst.index(el)
+
     def get(self, row):
         return self._lst[row]
 
diff --git a/src/View/Network/ContextMenu.py b/src/View/Network/ContextMenu.py
index 4e29fefe..f7ad10a9 100644
--- a/src/View/Network/ContextMenu.py
+++ b/src/View/Network/ContextMenu.py
@@ -23,7 +23,7 @@ from PyQt5.QtWidgets import (
 
 class AbstractMenu(object):
     def __init__(self, event=None, pos=None, items=[],
-                 trad=None, parent=None):
+                 graph=None, trad=None, parent=None):
         super(AbstractMenu, self).__init__()
 
         self._menu = QMenu(parent)
@@ -31,6 +31,7 @@ class AbstractMenu(object):
         self._pos = pos
         self._items = items
 
+        self._graph = graph
         self._trad = trad
         self._parent = parent
 
@@ -55,11 +56,34 @@ class DefaultMenu(AbstractMenu):
 
 class NodeMenu(AbstractMenu):
     def run(self):
+        item = self._items[0]
+        node = item.node
+
         delete = self._menu.addAction(self._trad["menu_del_node"])
 
+        is_internal = self._graph.is_internal_node(node)
+        if is_internal:
+            res = self._graph.reservoir.get_assoc_to_node(node)
+            if res is not None:
+                edt_res = self._menu.addAction(self._trad["menu_edit_res_node"])
+                del_res = self._menu.addAction(self._trad["menu_del_res_node"])
+                res_edit = True
+            else:
+                add_res = self._menu.addAction(self._trad["menu_add_res_node"])
+                res_edit = False
+
         action = self._exec()
         if action == delete:
-            self._parent.del_node(self._items[0])
+            self._parent.del_node(item)
+        elif is_internal:
+            if res_edit:
+                if action == edt_res:
+                    self._parent.edit_node_reservoir(node)
+                elif action == del_res:
+                    self._parent.del_node_reservoir(node)
+            else:
+                if action == add_res:
+                    self._parent.add_node_reservoir(node)
 
 
 class EdgeMenu(AbstractMenu):
diff --git a/src/View/Network/GraphWidget.py b/src/View/Network/GraphWidget.py
index b3e321cd..3fbc96d9 100644
--- a/src/View/Network/GraphWidget.py
+++ b/src/View/Network/GraphWidget.py
@@ -454,6 +454,15 @@ class GraphWidget(QGraphicsView):
             if type(i) is NodeItem:
                 self.texts[i].rename()
 
+    def add_node_reservoir(self, node):
+        self.parent.add_node_reservoir(node)
+
+    def del_node_reservoir(self, node):
+        self.parent.del_node_reservoir(node)
+
+    def edit_node_reservoir(self, node):
+        self.parent.edit_node_reservoir(node)
+
     def enable_edge(self, edge, prev):
         self._undo.push(
             EnableEdgeCommand(
@@ -487,7 +496,7 @@ class GraphWidget(QGraphicsView):
 
         Args:
             node1: The source node
-            node2: The destination node
+            node2: The desitnation node
 
         Returns:
             Nothing
@@ -836,6 +845,6 @@ class GraphWidget(QGraphicsView):
         # Create and exec menu
         m = m_type(
             event=event, pos=pos, items=items,
-            trad=self._trad, parent=self
+            graph=self.graph, trad=self._trad, parent=self
         )
         m.run()
diff --git a/src/View/Network/Window.py b/src/View/Network/Window.py
index 18763bc6..bd0daee4 100644
--- a/src/View/Network/Window.py
+++ b/src/View/Network/Window.py
@@ -46,6 +46,11 @@ from View.Network.Table import (
     ComboBoxDelegate, NodeTableModel, EdgeTableModel,
 )
 
+# Reservoir short cut
+from View.Reservoir.Edit.Window import EditReservoirWindow
+import View.Reservoir.UndoCommand as ResUndoCommand
+
+
 logger = logging.getLogger()
 
 _translate = QCoreApplication.translate
@@ -69,6 +74,7 @@ class NetworkWindow(PamhyrWindow):
         )
 
         self._graph = study.river
+        self._reservoir = study.river.reservoir
         self._table_headers_node = self._trad.get_dict("table_headers_node")
         self._table_headers_edge = self._trad.get_dict("table_headers_edge")
 
@@ -162,7 +168,39 @@ class NetworkWindow(PamhyrWindow):
         if key == Qt.Key_Escape:
             self._graph_widget.reset_selection
 
-    # Redefine undo/redo method
+    def add_node_reservoir(self, node):
+        if self._reservoir.get_assoc_to_node(node) is None:
+            self._undo_stack.push(
+                ResUndoCommand.AddAndAssociateCommand(
+                    self._reservoir, 0, node
+                )
+            )
+
+    def del_node_reservoir(self, node):
+        res = self._reservoir.get_assoc_to_node(node)
+        ind = self._reservoir.index(res)
+
+        self._undo_stack.push(
+            ResUndoCommand.DelCommand(
+                self._reservoir, [ind]
+            )
+        )
+
+    def edit_node_reservoir(self, node):
+        data = self._reservoir.get_assoc_to_node(node)
+
+        if self.sub_window_exists(
+            EditReservoirWindow,
+            data=[self._study, None, data]
+        ):
+            return
+
+        win = EditReservoirWindow(
+            data=data,
+            study=self._study,
+            parent=self
+        )
+        win.show()
 
     def _undo(self):
         self._undo_stack.undo()
diff --git a/src/View/Network/translate.py b/src/View/Network/translate.py
index ff5440b8..200af192 100644
--- a/src/View/Network/translate.py
+++ b/src/View/Network/translate.py
@@ -33,6 +33,15 @@ class NetworkTranslate(MainTranslate):
 
         self._dict["menu_add_node"] = _translate("Network", "Add node")
         self._dict["menu_del_node"] = _translate("Network", "Delete the node")
+        self._dict["menu_edit_res_node"] = _translate(
+            "Network", "Edit node reservoir"
+        )
+        self._dict["menu_add_res_node"] = _translate(
+            "Network", "Add node reservoir"
+        )
+        self._dict["menu_del_res_node"] = _translate(
+            "Network", "Delete node reservoir"
+        )
 
         self._dict["menu_del_edge"] = _translate("Network", "Delete the reach")
         self._dict["menu_ena_edge"] = _translate("Network", "Enable the reach")
diff --git a/src/View/Reservoir/Edit/Plot.py b/src/View/Reservoir/Edit/Plot.py
index 9de7d4a1..ac1859a1 100644
--- a/src/View/Reservoir/Edit/Plot.py
+++ b/src/View/Reservoir/Edit/Plot.py
@@ -50,7 +50,7 @@ class Plot(PamhyrPlot):
         self._table_headers = self._trad.get_dict("table_headers")
 
         self.label_x = self._table_headers["z"]
-        self.label_y = self._table_headers["Area"]
+        self.label_y = self._table_headers["area"]
 
         self._isometric_axis = False
 
diff --git a/src/View/Reservoir/Edit/Translate.py b/src/View/Reservoir/Edit/Translate.py
index 657cad0d..e90da571 100644
--- a/src/View/Reservoir/Edit/Translate.py
+++ b/src/View/Reservoir/Edit/Translate.py
@@ -35,5 +35,5 @@ class EditReservoirTranslate(ReservoirTranslate):
 
         self._sub_dict["table_headers"] = {
             "z": self._dict["unit_elevation"],
-            "Area": self._dict["unit_area"],
+            "area": self._dict["unit_area"],
         }
diff --git a/src/View/Reservoir/UndoCommand.py b/src/View/Reservoir/UndoCommand.py
index 4544b4ba..ef7b2dc4 100644
--- a/src/View/Reservoir/UndoCommand.py
+++ b/src/View/Reservoir/UndoCommand.py
@@ -85,6 +85,28 @@ class AddCommand(QUndoCommand):
             self._reservoir_lst.insert(self._index, self._new)
 
 
+class AddAndAssociateCommand(QUndoCommand):
+    def __init__(self, reservoir_lst, index, node):
+        QUndoCommand.__init__(self)
+
+        self._reservoir_lst = reservoir_lst
+
+        self._new = None
+        self._index = index
+        self._node = node
+
+    def undo(self):
+        self._reservoir_lst.delete_i([self._index])
+
+    def redo(self):
+        if self._new is None:
+            self._new = self._reservoir_lst.new(self._index)
+        else:
+            self._reservoir_lst.insert(self._index, self._new)
+
+        self._reservoir_lst.get(self._index).node = self._node
+
+
 class DelCommand(QUndoCommand):
     def __init__(self, reservoir_lst, rows):
         QUndoCommand.__init__(self)
diff --git a/src/View/Translate.py b/src/View/Translate.py
index bbebaf5f..bf94adcd 100644
--- a/src/View/Translate.py
+++ b/src/View/Translate.py
@@ -62,7 +62,7 @@ class UnitTranslate(CommonWordTranslate):
             "Unit", "Water elevation (m)"
         )
         self._dict["unit_discharge"] = _translate("Unit", "Discharge (m³/s)")
-        self._dict["unit_area"] = _translate("Unit", "Area (hectare)"),
+        self._dict["unit_area"] = _translate("Unit", "Area (hectare)")
 
         self._dict["unit_time_s"] = _translate("Unit", "Time (sec)")
         self._dict["unit_time_p"] = _translate("Unit", "Time (JJJ:HH:MM:SS)")
-- 
GitLab