diff --git a/src/View/InitialConditionsAdisTS/Table.py b/src/View/InitialConditionsAdisTS/Table.py index c2c8af48..658e0eba 100644 --- a/src/View/InitialConditionsAdisTS/Table.py +++ b/src/View/InitialConditionsAdisTS/Table.py @@ -47,24 +47,39 @@ _translate = QCoreApplication.translate class ComboBoxDelegate(QItemDelegate): - def __init__(self, data=None, reach=None, parent=None, mode="reaches"): + def __init__(self, data=None, ic_spec_lst=None, trad=None, parent=None, mode="reaches"): super(ComboBoxDelegate, self).__init__(parent) - self._reach = reach.reach - self._data = data self._mode = mode + self._trad = trad + self._ic_spec_lst = ic_spec_lst def createEditor(self, parent, option, index): self.editor = QComboBox(parent) - self.editor.addItems( - list( + val = [] + if self._mode == "kp": + reach_id = self._ic_spec_lst[index.row()].reach + + reach = next(filter(lambda edge: edge.id == reach_id, self._data.edges())) + + if reach_id is not None: + val = list( + map( + lambda kp: str(kp), reach.reach.get_kp() + ) + ) + else: + val = list( map( - str, - self._reach.get_kp() + lambda n: n.name, self._data.edges() ) ) + + self.editor.addItems( + [self._trad['not_associated']] + + val ) self.editor.setCurrentText(str(index.data(Qt.DisplayRole))) @@ -93,13 +108,10 @@ class ComboBoxDelegate(QItemDelegate): class InitialConditionTableModel(PamhyrTableModel): - def __init__(self, reach=None, **kwargs): - self._reach = reach + def __init__(self, data=None, **kwargs): + self._lst = data[0]._data super(InitialConditionTableModel, self).__init__(**kwargs) - def _setup_lst(self): - self._lst = self._data.river.initial_conditions.get(self._reach) - def data(self, index, role): if role != Qt.ItemDataRole.DisplayRole: return QVariant() @@ -107,22 +119,51 @@ class InitialConditionTableModel(PamhyrTableModel): row = index.row() column = index.column() - if self._headers[column] is "speed": - z = self._lst.get(row)["elevation"] - q = self._lst.get(row)["discharge"] - profile = self._reach.reach.get_profiles_from_kp( - self._lst.get(row)["kp"] - ) - if len(profile) >= 1: - speed = profile[0].speed(q, z) - return f"{speed:.4f}" - - return "" - elif self._headers[column] not in ["name", "comment"]: - v = self._lst.get(row)[self._headers[column]] - return f"{v:.4f}" - else: - return self._lst.get(row)[self._headers[column]] + if self._headers[column] is "name": + n = self._lst[row].name + if n is None: + return self._trad['not_associated'] + return n + elif self._headers[column] is "reach": + n = self._lst[row].reach + if n is None: + return self._trad['not_associated'] + return next(filter(lambda edge: edge.id == n, self._data.edges())).name + elif self._headers[column] is "start_kp": + n = self._lst[row].start_kp + if n is None: + return self._trad['not_associated'] + return n + elif self._headers[column] is "end_kp": + n = self._lst[row].end_kp + if n is None: + return self._trad['not_associated'] + return n + elif self._headers[column] is "concentration": + n = self._lst[row].concentration + if n is None: + return self._trad['not_associated'] + return n + elif self._headers[column] is "eg": + n = self._lst[row].eg + if n is None: + return self._trad['not_associated'] + return n + elif self._headers[column] is "em": + n = self._lst[row].em + if n is None: + return self._trad['not_associated'] + return n + elif self._headers[column] is "ed": + n = self._lst[row].ed + if n is None: + return self._trad['not_associated'] + return n + elif self._headers[column] is "rate": + n = self._lst[row].rate + if n is None: + return self._trad['not_associated'] + return n return QVariant() @@ -152,7 +193,7 @@ class InitialConditionTableModel(PamhyrTableModel): self._undo.push( AddCommand( - self._lst, row + self._data, self._lst, row ) ) @@ -164,126 +205,13 @@ class InitialConditionTableModel(PamhyrTableModel): self._undo.push( DelCommand( - self._lst, rows + self._data, self._lst, rows ) ) self.endRemoveRows() self.layoutChanged.emit() - def sort(self, _reverse, parent=QModelIndex()): - self.layoutAboutToBeChanged.emit() - - self._undo.push( - SortCommand( - self._lst, False - ) - ) - - self.layoutAboutToBeChanged.emit() - 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.push( - MoveCommand( - self._lst, "up", row - ) - ) - - self.endMoveRows() - self.layoutChanged.emit() - - def move_down(self, row, parent=QModelIndex()): - if row > len(self._lst): - return - - target = row - - self.beginMoveRows(parent, row + 1, row + 1, parent, target) - - self._undo.push( - MoveCommand( - self._lst, "down", row - ) - ) - - self.endMoveRows() - self.layoutChanged.emit() - - def paste(self, index, header, data): - if len(header) != 0: - logger.error("Unexpected header in IC past data") - return - - if len(data) == 0: - logger.error("Empty data") - return - - if len(data[0]) != 3: - logger.error(f"Unexpected data size: [{data[0]}, ...]") - return - - self.layoutAboutToBeChanged.emit() - - self._undo.push( - InsertCommand( - self._lst, index, - list( - map( - lambda d: self._lst.new_from_data(*d), - data - ) - ) - ) - ) - - self.layoutAboutToBeChanged.emit() - self.layoutChanged.emit() - - def import_from_results(self, index, results): - if results is None: - logger.error("No results data") - return - - self.layoutAboutToBeChanged.emit() - - ts = max(results.get("timestamps")) - res_reach = results.river.get_reach_by_geometry( - self._reach.reach - ) - data = list( - map( - lambda p: [ - p.geometry.kp, - p.get_ts_key(ts, "Q"), - p.get_ts_key(ts, "Z"), - ], - res_reach.profiles - ) - ) - - self._undo.push( - InsertCommand( - self._lst, index, - list( - map( - lambda d: self._lst.new_from_data(*d), - data - ) - ) - ) - ) - - self.layoutAboutToBeChanged.emit() - self.layoutChanged.emit() - def undo(self): self._undo.undo() self.layoutChanged.emit() @@ -292,10 +220,3 @@ class InitialConditionTableModel(PamhyrTableModel): self._undo.redo() self.layoutChanged.emit() - def generate(self, generator, param): - self._undo.push( - GenerateCommand( - self._lst, generator, param - ) - ) - self.layoutChanged.emit() diff --git a/src/View/InitialConditionsAdisTS/UndoCommand.py b/src/View/InitialConditionsAdisTS/UndoCommand.py index 444a1995..dfb1c268 100644 --- a/src/View/InitialConditionsAdisTS/UndoCommand.py +++ b/src/View/InitialConditionsAdisTS/UndoCommand.py @@ -77,3 +77,21 @@ class SetCommand(QUndoCommand): elif self._column == "ed": self._data[self._row].ed = self._new +class AddCommand(QUndoCommand): + def __init__(self, data, ics, index): + QUndoCommand.__init__(self) + + self._data = data + self._ics = ics + self._index = index + self._new = None + + def undo(self): + self._ics.delete_i([self._index]) + + def redo(self): + if self._new is None: + self._new = self._ics.new(self._index) + else: + self._ics.insert(self._index, self._new) + diff --git a/src/View/InitialConditionsAdisTS/Window.py b/src/View/InitialConditionsAdisTS/Window.py index 2880915a..ed608457 100644 --- a/src/View/InitialConditionsAdisTS/Window.py +++ b/src/View/InitialConditionsAdisTS/Window.py @@ -24,7 +24,7 @@ from tools import trace, timer, logger_exception from View.Tools.PamhyrWindow import PamhyrWindow from PyQt5.QtGui import ( - QKeySequence, + QKeySequence, QIcon, ) from PyQt5.QtCore import ( @@ -38,6 +38,7 @@ from PyQt5.QtWidgets import ( QFileDialog, QTableView, QAbstractItemView, QUndoStack, QShortcut, QAction, QItemDelegate, QComboBox, QVBoxLayout, QHeaderView, QTabWidget, + QVBoxLayout, QToolBar, QAction, QToolButton, ) from Modules import Modules @@ -50,6 +51,10 @@ from View.InitialConditionsAdisTS.TableDefault import ( InitialConditionTableDefaultModel, ) +from View.InitialConditionsAdisTS.Table import ( + InitialConditionTableModel, ComboBoxDelegate, +) + from View.InitialConditionsAdisTS.translate import IcAdisTSTranslate from Solver.Mage import Mage8 @@ -90,10 +95,13 @@ class InitialConditionsAdisTSWindow(PamhyrWindow): self.ui.setWindowTitle(self._title) def setup_table(self): - table = self.find(QTableView, f"tableView") + + path_icons = os.path.join(self._get_ui_directory(), f"ressources") + + table_default = self.find(QTableView, f"tableView") self._table = InitialConditionTableDefaultModel( - table_view=table, + table_view=table_default, table_headers=self._trad.get_dict("table_headers"), editable_headers=["name", "concentration", "eg", "em", "ed"], delegates={}, @@ -102,10 +110,63 @@ class InitialConditionsAdisTSWindow(PamhyrWindow): trad=self._trad ) - table.setModel(self._table) - table.setSelectionBehavior(QAbstractItemView.SelectRows) - table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) - table.setAlternatingRowColors(True) + table_default.setModel(self._table) + table_default.setSelectionBehavior(QAbstractItemView.SelectRows) + table_default.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) + table_default.setAlternatingRowColors(True) + + layout = self.find(QVBoxLayout, f"verticalLayout_1") + toolBar = QToolBar() + layout.addWidget(toolBar) + + action_add = QAction(self) + action_add.setIcon(QIcon(os.path.join(path_icons, f"add.png"))) + action_delete = QAction(self) + action_delete.setIcon(QIcon(os.path.join(path_icons, f"del.png"))) + + toolBar.addAction(action_add) + toolBar.addAction(action_delete) + + table_spec = QTableView() + layout.addWidget(table_spec) + + self._delegate_reach = ComboBoxDelegate( + trad=self._trad, + data=self._study.river, + ic_spec_lst=self._data[0]._data, + parent=self, + mode="reaches" + ) + self._delegate_kp = ComboBoxDelegate( + trad=self._trad, + data=self._study.river, + ic_spec_lst=self._data[0]._data, + parent=self, + mode="kp" + ) + + self._table_spec = InitialConditionTableModel( + table_view=table_spec, + table_headers=self._trad.get_dict("table_headers_spec"), + editable_headers=["name", "reach", "start_kp", "end_kp", "concentration", "eg", "em", "ed", "rate"], + delegates={ + "reach": self._delegate_reach, + "start_kp": self._delegate_kp, + "end_kp": self._delegate_kp + }, + data=self._data[0], + undo=self._undo_stack, + trad=self._trad + ) + + table_spec.setModel(self._table_spec) + table_spec.setSelectionBehavior(QAbstractItemView.SelectRows) + table_spec.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) + table_spec.setAlternatingRowColors(True) + + def setup_connections(self): + self.find(QAction, "action_add").triggered.connect(self.add) + self.find(QAction, "action_delete").triggered.connect(self.delete) def index_selected_row(self): table = self.find(QTableView, f"tableView") @@ -192,3 +253,16 @@ class InitialConditionsAdisTSWindow(PamhyrWindow): def _redo(self): self._table.redo() self._update() + + def add(self): + rows = self.index_selected_rows() + if len(self._data[0]._data) == 0 or len(rows) == 0: + self._table_spec.add(0) + else: + self._table_spec.add(rows[0]) + + def delete(self): + rows = self.index_selected_rows() + if len(rows) == 0: + return + self._table_spec.delete(rows) diff --git a/src/View/InitialConditionsAdisTS/translate.py b/src/View/InitialConditionsAdisTS/translate.py index cfbae22f..cbe225ff 100644 --- a/src/View/InitialConditionsAdisTS/translate.py +++ b/src/View/InitialConditionsAdisTS/translate.py @@ -39,3 +39,15 @@ class IcAdisTSTranslate(MainTranslate): "em": _translate("Unit", "EM (m)"), "ed": _translate("Unit", "ED (m)"), } + + self._sub_dict["table_headers_spec"] = { + "name": self._dict["name"], + "reach": self._dict["reach"], + "start_kp": _translate("Unit", "Start_KP (m)"), + "end_kp": _translate("Unit", "End_KP (m)"), + "concentration": self._dict["unit_concentration"], + "eg": _translate("Unit", "EG (m)"), + "em": _translate("Unit", "EM (m)"), + "ed": _translate("Unit", "ED (m)"), + "rate": _translate("Unit", "Rate"), + } diff --git a/src/View/OutputKpAdisTS/Window.py b/src/View/OutputKpAdisTS/Window.py index 04840d59..7689be9e 100644 --- a/src/View/OutputKpAdisTS/Window.py +++ b/src/View/OutputKpAdisTS/Window.py @@ -39,7 +39,7 @@ from View.Tools.Plot.PamhyrCanvas import MplCanvas from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar from View.OutputKpAdisTS.Table import ( - TableModel, ComboBoxDelegate + TableModel, ComboBoxDelegate, ) from View.Network.GraphWidget import GraphWidget diff --git a/src/View/ui/InitialConditionsAdisTS.ui b/src/View/ui/InitialConditionsAdisTS.ui index 94792877..b4fe3e2d 100644 --- a/src/View/ui/InitialConditionsAdisTS.ui +++ b/src/View/ui/InitialConditionsAdisTS.ui @@ -66,33 +66,7 @@ false - - - - - - ressources/add.pngressources/add.png - - - Add - - - Add new initial condition - - - - - - ressources/del.pngressources/del.png - - - delete - - - Delete inital condition - -