From 3617fde986cdc9fc24119888c4c1d297719b13d2 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby <pierre-antoine.rouby@inrae.fr> Date: Tue, 9 May 2023 13:36:44 +0200 Subject: [PATCH] BC: Add multiple tab for liquid, solid and suspenssion. --- .../BoundaryCondition/BoundaryCondition.py | 4 + .../BoundaryConditionList.py | 60 +++++++--- .../BoundaryConditionTypes.py | 16 +++ src/View/BoundaryCondition/BCUndoCommand.py | 106 ++++++++++-------- .../BoundaryConditionWindow.py | 93 +++++++++------ src/View/BoundaryCondition/Table.py | 48 +++++--- src/View/ui/BoundaryConditions.ui | 6 +- 7 files changed, 213 insertions(+), 120 deletions(-) diff --git a/src/Model/BoundaryCondition/BoundaryCondition.py b/src/Model/BoundaryCondition/BoundaryCondition.py index d5486eaa..5bd26189 100644 --- a/src/Model/BoundaryCondition/BoundaryCondition.py +++ b/src/Model/BoundaryCondition/BoundaryCondition.py @@ -18,6 +18,10 @@ class BoundaryCondition(object): def __len__(self): return len(self._data) + @classmethod + def compatibility(cls): + return ["liquid", "solid", "suspenssion"] + @property def name(self): return self._name diff --git a/src/Model/BoundaryCondition/BoundaryConditionList.py b/src/Model/BoundaryCondition/BoundaryConditionList.py index a44629d4..4b14d924 100644 --- a/src/Model/BoundaryCondition/BoundaryConditionList.py +++ b/src/Model/BoundaryCondition/BoundaryConditionList.py @@ -11,56 +11,82 @@ from Model.BoundaryCondition.BoundaryConditionTypes import ( TimeOverZ, TimeOverDebit, ZOverDebit ) -class BoundaryConditionList(list): +class BoundaryConditionList(object): def __init__(self): super(BoundaryConditionList, self).__init__() - def new(self, index): + self._tabs = { + "liquid" : [], + "solid" : [], + "suspenssion" : [] + } + + def len(self, lst): + return len(self._tabs[lst]) + + def get_tab(self, lst): + return self._tabs[lst].copy() + + def get(self, lst, row): + return self._tabs[lst][row] + + def set(self, lst, row, new): + self._tabs[lst][row] = new + + def new(self, lst, index): n = NotDefined() - self.insert(index, n) + self._tabs[lst].insert(index, n) return n - def delete(self, bcs): + def insert(self, lst, index, new): + self._tabs[lst].insert(index, new) + + def delete(self, lst, bcs): for bc in bcs: - self.remove(bc) + self._tabs[lst].remove(bc) - def delete_i(self, indexes): + def delete_i(self, lst, indexes): bcs = list( map( lambda x: x[1], filter( lambda x: x[0] in indexes, - enumerate(self) + enumerate(self._tabs[lst]) ) ) ) - self.delete(bcs) + self.delete(lst, bcs) + + def sort(self, lst, reverse=False, key=None): + self._tabs[lst].sort(reverse=reverse, key=key) - def move_up(self, index): - if index < len(self): + def move_up(self, lst, index): + if index < len(self._tabs[lst]): next = index - 1 - self[index], self[next] = self[next], self[index] + l = self._tabs[lst] + l[index], l[next] = l[next], l[index] - def move_down(self, index): + def move_down(self, lst, index): if index >= 0: prev = index + 1 - self[index], self[prev] = self[prev], self[index] + l = self._tabs[lst] + l[index], l[prev] = l[prev], l[index] def __copy__(self): new = BoundaryConditionList() - for bc in self: - new.append(bc) + for l in self._tabs: + new.tabs[l] = self._tabs[l].copy() return new def __deepcopy__(self): new = BoundaryConditionList() - for bc in self: - new.append(deepcopy(bc)) + for l in self._tabs: + new.tabs[l] = self._tabs[l].deepcopy() return new diff --git a/src/Model/BoundaryCondition/BoundaryConditionTypes.py b/src/Model/BoundaryCondition/BoundaryConditionTypes.py index 327bc3a5..85113389 100644 --- a/src/Model/BoundaryCondition/BoundaryConditionTypes.py +++ b/src/Model/BoundaryCondition/BoundaryConditionTypes.py @@ -19,6 +19,10 @@ class PonctualContribution(BoundaryCondition): self._type = "PC" self._header = ["time", "debit"] + @classmethod + def compatibility(cls): + return ["liquid"] + class TimeOverZ(BoundaryCondition): def __init__(self, name:str = ""): super(TimeOverZ, self).__init__(name=name) @@ -26,6 +30,10 @@ class TimeOverZ(BoundaryCondition): self._type = "TZ" self._header = ["time", "z"] + @classmethod + def compatibility(cls): + return ["liquid"] + class TimeOverDebit(BoundaryCondition): def __init__(self, name:str = ""): super(TimeOverDebit, self).__init__(name=name) @@ -33,6 +41,10 @@ class TimeOverDebit(BoundaryCondition): self._type = "TD" self._header = ["time", "debit"] + @classmethod + def compatibility(cls): + return ["liquid"] + class ZOverDebit(BoundaryCondition): def __init__(self, name:str = ""): super(ZOverDebit, self).__init__(name=name) @@ -41,6 +53,10 @@ class ZOverDebit(BoundaryCondition): self._header = ["z", "debit"] self._types = [float, float] + @classmethod + def compatibility(cls): + return ["liquid"] + @property def _default_0(self): return 0.0 diff --git a/src/View/BoundaryCondition/BCUndoCommand.py b/src/View/BoundaryCondition/BCUndoCommand.py index 3cd3ec9f..7b1c7f5e 100644 --- a/src/View/BoundaryCondition/BCUndoCommand.py +++ b/src/View/BoundaryCondition/BCUndoCommand.py @@ -11,105 +11,114 @@ from Model.BoundaryCondition.BoundaryCondition import BoundaryCondition from Model.BoundaryCondition.BoundaryConditionList import BoundaryConditionList class SetNameCommand(QUndoCommand): - def __init__(self, lst, index, new_value): + def __init__(self, bcs, tab, index, new_value): QUndoCommand.__init__(self) - self._lst = lst + self._bcs = bcs + self._tab = tab self._index = index - self._old = self._lst[self._index].name + self._old = self._bcs.get(self._tab, self._index).name self._new = new_value def undo(self): - self._lst[self._index].name = self._old + self._bcs.get(self._tab, self._index).name = self._old def redo(self): - self._lst[self._index].name = self._new + self._bcs.get(self._tab, self._index).name = self._new class SetNodeCommand(QUndoCommand): - def __init__(self, lst, index, node): + def __init__(self, bcs, tab, index, node): QUndoCommand.__init__(self) - self._lst = lst + self._bcs = bcs + self._tab = tab self._index = index - self._old = self._lst[index].node + self._old = self._bcs.get(self._tab, self._index).node self._new = node def undo(self): - self._lst[self._index].node = self._old + self._bcs.get(self._tab, self._index).node = self._old def redo(self): - self._lst[self._index].node = self._new + self._bcs.get(self._tab, self._index).node = self._new class SetTypeCommand(QUndoCommand): - def __init__(self, lst, index, _type): + def __init__(self, bcs, tab, index, _type): QUndoCommand.__init__(self) - self._lst = lst + self._bcs = bcs + self._tab = tab self._index = index self._type = _type - self._old = self._lst[index] - self._new = self._lst[index].convert(self._type) + self._old = self._bcs.get(self._tab, self._index) + self._new = self._bcs.get(self._tab, self._index)\ + .convert(self._type) def undo(self): - self._lst[self._index] = self._old + self._bcs.set(self._tab, self._index, self._old) def redo(self): - self._lst[self._index] = self._new + self._bcs.set(self._tab, self._index, self._new) class AddCommand(QUndoCommand): - def __init__(self, lst, index): + def __init__(self, bcs, tab, index): QUndoCommand.__init__(self) - self._lst = lst + self._bcs = bcs + self._tab = tab self._index = index self._new = None def undo(self): - self._lst.delete_i([self._index]) + self._bcs.delete_i(self._tab, [self._index]) def redo(self): if self._new is None: - self._new = self._lst.new(self._index) + self._new = self._bcs.new(self._tab, self._index) else: - self._lst.insert(self._index, self._new) + self._bcs.insert(self._tab, self._index, self._new) class DelCommand(QUndoCommand): - def __init__(self, lst, rows): + def __init__(self, bcs, tab, rows): QUndoCommand.__init__(self) - self._lst = lst + self._bcs = bcs + self._tab = tab self._rows = rows self._bc = [] for row in rows: - self._bc.append((row, self._lst[row])) + self._bc.append((row, self._bcs.get(self._tab, row))) self._bc.sort() def undo(self): for row, el in self._bc: - self._lst.insert(row, el) + self._bcs.insert(self._tab, row, el) def redo(self): - self._lst.delete_i(self._rows) + self._bcs.delete_i(self._tab, self._rows) class SortCommand(QUndoCommand): - def __init__(self, lst, _reverse): + def __init__(self, bcs, tab, _reverse): QUndoCommand.__init__(self) - self._lst = lst + self._bcs = bcs + self._tab = tab self._reverse = _reverse - self._old = self._lst.copy() + self._old = self._bcs.get_tab(self._tab) self._indexes = None def undo(self): - ll = self._lst.copy() - self._lst.sort( + ll = self._bcs.get_tab(self._tab) + self._bcs.sort( + self._tab, key=lambda x: self._indexes[ll.index(x)] ) def redo(self): - self._lst.sort( + self._bcs.sort( + self._tab, reverse=self._reverse, key=lambda x: x.name ) @@ -117,62 +126,65 @@ class SortCommand(QUndoCommand): self._indexes = list( map( lambda p: self._old.index(p), - self._lst + self._bcs.get_tab(self._tab) ) ) self._old = None class MoveCommand(QUndoCommand): - def __init__(self, lst, up, i): + def __init__(self, bcs, tab, up, i): QUndoCommand.__init__(self) - self._lst = lst + self._bcs = bcs + self._tab = tab self._up = up == "up" self._i = i def undo(self): if self._up: - self._lst.move_up(self._i) + self._bcs.move_up(self._tab, self._i) else: - self._lst.move_down(self._i) + self._bcs.move_down(self._tab, self._i) def redo(self): if self._up: - self._lst.move_up(self._i) + self._bcs.move_up(self._tab, self._i) else: - self._lst.move_down(self._i) + self._bcs.move_down(self._tab, self._i) class PasteCommand(QUndoCommand): - def __init__(self, lst, row, bc): + def __init__(self, bcs, tab, row, bc): QUndoCommand.__init__(self) - self._lst = lst + self._bcs = bcs + self._tab = tab self._row = row self._bc = deepcopy(bc) self._bc.reverse() def undo(self): - self._lst.delete(self._bc) + self._bcs.delete(self._tab, self._bc) def redo(self): for bc in self._bc: - self._lst.insert(self._row, bc) + self._bcs.insert(self._tab, self._row, bc) class DuplicateCommand(QUndoCommand): - def __init__(self, lst, rows, bc): + def __init__(self, bcs, tab, rows, bc): QUndoCommand.__init__(self) - self._lst = lst + self._bcs = bcs + self._tab = tab self._rows = rows self._bc = deepcopy(bc) self._bc.reverse() def undo(self): - self._lst.delete(self._bc) + self._bcs.delete(self._tab, self._bc) def redo(self): for bc in self._bcs: - self._lst.insert(self._rows[0], bc) + self._bcs.insert(self._tab, self._rows[0], bc) diff --git a/src/View/BoundaryCondition/BoundaryConditionWindow.py b/src/View/BoundaryCondition/BoundaryConditionWindow.py index 38b9e6b1..c14ef005 100644 --- a/src/View/BoundaryCondition/BoundaryConditionWindow.py +++ b/src/View/BoundaryCondition/BoundaryConditionWindow.py @@ -19,7 +19,7 @@ from PyQt5.QtWidgets import ( QDialogButtonBox, QPushButton, QLineEdit, QFileDialog, QTableView, QAbstractItemView, QUndoStack, QShortcut, QAction, QItemDelegate, - QComboBox, QVBoxLayout, QHeaderView + QComboBox, QVBoxLayout, QHeaderView, QTabWidget, ) from View.BoundaryCondition.BCUndoCommand import ( @@ -69,32 +69,40 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow): self.paste_sc = QShortcut(QKeySequence.Paste, self) def setup_table(self): - table = self.find(QTableView, "tableView_liquid") - self._table = TableModel( - data = self._study.river, - undo = self._undo_stack - ) - table.setModel(self._table) + self._table = {} + + for t in ["liquid", "solid", "suspenssion"]: + table = self.find(QTableView, f"tableView_{t}") + self._table[t] = TableModel( + data = self._study.river, + undo = self._undo_stack, + tab = t, + ) + table.setModel(self._table[t]) - self._delegate_type = ComboBoxDelegate( - data = self._study.river, - mode = "type" - ) - self._delegate_node = ComboBoxDelegate( - data = self._study.river, - mode = "node" - ) + self._delegate_type = ComboBoxDelegate( + data = self._study.river, + mode = "type", + tab = t, + parent=self + ) + self._delegate_node = ComboBoxDelegate( + data = self._study.river, + mode = "node", + tab = t, + parent=self + ) - table.setItemDelegateForColumn( - 1, self._delegate_type - ) - table.setItemDelegateForColumn( - 2, self._delegate_node - ) + table.setItemDelegateForColumn( + 1, self._delegate_type + ) + table.setItemDelegateForColumn( + 2, self._delegate_node + ) - table.setSelectionBehavior(QAbstractItemView.SelectRows) - table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) - table.setAlternatingRowColors(True) + table.setSelectionBehavior(QAbstractItemView.SelectRows) + table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) + table.setAlternatingRowColors(True) def setup_graph(self): self.graph_widget = GraphWidget( @@ -117,15 +125,22 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow): self.copy_sc.activated.connect(self.copy) self.paste_sc.activated.connect(self.paste) + def current_tab(self): + return self.find(QTabWidget, "tabWidget")\ + .currentWidget()\ + .objectName()\ + .replace("tab_", "") def index_selected_row(self): - table = self.find(QTableView, "tableView_liquid") + tab = self.current_tab() + table = self.find(QTableView, f"tableView_{tab}") return table.selectionModel()\ .selectedRows()[0]\ .row() def index_selected_rows(self): - table = self.find(QTableView, "tableView_liquid") + tab = self.current_tab() + table = self.find(QTableView, f"tableView_{tab}") return list( # Delete duplicate set( @@ -137,30 +152,34 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow): ) def add(self): + tab = self.current_tab() rows = self.index_selected_rows() - if len(self._lst) == 0 or len(rows) == 0: - self._table.add(0) + if self._lst.len(tab) == 0 or len(rows) == 0: + self._table[tab].add(0) else: - self._table.add(rows[0]) + self._table[tab].add(rows[0]) def delete(self): + tab = self.current_tab() rows = self.index_selected_rows() if len(rows) == 0: return - self._table.delete(rows) + self._table[tab].delete(rows) def sort(self): - self._table.sort(False) + tab = self.current_tab() + self._table[tab].sort(False) def move_up(self): + tab = self.current_tab() row = self.index_selected_row() - self._table.move_up(row) + self._table[tab].move_up(row) def move_down(self): + tab = self.current_tab() row = self.index_selected_row() - self._table.move_down(row) - + self._table[tab].move_down(row) def copy(self): print("TODO") @@ -169,10 +188,12 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow): print("TODO") def undo(self): - self._table.undo() + tab = self.current_tab() + self._table[tab].undo() def redo(self): - self._table.redo() + tab = self.current_tab() + self._table[tab].redo() def edit(self): rows = self.index_selected_rows() diff --git a/src/View/BoundaryCondition/Table.py b/src/View/BoundaryCondition/Table.py index f7bc377a..019f4642 100644 --- a/src/View/BoundaryCondition/Table.py +++ b/src/View/BoundaryCondition/Table.py @@ -30,17 +30,30 @@ from View.BoundaryCondition.translate import * _translate = QCoreApplication.translate class ComboBoxDelegate(QItemDelegate): - def __init__(self, data=None, mode="type", parent=None): + def __init__(self, data=None, mode="type", tab="", parent=None): super(ComboBoxDelegate, self).__init__(parent) self._data = data self._mode = mode + self._tab = tab def createEditor(self, parent, option, index): self.editor = QComboBox(parent) if self._mode == "type": - self.editor.addItems([long_types[k] for k in BC_types.keys()]) + lst = list( + map( + lambda k: long_types[k], + filter( + lambda k: self._tab in BC_types[k].compatibility(), + BC_types.keys() + ) + ) + ) + print(lst) + self.editor.addItems( + lst + ) else: self.editor.addItems( [_translate("BoundaryCondition", "Not associate")] + @@ -72,12 +85,13 @@ class ComboBoxDelegate(QItemDelegate): class TableModel(QAbstractTableModel): - def __init__(self, data=None, undo=None): + def __init__(self, data=None, undo=None, tab=""): super(QAbstractTableModel, self).__init__() self._headers = list(table_headers.keys()) self._data = data self._undo = undo - self._lst = self._data.boundary_condition + self._tab = tab + self._bcs = self._data.boundary_condition def flags(self, index): options = Qt.ItemIsEnabled | Qt.ItemIsSelectable @@ -86,7 +100,7 @@ class TableModel(QAbstractTableModel): return options def rowCount(self, parent): - return len(self._lst) + return self._bcs.len(self._tab) def columnCount(self, parent): return len(self._headers) @@ -99,12 +113,12 @@ class TableModel(QAbstractTableModel): column = index.column() if self._headers[column] == "name": - return self._lst[row].name + return self._bcs.get(self._tab, row).name elif self._headers[column] == "type": - t = self._lst[row].bctype + t = self._bcs.get(self._tab, row).bctype return long_types[t] elif self._headers[column] == "node": - n = self._lst[row].node + n = self._bcs.get(self._tab, row).node if n is None: return _translate("BoundaryCondition", "Not associate") return n.name @@ -127,20 +141,20 @@ class TableModel(QAbstractTableModel): if self._headers[column] == "name": self._undo.push( SetNameCommand( - self._lst, row, value + self._bcs, self._tab,row, value ) ) elif self._headers[column] == "type": key = next(k for k, v in long_types.items() if v == value) self._undo.push( SetTypeCommand( - self._lst, row, BC_types[key] + self._bcs, self._tab,row, BC_types[key] ) ) elif self._headers[column] == "node": self._undo.push( SetNodeCommand( - self._lst, row, self._data.node(value) + self._bcs, self._tab,row, self._data.node(value) ) ) @@ -152,7 +166,7 @@ class TableModel(QAbstractTableModel): self._undo.push( AddCommand( - self._lst, row + self._bcs, self._tab,row ) ) @@ -164,7 +178,7 @@ class TableModel(QAbstractTableModel): self._undo.push( DelCommand( - self._lst, rows + self._bcs, self._tab,rows ) ) @@ -176,7 +190,7 @@ class TableModel(QAbstractTableModel): self._undo.push( SortCommand( - self._lst, False + self._bcs, self._tab,False ) ) @@ -193,7 +207,7 @@ class TableModel(QAbstractTableModel): self._undo_stack.push( MoveCommand( - self._lst, "up", row + self._bcs, self._tab,"up", row ) ) @@ -201,7 +215,7 @@ class TableModel(QAbstractTableModel): self.layoutChanged.emit() def move_down(self, index, parent=QModelIndex()): - if row > len(self._lst): + if row > len(self._bcs): return target = row @@ -210,7 +224,7 @@ class TableModel(QAbstractTableModel): self._undo_stack.push( MoveCommand( - self._lst, "down", row + self._bcs, self._tab,"down", row ) ) diff --git a/src/View/ui/BoundaryConditions.ui b/src/View/ui/BoundaryConditions.ui index 602a1887..3097fd63 100644 --- a/src/View/ui/BoundaryConditions.ui +++ b/src/View/ui/BoundaryConditions.ui @@ -33,7 +33,7 @@ <property name="currentIndex"> <number>0</number> </property> - <widget class="QWidget" name="tab"> + <widget class="QWidget" name="tab_liquid"> <attribute name="title"> <string>Liquid</string> </attribute> @@ -43,7 +43,7 @@ </item> </layout> </widget> - <widget class="QWidget" name="tab_2"> + <widget class="QWidget" name="tab_solid"> <attribute name="title"> <string>Solid</string> </attribute> @@ -53,7 +53,7 @@ </item> </layout> </widget> - <widget class="QWidget" name="tab_3"> + <widget class="QWidget" name="tab_suspenssion"> <attribute name="title"> <string>Suspenssion</string> </attribute> -- GitLab