diff --git a/src/Model/River.py b/src/Model/River.py
index a19e6cc3..a46661f4 100644
--- a/src/Model/River.py
+++ b/src/Model/River.py
@@ -15,6 +15,7 @@ from Model.InitialConditions.InitialConditionsDict import InitialConditionsDict
from Model.Stricklers.StricklersList import StricklersList
from Model.Friction.FrictionList import FrictionList
from Model.SolverParameters.SolverParametersList import SolverParametersList
+from Model.SedimentLayer.SedimentLayerList import SedimentLayerList
from Solver.Solvers import solver_type_list
@@ -192,6 +193,7 @@ class River(Graph, SQLSubModel):
InitialConditionsDict,
StricklersList,
SolverParametersList,
+ SedimentLayerList,
]
def __init__(self, status=None):
@@ -207,6 +209,7 @@ class River(Graph, SQLSubModel):
self._initial_conditions = InitialConditionsDict(status=self._status)
self._stricklers = StricklersList(status=self._status)
self._parameters = {}
+ self._sediment_layers = SedimentLayerList()
@classmethod
def _sql_create(cls, execute):
@@ -301,6 +304,10 @@ class River(Graph, SQLSubModel):
def initial_conditions(self):
return self._initial_conditions
+ @property
+ def sediment_layers(self):
+ return self._sediment_layers
+
@property
def stricklers(self):
return self._stricklers
diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py
index 10a35a6e..79c7ef67 100644
--- a/src/View/MainWindow.py
+++ b/src/View/MainWindow.py
@@ -33,6 +33,7 @@ from View.LateralContribution.Window import LateralContributionWindow
from View.InitialConditions.Window import InitialConditionsWindow
from View.Stricklers.Window import StricklersWindow
from View.Frictions.Window import FrictionsWindow
+from View.SedimentLayers.Window import SedimentLayersWindow
from View.SolverParameters.Window import SolverParametersWindow
from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow
from View.CheckList.Window import CheckListWindow
@@ -70,7 +71,8 @@ define_model_action = [
"action_menu_edit_network", "action_menu_edit_geometry",
"action_menu_boundary_conditions", "action_menu_initial_conditions",
"action_menu_edit_friction", "action_menu_edit_lateral_contribution",
- "action_menu_run_solver",
+ "action_menu_run_solver", "action_menu_sediment_layers",
+ "action_menu_edit_reach_sediment_layers"
]
action = (
@@ -147,6 +149,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
"action_menu_edit_friction": self.open_frictions,
"action_menu_edit_lateral_contribution": self.open_lateral_contrib,
"action_menu_run_solver": self.run_solver,
+ "action_menu_sediment_layers": self.open_sediment_layer,
## Help
"action_menu_about": self.open_about,
# ToolBar action
@@ -490,6 +493,13 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
)
params.show()
+ def open_sediment_layer(self):
+ sl = SedimentLayersWindow(
+ study = self.model,
+ parent = self
+ )
+ sl.show()
+
def run_solver(self):
if self.model is None:
return
diff --git a/src/View/SedimentLayers/Edit/Table.py b/src/View/SedimentLayers/Edit/Table.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/View/SedimentLayers/Edit/UndoCommand.py b/src/View/SedimentLayers/Edit/UndoCommand.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/View/SedimentLayers/Edit/Window.py b/src/View/SedimentLayers/Edit/Window.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/View/SedimentLayers/Edit/translate.py b/src/View/SedimentLayers/Edit/translate.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/View/SedimentLayers/Reach/Profile/Table.py b/src/View/SedimentLayers/Reach/Profile/Table.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/View/SedimentLayers/Reach/Profile/UndoCommand.py b/src/View/SedimentLayers/Reach/Profile/UndoCommand.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/View/SedimentLayers/Reach/Profile/Window.py b/src/View/SedimentLayers/Reach/Profile/Window.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/View/SedimentLayers/Reach/Profile/translate.py b/src/View/SedimentLayers/Reach/Profile/translate.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/View/SedimentLayers/Reach/Table.py b/src/View/SedimentLayers/Reach/Table.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/View/SedimentLayers/Reach/UndoCommand.py b/src/View/SedimentLayers/Reach/UndoCommand.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/View/SedimentLayers/Reach/Window.py b/src/View/SedimentLayers/Reach/Window.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/View/SedimentLayers/Reach/translate.py b/src/View/SedimentLayers/Reach/translate.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/View/SedimentLayers/Table.py b/src/View/SedimentLayers/Table.py
new file mode 100644
index 00000000..7abbd869
--- /dev/null
+++ b/src/View/SedimentLayers/Table.py
@@ -0,0 +1,151 @@
+# -*- coding: utf-8 -*-
+
+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.SedimentLayers.UndoCommand import *
+from View.SedimentLayers.translate import *
+
+_translate = QCoreApplication.translate
+
+
+class TableModel(QAbstractTableModel):
+ def __init__(self, study=None, undo=None):
+ super(QAbstractTableModel, self).__init__()
+ self._headers = list(table_headers.keys())
+ self._study = study
+ self._undo = undo
+ self._sl = self._study.river.sediment_layers
+
+ def flags(self, index):
+ options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
+ options |= Qt.ItemIsEditable
+
+ return options
+
+ def rowCount(self, parent):
+ return len(self._sl)
+
+ def columnCount(self, parent):
+ return len(self._headers)
+
+ 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._sl.get(row).name
+ elif self._headers[column] == "comment":
+ return self._sl.get(row).name
+
+ return QVariant()
+
+ def headerData(self, friction, orientation, role):
+ if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
+ return table_headers[self._headers[friction]]
+
+ 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()
+
+ if self._headers[column] == "name":
+ self._undo.push(
+ SetNameCommand(
+ self._sl, row, value
+ )
+ )
+ if self._headers[column] == "comment":
+ self._undo.push(
+ SetCommentCommand(
+ self._sl, row, value
+ )
+ )
+
+ self.dataChanged.emit(index, index)
+ return True
+
+ def add(self, row, parent=QModelIndex()):
+ self.beginInsertRows(parent, row, row - 1)
+
+ self._undo.push(
+ AddCommand(
+ self._sl, row, self._data
+ )
+ )
+
+ self.endInsertRows()
+ self.layoutChanged.emit()
+
+ def delete(self, rows, parent=QModelIndex()):
+ self.beginRemoveRows(parent, rows[0], rows[-1])
+
+ self._undo.push(
+ DelCommand(
+ self._sl, rows
+ )
+ )
+
+ self.endRemoveRows()
+ self.layoutChanged.emit()
+
+ def move_up(self, row, parent=QModelIndex()):
+ if row <= 0:
+ return
+
+ target = row + 2
+
+ self.beginMoveRows(parent, row - 1, row - 1, parent, target)
+
+ self._undo_stack.push(
+ MoveCommand(
+ self._sl, "up", row
+ )
+ )
+
+ self.endMoveRows()
+ self.layoutChanged.emit()
+
+ def move_down(self, index, parent=QModelIndex()):
+ if row > len(self._sl):
+ return
+
+ target = row
+
+ self.beginMoveRows(parent, row + 1, row + 1, parent, target)
+
+ self._undo_stack.push(
+ MoveCommand(
+ self._sl, "down", row
+ )
+ )
+
+ self.endMoveRows()
+ 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/SedimentLayers/UndoCommand.py b/src/View/SedimentLayers/UndoCommand.py
new file mode 100644
index 00000000..84c4027b
--- /dev/null
+++ b/src/View/SedimentLayers/UndoCommand.py
@@ -0,0 +1,97 @@
+# -*- coding: utf-8 -*-
+
+from copy import deepcopy
+from tools import trace, timer
+
+from PyQt5.QtWidgets import (
+ QMessageBox, QUndoCommand, QUndoStack,
+)
+
+from Model.SedimentLayer.SedimentLayer import SedimentLayer
+from Model.SedimentLayer.SedimentLayerList import SedimentLayerList
+
+class SetNameCommand(QUndoCommand):
+ def __init__(self, sediment_layers_list, index, new_value):
+ QUndoCommand.__init__(self)
+
+ self._sediment_layers_list = sediment_layers_list
+ self._index = index
+ self._old = self._sediment_layers_list.get(self._index).name
+ self._new = new_value
+
+ def undo(self):
+ self._sediment_layers_list.get(self._index).name = self._old
+
+ def redo(self):
+ self._sediment_layers_list.get(self._index).name = self._new
+
+class SetCommentCommand(QUndoCommand):
+ def __init__(self, sediment_layers_list, index, new_value):
+ QUndoCommand.__init__(self)
+
+ self._sediment_layers_list = sediment_layers_list
+ self._index = index
+ self._old = self._sediment_layers_list.get(self._index).comment
+ self._new = new_value
+
+ def undo(self):
+ self._sediment_layers_list.get(self._index).comment = self._old
+
+ def redo(self):
+ self._sediment_layers_list.get(self._index).comment = self._new
+
+class AddCommand(QUndoCommand):
+ def __init__(self, sediment_layers_list, index, reach):
+ QUndoCommand.__init__(self)
+
+ self._sediment_layers_list = sediment_layers_list
+ self._index = index
+ self._new = None
+
+ def undo(self):
+ self._sediment_layers_list.delete_i([self._index])
+
+ def redo(self):
+ if self._new is None:
+ self._new = self._sediment_layers_list.new(self._index)
+ else:
+ self._sediment_layers_list.insert(self._index, self._new)
+
+class DelCommand(QUndoCommand):
+ def __init__(self, sediment_layers_list, rows):
+ QUndoCommand.__init__(self)
+
+ self._sediment_layers_list = sediment_layers_list
+ self._rows = rows
+
+ self._sl_pos = []
+ for row in rows:
+ self._sl_pos.append((row, self._sediment_layers_list.get(row)))
+ self._sl_pos.sort()
+
+ def undo(self):
+ for row, el in self._sl_pos:
+ self._sediment_layers_list.insert(row, el)
+
+ def redo(self):
+ self._sediment_layers_list.delete_i(self._rows)
+
+class MoveCommand(QUndoCommand):
+ def __init__(self, sediment_layers_list, up, i):
+ QUndoCommand.__init__(self)
+
+ self._sediment_layers_list = sediment_layers_list
+ self._up = up == "up"
+ self._i = i
+
+ def undo(self):
+ if self._up:
+ self._sediment_layers_list.move_up(self._i)
+ else:
+ self._sediment_layers_list.move_down(self._i)
+
+ def redo(self):
+ if self._up:
+ self._sediment_layers_list.move_up(self._i)
+ else:
+ self._sediment_layers_list.move_down(self._i)
diff --git a/src/View/SedimentLayers/Window.py b/src/View/SedimentLayers/Window.py
new file mode 100644
index 00000000..22b61318
--- /dev/null
+++ b/src/View/SedimentLayers/Window.py
@@ -0,0 +1,156 @@
+# -*- coding: utf-8 -*-
+
+import logging
+
+from tools import trace, timer
+
+from View.ASubWindow import ASubMainWindow
+from View.ListedSubWindow import ListedSubWindow
+
+from PyQt5.QtGui import (
+ QKeySequence,
+)
+
+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, QVBoxLayout, QHeaderView, QTabWidget,
+)
+
+from View.SedimentLayers.UndoCommand import *
+from View.SedimentLayers.Table import *
+
+from View.Plot.MplCanvas import MplCanvas
+from View.SedimentLayers.translate import *
+
+# from View.SedimentLayers.Edit.Window import EditSedimentLayersWindow
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+class SedimentLayersWindow(ASubMainWindow, ListedSubWindow):
+ def __init__(self, title="SedimentLayersList", study=None, parent=None):
+ self._study = study
+ self._sediment_layers = self._study.river.sediment_layers
+
+ self.setup_title(title)
+
+ super(SedimentLayersWindow, self).__init__(
+ name=self._title, ui="SedimentLayersList", parent=parent
+ )
+
+ self.setup_sc()
+ self.setup_table()
+ self.setup_graph()
+ self.setup_connections()
+
+ self.ui.setWindowTitle(self._title)
+
+ def setup_title(self, title):
+ self._title = (
+ title + " - " + self._study.name
+ )
+
+ def setup_sc(self):
+ self._undo_stack = QUndoStack()
+
+ self.undo_sc = QShortcut(QKeySequence.Undo, self)
+ self.redo_sc = QShortcut(QKeySequence.Redo, self)
+ self.copy_sc = QShortcut(QKeySequence.Copy, self)
+ self.paste_sc = QShortcut(QKeySequence.Paste, self)
+
+ def setup_table(self):
+ self._table = {}
+
+ table = self.find(QTableView, f"tableView")
+ self._table = TableModel(
+ study = self._study,
+ undo = self._undo_stack,
+ )
+ table.setModel(self._table)
+
+ table.setSelectionBehavior(QAbstractItemView.SelectRows)
+ table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
+ table.setAlternatingRowColors(True)
+
+ def setup_graph(self):
+ self.canvas = MplCanvas(width=5, height=4, dpi=100)
+ self.canvas.setObjectName("canvas")
+ self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
+ self.plot_layout.addWidget(self.canvas)
+
+ # self.plot = PlotKPC(
+ # canvas = self.canvas,
+ # data = self._reach.reach,
+ # toolbar = None,
+ # display_current = False
+ # )
+ # self.plot.draw()
+
+
+ def setup_connections(self):
+ self.find(QAction, "action_add").triggered.connect(self.add)
+ self.find(QAction, "action_del").triggered.connect(self.delete)
+ self.find(QAction, "action_edit").triggered.connect(self.edit_sediment_layers)
+
+ self.undo_sc.activated.connect(self.undo)
+ self.redo_sc.activated.connect(self.redo)
+ self.copy_sc.activated.connect(self.copy)
+ self.paste_sc.activated.connect(self.paste)
+
+ def index_selected_rows(self):
+ table = self.find(QTableView, f"tableView")
+ return list(
+ # Delete duplicate
+ set(
+ map(
+ lambda i: i.row(),
+ table.selectedIndexes()
+ )
+ )
+ )
+
+ def add(self):
+ rows = self.index_selected_rows()
+ if len(self._sediment_layers) == 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_sediment_layers(self):
+ rows = self.index_selected_rows()
+
+ for row in rows:
+ slw = EditSedimentLayersWindow(
+ study = self._study,
+ sl = self.__sediment_layers[row],
+ parent = self
+ )
+ slw.show()
diff --git a/src/View/SedimentLayers/translate.py b/src/View/SedimentLayers/translate.py
new file mode 100644
index 00000000..6eafe079
--- /dev/null
+++ b/src/View/SedimentLayers/translate.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+
+from PyQt5.QtCore import QCoreApplication
+
+_translate = QCoreApplication.translate
+
+table_headers = {
+ "name": _translate("SedimentLayers", "Name"),
+ "comment": _translate("SedimentLayers", "Comment"),
+}
diff --git a/src/View/ui/EditSedimentLayers.ui b/src/View/ui/EditSedimentLayers.ui
new file mode 100644
index 00000000..7e236641
--- /dev/null
+++ b/src/View/ui/EditSedimentLayers.ui
@@ -0,0 +1,114 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 960
+ 480
+
+
+
+ MainWindow
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+
+
+
+
+
+
+
+
+
+
+ toolBar
+
+
+ TopToolBarArea
+
+
+ false
+
+
+
+
+
+
+
+
+
+ ressources/gtk-add.pngressources/gtk-add.png
+
+
+ Add sediment layer
+
+
+ Add a new sediment layer
+
+
+ Ctrl+N
+
+
+
+
+
+ ressources/gtk-remove.pngressources/gtk-remove.png
+
+
+ Delete sediment layer
+
+
+ Delete selected sediment layer(s)
+
+
+ Ctrl+D
+
+
+
+
+
+ ressources/up.pngressources/up.png
+
+
+ Move up
+
+
+ Move up
+
+
+
+
+
+ ressources/down.pngressources/down.png
+
+
+ Move down
+
+
+ Move down
+
+
+
+
+
+
diff --git a/src/View/ui/MainWindow.ui b/src/View/ui/MainWindow.ui
index b63f032c..e91bd14d 100644
--- a/src/View/ui/MainWindow.ui
+++ b/src/View/ui/MainWindow.ui
@@ -199,10 +199,18 @@
+
+
@@ -909,6 +917,16 @@
Initial conditions
+
+
+ Sediment layers
+
+
+
+
+ Edit reach sediment layers
+
+
diff --git a/src/View/ui/ProfileSedimentLayers.ui b/src/View/ui/ProfileSedimentLayers.ui
new file mode 100644
index 00000000..b9f5106d
--- /dev/null
+++ b/src/View/ui/ProfileSedimentLayers.ui
@@ -0,0 +1,95 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 960
+ 480
+
+
+
+ MainWindow
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+
+
+
+
+
+
+
+
+
+
+ toolBar
+
+
+ TopToolBarArea
+
+
+ false
+
+
+
+
+
+
+
+
+ ressources/gtk-add.pngressources/gtk-add.png
+
+
+ Add sediment layers
+
+
+ Add specific sediment layers on selected point(s)
+
+
+
+
+
+ ressources/gtk-remove.pngressources/gtk-remove.png
+
+
+ Delete sediment layers
+
+
+ Delete specific sediment layers of selected point(s)
+
+
+
+
+
+ ressources/edit.pngressources/edit.png
+
+
+ Edit sediment layers
+
+
+ Edit sediment layers list
+
+
+
+
+
+
diff --git a/src/View/ui/ReachSedimentLayers.ui b/src/View/ui/ReachSedimentLayers.ui
new file mode 100644
index 00000000..b37db0c4
--- /dev/null
+++ b/src/View/ui/ReachSedimentLayers.ui
@@ -0,0 +1,98 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 960
+ 480
+
+
+
+ MainWindow
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+
-
+
+
+ -
+
+
+ Edit sediment layers list
+
+
+
+ -
+
+
+ Apply sediment layers on all reach
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ toolBar
+
+
+ TopToolBarArea
+
+
+ false
+
+
+
+
+
+
+ ressources/edit.pngressources/edit.png
+
+
+ Edit profile
+
+
+ Edit profile sediment layer
+
+
+
+
+
+ ressources/gtk-add.pngressources/gtk-add.png
+
+
+ Add sediment layer
+
+
+
+
+
+
diff --git a/src/View/ui/SedimentLayersList.ui b/src/View/ui/SedimentLayersList.ui
new file mode 100644
index 00000000..399b0995
--- /dev/null
+++ b/src/View/ui/SedimentLayersList.ui
@@ -0,0 +1,95 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 960
+ 480
+
+
+
+ MainWindow
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+
+
+
+
+
+
+
+
+
+
+ toolBar
+
+
+ TopToolBarArea
+
+
+ false
+
+
+
+
+
+
+
+
+ ressources/gtk-add.pngressources/gtk-add.png
+
+
+ Add sediment layer
+
+
+
+
+
+ ressources/gtk-remove.pngressources/gtk-remove.png
+
+
+ Delete sediment layer
+
+
+ Delete sediment layer
+
+
+
+
+
+ ressources/edit.pngressources/edit.png
+
+
+ Edit sediment layer
+
+
+ Edit sediment layer
+
+
+ Ctrl+E
+
+
+
+
+
+