diff --git a/src/Model/River.py b/src/Model/River.py
index a4dd8fa54318371139a4d8f9cef965cd819902f9..d995d2c389b6133be698e826608acd800b9ffc5c 100644
--- a/src/Model/River.py
+++ b/src/Model/River.py
@@ -376,8 +376,8 @@ class River(Graph, SQLSubModel):
         return self._reservoir
 
     @property
-    def hydraulics_structures(self):
-        return self._hydraulics_structures
+    def hydraulic_structures(self):
+        return self._hydraulic_structures
 
     @property
     def parameters(self):
diff --git a/src/Solver/Mage.py b/src/Solver/Mage.py
index 80793357dbeef7df62ce600ec8f605f54b2e11f8..5dc5920754696588fc2a08ebae3474abaf771286 100644
--- a/src/Solver/Mage.py
+++ b/src/Solver/Mage.py
@@ -455,7 +455,7 @@ class Mage(CommandLineSolver):
                     reach_id = study.river.get_edge_id(hs.reach)
                     params = [p.value for p in hs.basic_hydraulic_structure.param]
                     param_str = ' '.join([f'{p.value:>10.3f}' for p in hs.basic_hydraulic_structure.param])
-                    f.write(f"{reach_id} {hs.kp:>12.3f} {params} {hs.name}\n")
+                    f.write(f"{hs.basic_hydraulic_structure.type} {reach_id} {hs.kp:>12.3f} {params} {hs.name}\n")
 
         return files
 
diff --git a/src/View/HydraulicStructures/BasicHydraulicStructures/Table.py b/src/View/HydraulicStructures/BasicHydraulicStructures/Table.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0522af555679571f817f2bad2e2fc925da874ba4 100644
--- a/src/View/HydraulicStructures/BasicHydraulicStructures/Table.py
+++ b/src/View/HydraulicStructures/BasicHydraulicStructures/Table.py
@@ -0,0 +1,20 @@
+# Table.py -- Pamhyr
+# Copyright (C) 2023  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
+import traceback
diff --git a/src/View/HydraulicStructures/BasicHydraulicStructures/Translate.py b/src/View/HydraulicStructures/BasicHydraulicStructures/Translate.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f2d74d02529c6ac24646c5f6e3219826385e7ee3 100644
--- a/src/View/HydraulicStructures/BasicHydraulicStructures/Translate.py
+++ b/src/View/HydraulicStructures/BasicHydraulicStructures/Translate.py
@@ -0,0 +1,23 @@
+# translate.py -- Pamhyr
+# Copyright (C) 2023  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 -*-
+
+from PyQt5.QtCore import QCoreApplication
+
+from View.Tools.PamhyrTranslate import PamhyrTranslate
+
+_translate = QCoreApplication.translate
diff --git a/src/View/HydraulicStructures/BasicHydraulicStructures/UndoCommand.py b/src/View/HydraulicStructures/BasicHydraulicStructures/UndoCommand.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ca18efaa83e126490b58714fbe6cf34775dfb5e9 100644
--- a/src/View/HydraulicStructures/BasicHydraulicStructures/UndoCommand.py
+++ b/src/View/HydraulicStructures/BasicHydraulicStructures/UndoCommand.py
@@ -0,0 +1,17 @@
+# UndoCommand.py -- Pamhyr
+# Copyright (C) 2023  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 -*-
diff --git a/src/View/HydraulicStructures/BasicHydraulicStructures/Window.py b/src/View/HydraulicStructures/BasicHydraulicStructures/Window.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..43e78cefde37ebc935e71267888843bc9eda55d8 100644
--- a/src/View/HydraulicStructures/BasicHydraulicStructures/Window.py
+++ b/src/View/HydraulicStructures/BasicHydraulicStructures/Window.py
@@ -0,0 +1,17 @@
+# Window.py -- Pamhyr
+# Copyright (C) 2023  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 -*-
diff --git a/src/View/HydraulicStructures/Table.py b/src/View/HydraulicStructures/Table.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..44e5d1690ea6bd5e44263c08d411274f36160dd8 100644
--- a/src/View/HydraulicStructures/Table.py
+++ b/src/View/HydraulicStructures/Table.py
@@ -0,0 +1,198 @@
+# Table.py -- Pamhyr
+# Copyright (C) 2023  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
+import traceback
+
+from tools import trace, timer
+
+from PyQt5.QtCore import (
+    Qt, QVariant, QAbstractTableModel,
+    QCoreApplication, QModelIndex, pyqtSlot,
+    QRect,
+)
+
+from PyQt5.QtWidgets import (
+    QDialogButtonBox, QPushButton, QLineEdit,
+    QFileDialog, QTableView, QAbstractItemView,
+    QUndoStack, QShortcut, QAction, QItemDelegate,
+    QComboBox,
+)
+
+from View.Tools.PamhyrTable import PamhyrTableModel
+
+from View.HydraulicStructures.UndoCommand import (
+    SetNameCommand, SetReachCommand, SetKpCommand,
+    AddCommand, DelCommand,
+)
+
+logger = logging.getLogger()
+
+_translate = QCoreApplication.translate
+
+
+class ComboBoxDelegate(QItemDelegate):
+    def __init__(self, data=None, trad=None, parent=None, mode="reaches"):
+        super(ComboBoxDelegate, self).__init__(parent)
+
+        self._data = data
+        self._trad = trad
+        self._mode = mode
+
+    def createEditor(self, parent, option, index):
+        self.editor = QComboBox(parent)
+
+        val = []
+        if self._mode == "kp":
+            reach = self._data.hydraulic_structures.get(index.row()).input_reach
+            if reach is not None:
+                val = list(
+                    map(
+                        lambda kp: str(kp), reach.reach.get_kp()
+                    )
+                )
+        else:
+            val = list(
+                map(
+                    lambda n: n.name, self._data.edges()
+                )
+            )
+
+        self.editor.addItems(
+            [_translate("Hydraulic structure", "Not associated")] +
+            val
+        )
+
+        self.editor.setCurrentText(index.data(Qt.DisplayRole))
+        return self.editor
+
+    def setEditorData(self, editor, index):
+        value = index.data(Qt.DisplayRole)
+        self.editor.currentTextChanged.connect(self.currentItemChanged)
+
+    def setModelData(self, editor, model, index):
+        text = str(editor.currentText())
+        model.setData(index, text)
+        editor.close()
+        editor.deleteLater()
+
+    def updateEditorGeometry(self, editor, option, index):
+        r = QRect(option.rect)
+        if self.editor.windowFlags() & Qt.Popup:
+            if editor.parent() is not None:
+                r.setTopLeft(self.editor.parent().mapToGlobal(r.topLeft()))
+        editor.setGeometry(r)
+
+    @pyqtSlot()
+    def currentItemChanged(self):
+        self.commitData.emit(self.sender())
+
+
+class TableModel(PamhyrTableModel):
+    def _setup_lst(self):
+        self._lst = self._data._hydraulic_structures
+
+    def rowCount(self, parent):
+        return len(self._lst)
+
+    def data(self, index, role):
+        if role != Qt.ItemDataRole.DisplayRole:
+            return QVariant()
+
+        row = index.row()
+        column = index.column()
+
+        if self._headers[column] == "name":
+            return self._lst.get(row).name
+        elif self._headers[column] == "reach":
+            n = self._lst.get(row).input_reach
+            if n is None:
+                return _translate("Hydraulic structure", "Not associated")
+            return n.name
+        elif self._headers[column] == "kp":
+            n = self._lst.get(row).input_kp
+            if n is None:
+                return _translate("Hydraulic structure", "Not associated")
+            return n
+
+        return QVariant()
+
+    def setData(self, index, value, role=Qt.EditRole):
+        if not index.isValid() or role != Qt.EditRole:
+            return False
+
+        row = index.row()
+        column = index.column()
+
+        try:
+            if self._headers[column] == "name":
+                self._undo.push(
+                    SetNameCommand(
+                        self._lst, row, value
+                    )
+                )
+            elif self._headers[column] == "reach":
+                self._undo.push(
+                    SetReachCommand(
+                        self._lst, row, self._data.edge(value)
+                    )
+                )
+            elif self._headers[column] == "kp":
+                self._undo.push(
+                    SetKpCommand(
+                        self._lst, row, value
+                    )
+                )
+        except Exception as e:
+            logger.info(e)
+            logger.debug(traceback.format_exc())
+
+        self.dataChanged.emit(index, index)
+        return True
+
+    def add(self, row, parent=QModelIndex()):
+        self.beginInsertRows(parent, row, row - 1)
+
+        self._undo.push(
+            AddCommand(
+                self._lst, row
+            )
+        )
+
+        self.endInsertRows()
+        self.layoutChanged.emit()
+
+    def delete(self, rows, parent=QModelIndex()):
+        self.beginRemoveRows(parent, rows[0], rows[-1])
+
+        self._undo.push(
+            DelCommand(
+                self._lst, rows
+            )
+        )
+
+        self.endRemoveRows()
+        self.layoutChanged.emit()
+
+    def undo(self):
+        self._undo.undo()
+        self.layoutChanged.emit()
+
+    def redo(self):
+        self._undo.redo()
+        self.layoutChanged.emit()
diff --git a/src/View/HydraulicStructures/Translate.py b/src/View/HydraulicStructures/Translate.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1db3faeca39e54c5d391af1f631598809e3c3d52 100644
--- a/src/View/HydraulicStructures/Translate.py
+++ b/src/View/HydraulicStructures/Translate.py
@@ -0,0 +1,34 @@
+# translate.py -- Pamhyr
+# Copyright (C) 2023  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 -*-
+
+from PyQt5.QtCore import QCoreApplication
+
+from View.Tools.PamhyrTranslate import PamhyrTranslate
+
+_translate = QCoreApplication.translate
+
+
+class HydraulicStructuresTranslate(PamhyrTranslate):
+    def __init__(self):
+        super(HydraulicStructuresTranslate, self).__init__()
+
+        self._sub_dict["table_headers"] = {
+            "name": _translate("HydraulicStructures", "Name"),
+            "reach": _translate("HydraulicStructures", "Reach"),
+            "kp": _translate("HydraulicStructures", "Kp"),
+        }
diff --git a/src/View/HydraulicStructures/UndoCommand.py b/src/View/HydraulicStructures/UndoCommand.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c1a53f0dfe36821e7311600429993d62e63733e7 100644
--- a/src/View/HydraulicStructures/UndoCommand.py
+++ b/src/View/HydraulicStructures/UndoCommand.py
@@ -0,0 +1,139 @@
+# UndoCommand.py -- Pamhyr
+# Copyright (C) 2023  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 -*-
+
+from copy import deepcopy
+from tools import trace, timer
+
+from PyQt5.QtWidgets import (
+    QMessageBox, QUndoCommand, QUndoStack,
+)
+
+
+class SetNameCommand(QUndoCommand):
+    def __init__(self, h_s_lst, index, new_value):
+        QUndoCommand.__init__(self)
+
+        self._h_s_lst = h_s_lst
+        self._index = index
+        self._old = self._h_s_lst.get(self._index).name
+        self._new = str(new_value)
+
+    def undo(self):
+        self._h_s_lst.get(self._index).name = self._old
+
+    def redo(self):
+        self._h_s_lst.get(self._index).name = self._new
+
+
+class SetReachCommand(QUndoCommand):
+    def __init__(self, h_s_lst, index, reach):
+        QUndoCommand.__init__(self)
+
+        self._h_s_lst = h_s_lst
+        self._index = index
+        self._old = self._h_s_lst.get(self._index).input_reach
+        self._new = reach
+        self._old_kp = self._h_s_lst.get(self._index).input_kp
+        self._new_kp = None
+
+    def undo(self):
+        i = self._h_s_lst.get(self._index)
+        i.input_reach = self._old
+        i.input_kp = self._old_kp
+
+    def redo(self):
+        i = self._h_s_lst.get(self._index)
+        i.input_reach = self._new
+        i.input_kp = self._new_kp
+
+
+class SetKpCommand(QUndoCommand):
+    def __init__(self, h_s_lst, index, kp):
+        QUndoCommand.__init__(self)
+
+        self._h_s_lst = h_s_lst
+        self._index = index
+        self._old = self._h_s_lst.get(self._index).input_kp
+        self._new = kp
+
+    def undo(self):
+        self._h_s_lst.get(self._index).input_kp = self._old
+
+    def redo(self):
+        self._h_s_lst.get(self._index).input_kp = self._new
+
+
+class AddCommand(QUndoCommand):
+    def __init__(self, h_s_lst, index):
+        QUndoCommand.__init__(self)
+
+        self._h_s_lst = h_s_lst
+
+        self._index = index
+        self._new = None
+
+    def undo(self):
+        self._h_s_lst.delete_i([self._index])
+
+    def redo(self):
+        if self._new is None:
+            self._new = self._h_s_lst.new(self._h_s_lst, self._index)
+        else:
+            self._h_s_lst.insert(self._index, self._new)
+
+
+class DelCommand(QUndoCommand):
+    def __init__(self, h_s_lst, rows):
+        QUndoCommand.__init__(self)
+
+        self._h_s_lst = h_s_lst
+
+        self._rows = rows
+
+        self._h_s = []
+        for row in rows:
+            self._h_s.append((row, self._h_s_lst.get(row)))
+        self._h_s.sort()
+
+    def undo(self):
+        for row, el in self._h_s:
+            self._h_s_lst.insert(row, el)
+
+    def redo(self):
+        self._h_s_lst.delete_i(self._rows)
+
+
+class PasteCommand(QUndoCommand):
+    def __init__(self, h_s_lst, row, h_s):
+        QUndoCommand.__init__(self)
+
+        self._h_s_lst = h_s_lst
+
+        self._row = row
+        self._h_s = deepcopy(h_s)
+        self._h_s.reverse()
+
+    def undo(self):
+        self._h_s_lst.delete_i(
+            self._tab,
+            range(self._row, self._row + len(self._h_s))
+        )
+
+    def redo(self):
+        for r in self._h_s:
+            self._h_s_lst.insert(self._row, r)
diff --git a/src/View/HydraulicStructures/Window.py b/src/View/HydraulicStructures/Window.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0620d4a4715c415cd14e7b045e560b40b66e07d2 100644
--- a/src/View/HydraulicStructures/Window.py
+++ b/src/View/HydraulicStructures/Window.py
@@ -0,0 +1,208 @@
+# Window.py -- Pamhyr
+# Copyright (C) 2023  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 timer, trace
+
+from View.Tools.PamhyrWindow import PamhyrWindow
+
+from PyQt5 import QtCore
+from PyQt5.QtCore import (
+    Qt, QVariant, QAbstractTableModel, QCoreApplication,
+    pyqtSlot, pyqtSignal, QItemSelectionModel,
+)
+
+from PyQt5.QtWidgets import (
+    QDialogButtonBox, QPushButton, QLineEdit,
+    QFileDialog, QTableView, QAbstractItemView,
+    QUndoStack, QShortcut, QAction, QItemDelegate,
+    QHeaderView, QDoubleSpinBox, QVBoxLayout, QCheckBox
+)
+
+from View.HydraulicStructures.Table import (
+    TableModel, ComboBoxDelegate
+)
+
+from View.Network.GraphWidget import GraphWidget
+from View.HydraulicStructures.Translate import HydraulicStructuresTranslate
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+
+class HydraulicStructuresWindow(PamhyrWindow):
+    _pamhyr_ui = "HydraulicStructures"
+    _pamhyr_name = "Hydraulic Structures"
+
+    def __init__(self, study=None, config=None, parent=None):
+        name = self._pamhyr_name + " - " + study.name
+
+        super(HydraulicStructuresWindow, self).__init__(
+            title=name,
+            study=study,
+            config=config,
+            trad=HydraulicStructuresTranslate(),
+            parent=parent
+        )
+
+        self._hs_lst = self._study.river._hydraulic_structures
+
+        self.setup_table()
+        self.setup_checkbox()
+        self.setup_plots()
+        self.setup_connections()
+
+    def setup_table(self):
+        self._table = None
+
+        self._delegate_reach = ComboBoxDelegate(
+            trad=self._trad,
+            data=self._study.river,
+            parent=self,
+            mode = "reaches"
+        )
+        self._delegate_kp = ComboBoxDelegate(
+            trad=self._trad,
+            data=self._study.river,
+            parent=self,
+            mode = "kp"
+        )
+
+        table = self.find(QTableView, f"tableView")
+        self._table = TableModel(
+            table_view=table,
+            table_headers=self._trad.get_dict("table_headers"),
+            editable_headers=["name", "reach", "kp"],
+            delegates={
+                "reach": self._delegate_reach,
+                "kp": self._delegate_kp,
+            },
+            trad=self._trad,
+            data=self._study.river,
+            undo=self._undo_stack,
+        )
+
+        selectionModel = table.selectionModel()
+        index = table.model().index(0, 0)
+
+        selectionModel.select(
+            index,
+            QItemSelectionModel.Rows |
+            QItemSelectionModel.ClearAndSelect |
+            QItemSelectionModel.Select
+        )
+        table.scrollTo(index)
+
+    def setup_checkbox(self):
+        self._checkbox = self.find(QCheckBox, f"checkBox")
+        self._set_checkbox_state
+
+    def setup_plots(self):
+        return
+
+    def setup_connections(self):
+        self.find(QAction, "action_add").triggered.connect(self.add)
+        self.find(QAction, "action_delete").triggered.connect(self.delete)
+        self.find(QAction, "action_edit").triggered.connect(self.edit)
+        self._checkbox.stateChanged.connect(self._set_structure_state)
+
+        table = self.find(QTableView, "tableView")
+        table.selectionModel()\
+                 .selectionChanged\
+                 .connect(self._set_checkbox_state)
+
+    def index_selected_row(self):
+        table = self.find(QTableView, "tableView")
+        r = table.selectionModel()\
+                    .selectedRows()
+        if len(r)>0:
+            return r[0].row()
+        else:
+            return None
+
+    def index_selected_rows(self):
+        table = self.find(QTableView, "tableView")
+        return list(
+            # Delete duplicate
+            set(
+                map(
+                    lambda i: i.row(),
+                    table.selectedIndexes()
+                )
+            )
+        )
+
+    def add(self):
+        rows = self.index_selected_rows()
+        if len(self._hs_lst) == 0 or len(rows) == 0:
+            self._table.add(0)
+        else:
+            self._table.add(rows[0])
+
+    def delete(self):
+        rows = self.index_selected_rows()
+        if len(rows) == 0:
+            return
+
+        self._table.delete(rows)
+
+    def _copy(self):
+        logger.info("TODO: copy")
+
+    def _paste(self):
+        logger.info("TODO: paste")
+
+    def _undo(self):
+        self._table.undo()
+
+    def _redo(self):
+        self._table.redo()
+
+    def edit(self):
+        rows = self.index_selected_rows()
+        for row in rows:
+            data = self._hs_lst.get(row)
+
+            if self.sub_window_exists(
+                BasicHydraulicStructuresWindow,
+                data=[self._study, None, data]
+            ):
+                continue
+
+            win = BasicHydraulicStructuresWindow(
+                data=data,
+                study=self._study,
+                parent=self
+            )
+            win.show()
+
+    def _set_checkbox_state(self):
+        row = self.index_selected_row()
+        if row is None:
+            self._checkbox.setEnabled(False)
+            self._checkbox.setChecked(True)
+        else:
+            self._checkbox.setEnabled(True)
+            self._checkbox.setChecked(self._hs_lst.get(row).enabled)
+
+    def _set_structure_state(self):
+        row = self.index_selected_row()
+        #self._checkbox.setChecked(self._hs_lst.get(row).enabled)
+        self._hs_lst.get(row).enabled = self._checkbox.isChecked()
diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py
index 04ed5f94267aad9aad4e2419b6aea1fab59b47f1..a9d98062dbab2b1e1aa5091477bb00b6af6cf0c5 100644
--- a/src/View/MainWindow.py
+++ b/src/View/MainWindow.py
@@ -48,6 +48,7 @@ from View.Network.Window import NetworkWindow
 from View.Geometry.Window import GeometryWindow
 from View.BoundaryCondition.Window import BoundaryConditionWindow
 from View.Reservoir.Window import ReservoirWindow
+from View.HydraulicStructures.Window import HydraulicStructuresWindow
 from View.LateralContribution.Window import LateralContributionWindow
 from View.InitialConditions.Window import InitialConditionsWindow
 from View.Stricklers.Window import StricklersWindow
@@ -102,7 +103,8 @@ define_model_action = [
     "action_menu_boundary_conditions", "action_menu_initial_conditions",
     "action_menu_edit_friction", "action_menu_edit_lateral_contribution",
     "action_menu_run_solver", "action_menu_sediment_layers",
-    "action_menu_edit_reach_sediment_layers", "action_menu_edit_reservoirs"
+    "action_menu_edit_reach_sediment_layers", "action_menu_edit_reservoirs",
+    "action_menu_edit_hydraulic_structures"
 ]
 
 action = (
@@ -193,6 +195,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
             "action_menu_edit_geometry": self.open_geometry,
             "action_menu_boundary_conditions": self.open_boundary_cond,
             "action_menu_edit_reservoirs": self.open_reservoir,
+            "action_menu_edit_hydraulic_structures": self.open_hydraulic_structures,
             "action_menu_initial_conditions": self.open_initial_conditions,
             "action_menu_edit_friction": self.open_frictions,
             "action_menu_edit_lateral_contribution": self.open_lateral_contrib,
@@ -628,6 +631,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
         reservoir = ReservoirWindow(study=self._study, parent=self)
         reservoir.show()
 
+    def open_hydraulic_structures(self):
+        if self.sub_window_exists(
+            HydraulicStructuresWindow,
+            data=[self._study, None]
+        ):
+            return
+
+        hydraulic_structures = HydraulicStructuresWindow(study=self._study, parent=self)
+        hydraulic_structures.show()
+
     def open_lateral_contrib(self):
         if self.sub_window_exists(
             LateralContributionWindow,
diff --git a/src/View/ui/BasicHydraulicStructures.ui b/src/View/ui/BasicHydraulicStructures.ui
index 28ffae5448207582664bfadee6530cc36082f7fa..add59b7c8c5d4de7cdde19a8eaec49f1789c0e3a 100644
--- a/src/View/ui/BasicHydraulicStructures.ui
+++ b/src/View/ui/BasicHydraulicStructures.ui
@@ -40,6 +40,9 @@
         </item>
         <item>
          <layout class="QHBoxLayout" name="horizontalLayout">
+          <property name="leftMargin">
+           <number>5</number>
+          </property>
           <item>
            <widget class="QCheckBox" name="checkBox">
             <property name="text">
diff --git a/src/View/ui/HydraulicStructures.ui b/src/View/ui/HydraulicStructures.ui
index 0464f0180be53ebb86170ac78b2b778a8a715482..813da5b5f48ef45a2e14e4c473eb3263ed35f1b4 100644
--- a/src/View/ui/HydraulicStructures.ui
+++ b/src/View/ui/HydraulicStructures.ui
@@ -40,6 +40,9 @@
         </item>
         <item>
          <layout class="QHBoxLayout" name="horizontalLayout">
+          <property name="leftMargin">
+           <number>5</number>
+          </property>
           <item>
            <widget class="QCheckBox" name="checkBox">
             <property name="text">
diff --git a/src/View/ui/MainWindow.ui b/src/View/ui/MainWindow.ui
index e4d00954ccfff566746cfb1c98d94be09c52d6b1..bf73c3d3cb232511420f01a2fd72ad73438b235e 100644
--- a/src/View/ui/MainWindow.ui
+++ b/src/View/ui/MainWindow.ui
@@ -132,6 +132,7 @@
     <addaction name="action_menu_edit_friction"/>
     <addaction name="action_menu_edit_lateral_contribution"/>
     <addaction name="action_menu_edit_reservoirs"/>
+    <addaction name="action_menu_edit_hydraulic_structures"/>
    </widget>
    <widget class="QMenu" name="menu_results">
     <property name="title">
@@ -934,6 +935,14 @@
     <string>Edit reservoirs</string>
    </property>
   </action>
+  <action name="action_menu_edit_hydraulic_structures">
+   <property name="text">
+    <string>Hydraulic structures</string>
+   </property>
+   <property name="toolTip">
+    <string>Edit hydraulic structures</string>
+   </property>
+  </action>
  </widget>
  <resources/>
  <connections>