Compare commits

..

17 Commits

Author SHA1 Message Date
Dylan Jeannin ea2287215e fix pep8 before push 2026-05-18 15:33:36 +02:00
Dylan Jeannin e940dead70 Merge branch 'dev_dylan' into scenarios 2026-05-18 15:04:37 +02:00
Dylan Jeannin 084c22836b debug undo after deletion of BCA 2026-05-12 13:48:14 +02:00
Dylan Jeannin 726b81bf12 debug undo after add LateralContributionAdisTS 2026-05-12 08:40:35 +02:00
Dylan Jeannin 7c3de520d9 delete old references to pollutants in BoundaryConditionsAdisTS window 2026-05-12 08:39:58 +02:00
Dylan Jeannin b450796df5 stab window InitialCond AdisTS (undo / redo / add / delete / save / load), all should work correctly 2026-05-11 16:14:35 +02:00
Dylan Jeannin b1daadf9f2 rename variables for DIF to keep consistency 2026-05-11 14:59:48 +02:00
Dylan Jeannin c38e3ee446 correct pep8 rules 2026-05-11 14:59:14 +02:00
Dylan Jeannin 606b9919e3 stab window D90 AdisTS (undo / redo / add / delete / save / load), all should work correctly 2026-05-11 14:58:42 +02:00
Dylan Jeannin e3de7e7100 rename variable to keep consistency 2026-05-11 14:07:38 +02:00
Dylan Jeannin 92fae0e13f rename variable to keep consistency 2026-05-11 14:06:07 +02:00
Dylan Jeannin a8b260ad38 debug crash when double clic on PK combobox when no reach is selected (DIF window) 2026-05-11 13:49:54 +02:00
Dylan Jeannin faff877c80 stab window DIF AdisTS (undo / redo / add / delete / save / load), all should work correctly 2026-05-11 12:52:33 +02:00
Dylan Jeannin 7565d8ee95 fix pep8 2026-05-05 17:51:49 +02:00
Dylan Jeannin 11e1302e05 fix add/del/undo/redo in edit BoundaryConditionsAdisTS + quick fix in edit LateralContributionsAdisTS 2026-05-05 17:50:45 +02:00
Dylan Jeannin 99cb2883a1 display seconds in LateralContributionAdisTS data (edition window) 2026-05-05 12:34:44 +02:00
Dylan Jeannin e61dede7f8 add Dylan in contributors 2026-05-05 12:33:41 +02:00
22 changed files with 233 additions and 98 deletions

View File

@ -1,3 +1,4 @@
Sylvain COULIBALY, INRAE, 2020 - 2022 Sylvain COULIBALY, INRAE, 2020 - 2022
Théophile TERRAZ, INRAE, 2022 - 2024 Théophile TERRAZ, INRAE, 2022 - 2024
Pierre-Antoine ROUBY, INRAE, 2023 - 2025 Pierre-Antoine ROUBY, INRAE, 2023 - 2025
Dylan JEANNIN, INRAE, 2026

View File

@ -143,9 +143,9 @@ class Data(SQLSubModel):
table = execute( table = execute(
"SELECT pamhyr_id, deleted, data0, data1, scenario FROM " + "SELECT pamhyr_id, deleted, data0, data1, scenario FROM " +
"boundary_condition_data_adists " + "boundary_condition_data_adists " +
f"WHERE bca = {bca.id} " + f"WHERE scenario = {scenario.id} " +
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) " + # f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) " +
f"AND scenario = {scenario.id}" f"AND bca = {bca.id}"
) )
if table is not None: if table is not None:
@ -188,8 +188,9 @@ class Data(SQLSubModel):
execute( execute(
"INSERT INTO " + "INSERT INTO " +
"boundary_condition_data_adists(" + "boundary_condition_data_adists(" +
"pamhyr_id, data0, data1, bca, scenario) " + "pamhyr_id, deleted, data0, data1, bca, scenario) " +
f"VALUES ({self.id}, '{data0}', {data1}, {bca.id}, " + f"VALUES ({self.id}, {self._db_format(self.is_deleted())}, " +
f"'{data0}', {data1}, {bca.id}, " +
f"{self._status.scenario_id})" f"{self._status.scenario_id})"
) )
@ -437,7 +438,14 @@ class BoundaryConditionAdisTS(SQLSubModel):
d._data_traversal(predicate, modifier, data) d._data_traversal(predicate, modifier, data)
def __len__(self): def __len__(self):
return len(self._data) return len(
list(
filter(
lambda el: el is not None and not el.is_deleted(),
self._data
)
)
)
@classmethod @classmethod
def time_convert(cls, data): def time_convert(cls, data):
@ -493,7 +501,12 @@ class BoundaryConditionAdisTS(SQLSubModel):
@property @property
def data(self): def data(self):
return self._data.copy() return list(
filter(
lambda el: el is not None and not el.is_deleted(),
self._data
)
)
@property @property
def _default_0(self): def _default_0(self):
@ -535,11 +548,11 @@ class BoundaryConditionAdisTS(SQLSubModel):
self.modified() self.modified()
def delete_i(self, indexes): def delete_i(self, indexes):
self._data = list( list(
map( map(
lambda e: e[1], lambda e: e[1].set_as_deleted(),
filter( filter(
lambda e: e[0] not in indexes, lambda e: e[0] in indexes,
enumerate(self.data) enumerate(self.data)
) )
) )

View File

@ -142,24 +142,24 @@ class DIFAdisTS(SQLSubModel):
enabled = (next(it) == 1) enabled = (next(it) == 1)
owner_scenario = next(it) owner_scenario = next(it)
dif = cls( DIF = cls(
id=pid, id=pid,
name=name, name=name,
status=status, status=status,
owner_scenario=owner_scenario, owner_scenario=owner_scenario,
) )
dif.method = method DIF.method = method
dif.dif = dif DIF.dif = dif
dif.b = b DIF.b = b
dif.c = c DIF.c = c
dif.enabled = enabled DIF.enabled = enabled
data['dif_default_id'] = pid data['dif_default_id'] = pid
dif._data = DIFAdisTSSpec._db_load(execute, data) DIF._data = DIFAdisTSSpec._db_load(execute, data)
loaded.add(pid) loaded.add(pid)
new.append(dif) new.append(DIF)
data["scenario"] = scenario.parent data["scenario"] = scenario.parent
new += cls._db_load(execute, data) new += cls._db_load(execute, data)
@ -190,7 +190,7 @@ class DIFAdisTS(SQLSubModel):
b = self.b b = self.b
c = -1. c = -1.
if self.dif is not None: if self.c is not None:
c = self.c c = self.c
sql = ( sql = (
@ -201,7 +201,7 @@ class DIFAdisTS(SQLSubModel):
"VALUES (" + "VALUES (" +
f"{self.id}, '{self._db_format(self._name)}', " + f"{self.id}, '{self._db_format(self._name)}', " +
f"'{self._db_format(self._method)}', " + f"'{self._db_format(self._method)}', " +
f"{dif.id}, {b}, {c}, {self._enabled}, " + f"{dif}, {b}, {c}, {self._enabled}, " +
f"{self._status.scenario_id}" + f"{self._status.scenario_id}" +
")" ")"
) )

View File

@ -33,15 +33,15 @@ class DIFAdisTSSpec(SQLSubModel):
_id_cnt = 0 _id_cnt = 0
def __init__(self, id: int = -1, method: str = "", def __init__(self, id: int = -1, method: str = "",
status=None): status=None, owner_scenario=-1):
super(DIFAdisTSSpec, self).__init__() super(DIFAdisTSSpec, self).__init__()
self._status = status self._status = status
if id == -1: if id == -1:
self.id = DIFAdisTSSpec._id_cnt self._id = DIFAdisTSSpec._id_cnt
else: else:
self.id = id self._id = id
self._method = method self._method = method
self._reach = None self._reach = None
@ -52,7 +52,7 @@ class DIFAdisTSSpec(SQLSubModel):
self._c = None self._c = None
self._enabled = True self._enabled = True
DIFAdisTSSpec._id_cnt = max(DIFAdisTSSpec._id_cnt + 1, self.id) DIFAdisTSSpec._id_cnt = max(DIFAdisTSSpec._id_cnt + 1, self._id)
@classmethod @classmethod
def _db_create(cls, execute, ext=""): def _db_create(cls, execute, ext=""):
@ -195,7 +195,7 @@ class DIFAdisTSSpec(SQLSubModel):
new_spec.c = c new_spec.c = c
new_spec.enabled = enabled new_spec.enabled = enabled
loaded.add(pid) loaded.add(id)
new.append(new_spec) new.append(new_spec)
data["scenario"] = scenario.parent data["scenario"] = scenario.parent
@ -210,22 +210,23 @@ class DIFAdisTSSpec(SQLSubModel):
dif_default = data['dif_default_id'] dif_default = data['dif_default_id']
execute( sql = (
"INSERT INTO " + "INSERT INTO " +
"dif_adists_spec(pamhyr_id, deleted, " + "dif_adists_spec(pamhyr_id, deleted, " +
"dif_default, method, reach, " + "dif_default, method, reach, " +
"start_rk, end_rk, dif, b, c, enabled, scenario) " + "start_rk, end_rk, dif, b, c, enabled, scenario) " +
"VALUES (" + "VALUES (" +
f"{self.id}, {self._db_format(self.is_deleted())}" + f"{self.id}, {self._db_format(self.is_deleted())}, " +
f"{dif_default}, " + f"{dif_default}, " +
f"'{self._db_format(self._method)}', " + f"'{self._db_format(self._method)}', " +
f"{self._reach}, " + f"{self._reach}, " +
f"{self._start_rk}, {self._end_rk}, " + f"{self._start_rk}, {self._end_rk}, " +
f"{self._dif}, {self._b}, {self._c}, " + f"{self._dif}, {self._b}, {self._c}, " +
f"{self._enabled}" + f"{self._enabled}, " +
f"{self._status.scenario_id}" + f"{self._status.scenario_id}" +
")" ")"
) )
execute(sql)
return True return True

View File

@ -410,7 +410,7 @@ class LateralContributionAdisTS(SQLSubModel):
return len( return len(
list( list(
filter( filter(
lambda el: not el.is_deleted(), lambda el: el is not None and not el.is_deleted(),
self._data self._data
) )
) )
@ -456,7 +456,12 @@ class LateralContributionAdisTS(SQLSubModel):
@property @property
def data(self): def data(self):
return self._data.copy() return list(
filter(
lambda el: el is not None and not el.is_deleted(),
self._data
)
)
@property @property
def begin_rk(self): def begin_rk(self):
@ -497,7 +502,7 @@ class LateralContributionAdisTS(SQLSubModel):
def delete_i(self, indexes): def delete_i(self, indexes):
self._data = list( self._data = list(
map( map(
lambda e: e[1], lambda e: e[1].set_as_deleted(),
filter( filter(
lambda e: e[0] not in indexes, lambda e: e[0] not in indexes,
enumerate(self.data) enumerate(self.data)

View File

@ -425,10 +425,6 @@ class Pollutants(SQLSubModel):
execute, data=data execute, data=data
) )
new_pollutant._boundary_conditions_adists = BoundaryConditionAdisTS._db_load(
execute, data=data
)
new_pollutant._boundary_conditions_adists = ( new_pollutant._boundary_conditions_adists = (
BoundaryConditionAdisTS._db_load( BoundaryConditionAdisTS._db_load(
execute, execute,

View File

@ -845,7 +845,9 @@ class AdisTSwc(AdisTS):
# seventh line (useless) # seventh line (useless)
for k in range(0, ismax, kbl): for k in range(0, ismax, kbl):
data = np.fromfile(f, dtype=np.int32, count=1) # (start) data = np.fromfile(f, dtype=np.int32, count=1) # (start)
zero = np.fromfile(f, dtype=np.int32, count=min(k + kbl, ismax) - k) zero = np.fromfile(
f, dtype=np.int32, count=min(k + kbl, ismax) - k
)
data = np.fromfile(f, dtype=np.int32, count=1) # (end) data = np.fromfile(f, dtype=np.int32, count=1) # (end)
# end header # end header
# data # data

View File

@ -50,6 +50,22 @@ logger = logging.getLogger()
class TableModel(PamhyrTableModel): class TableModel(PamhyrTableModel):
def get_true_data_row(self, row):
if len(self._data.data) > 0:
bc = self._data.data[row]
else:
return 0
return next(
map(
lambda e: e[0],
filter(
lambda e: e[1] == bc,
enumerate(self._data._data)
)
), 0
)
def data(self, index, role): def data(self, index, role):
if role == Qt.TextAlignmentRole: if role == Qt.TextAlignmentRole:
return Qt.AlignHCenter | Qt.AlignVCenter return Qt.AlignHCenter | Qt.AlignVCenter
@ -63,6 +79,7 @@ class TableModel(PamhyrTableModel):
value = QVariant() value = QVariant()
if 0 <= column < 2: if 0 <= column < 2:
row = self.get_true_data_row(row)
v = self._data._data[row][column] v = self._data._data[row][column]
if self._data._types[column] == float: if self._data._types[column] == float:
value = f"{v:.4f}" value = f"{v:.4f}"
@ -84,6 +101,8 @@ class TableModel(PamhyrTableModel):
column = index.column() column = index.column()
try: try:
row = self.get_true_data_row(row)
self._undo.push( self._undo.push(
SetDataCommand( SetDataCommand(
self._data, row, column, value self._data, row, column, value
@ -110,14 +129,20 @@ class TableModel(PamhyrTableModel):
def delete(self, rows, parent=QModelIndex()): def delete(self, rows, parent=QModelIndex()):
self.beginRemoveRows(parent, rows[0], rows[-1]) self.beginRemoveRows(parent, rows[0], rows[-1])
_rows = list(
map(
lambda r: self.get_true_data_row(r),
rows
)
)
self._undo.push( self._undo.push(
DelCommand( DelCommand(
self._data, rows self._data, _rows
) )
) )
self.endRemoveRows() self.endRemoveRows()
self.layoutChanged.emit()
def sort(self, _reverse, parent=QModelIndex()): def sort(self, _reverse, parent=QModelIndex()):
self.layoutAboutToBeChanged.emit() self.layoutAboutToBeChanged.emit()

View File

@ -80,10 +80,11 @@ class DelCommand(QUndoCommand):
def undo(self): def undo(self):
for row, el in self._bc: for row, el in self._bc:
self._data.insert(row, el) el.set_as_not_deleted()
def redo(self): def redo(self):
self._data.delete_i(self._rows) for row, el in self._bc:
el.set_as_deleted()
class PasteCommand(QUndoCommand): class PasteCommand(QUndoCommand):

View File

@ -43,7 +43,7 @@ from View.Tools.PamhyrTable import PamhyrTableModel
from View.BoundaryConditionsAdisTS.UndoCommand import ( from View.BoundaryConditionsAdisTS.UndoCommand import (
SetNodeCommand, SetTypeCommand, SetNodeCommand, SetTypeCommand,
AddCommand, DelCommand, SetPolCommand AddCommand, DelCommand
) )
from View.BoundaryCondition.translate import BC_types from View.BoundaryCondition.translate import BC_types

View File

@ -62,22 +62,6 @@ class SetTypeCommand(QUndoCommand):
self._bcs.get(self._index).type = self._new self._bcs.get(self._index).type = self._new
class SetPolCommand(QUndoCommand):
def __init__(self, bcs, index, pollutant):
QUndoCommand.__init__(self)
self._bcs = bcs
self._index = index
self._old = self._bcs.get(self._index).pollutant
self._new = pollutant
def undo(self):
self._bcs.get(self._index).pollutant = self._old
def redo(self):
self._bcs.get(self._index).pollutant = self._new
class AddCommand(QUndoCommand): class AddCommand(QUndoCommand):
def __init__(self, pollutant, bcs, index): def __init__(self, pollutant, bcs, index):
QUndoCommand.__init__(self) QUndoCommand.__init__(self)
@ -106,7 +90,7 @@ class DelCommand(QUndoCommand):
self._bc = [] self._bc = []
for row in rows: for row in rows:
self._bc.append((row, self._bcs.get(row))) self._bc.append((row, self._bcs._lst[row]))
self._bc.sort() self._bc.sort()
def undo(self): def undo(self):

View File

@ -62,9 +62,12 @@ class ComboBoxDelegate(QItemDelegate):
if self._mode == "rk": if self._mode == "rk":
reach_id = self._d90_spec_lst[index.row()].reach reach_id = self._d90_spec_lst[index.row()].reach
reach = next(filter( reach = next(
filter(
lambda edge: edge.id == reach_id, self._data.edges() lambda edge: edge.id == reach_id, self._data.edges()
)) ),
None
)
if reach_id is not None: if reach_id is not None:
val = list( val = list(
@ -116,6 +119,8 @@ class D90TableModel(PamhyrTableModel):
super(D90TableModel, self).__init__(data=data, **kwargs) super(D90TableModel, self).__init__(data=data, **kwargs)
self._data = data self._data = data
if self._undo is not None:
self._undo.indexChanged.connect(lambda _: self.update())
def _setup_lst(self): def _setup_lst(self):
self._lst = list( self._lst = list(
@ -216,7 +221,8 @@ class D90TableModel(PamhyrTableModel):
DelCommand( DelCommand(
self._data, self._data,
self._data._data, self._data._data,
[data_rows[id(self._lst[row])] for row in rows] [data_rows[id(self._lst[row])] for row in rows
if 0 <= row < len(self._lst)]
) )
) )
@ -226,8 +232,10 @@ class D90TableModel(PamhyrTableModel):
def undo(self): def undo(self):
self._undo.undo() self._undo.undo()
self._setup_lst()
self.layoutChanged.emit() self.layoutChanged.emit()
def redo(self): def redo(self):
self._undo.redo() self._undo.redo()
self._setup_lst()
self.layoutChanged.emit() self.layoutChanged.emit()

View File

@ -43,7 +43,7 @@ from PyQt5.QtWidgets import (
from Modules import Modules from Modules import Modules
from View.InitialConditionsAdisTS.UndoCommand import ( from View.D90AdisTS.UndoCommand import (
SetCommand, SetCommand,
) )
@ -264,11 +264,27 @@ class D90AdisTSWindow(PamhyrWindow):
self._update() self._update()
def _undo(self): def _undo(self):
undo_stack = self._undo_stack
if undo_stack is None or not undo_stack.canUndo():
return
if isinstance(undo_stack.command(undo_stack.index() - 1), SetCommand):
self._table.undo() self._table.undo()
else:
self._table_spec.undo()
self._update() self._update()
def _redo(self): def _redo(self):
undo_stack = self._undo_stack
if undo_stack is None or not undo_stack.canRedo():
return
if isinstance(undo_stack.command(undo_stack.index()), SetCommand):
self._table.redo() self._table.redo()
else:
self._table_spec.redo()
self._update() self._update()
def add(self): def add(self):

View File

@ -46,25 +46,28 @@ _translate = QCoreApplication.translate
class ComboBoxDelegate(QItemDelegate): class ComboBoxDelegate(QItemDelegate):
def __init__(self, data=None, ic_spec_lst=None, def __init__(self, data=None, dif_spec_lst=None,
trad=None, parent=None, mode="reaches"): trad=None, parent=None, mode="reaches"):
super(ComboBoxDelegate, self).__init__(parent) super(ComboBoxDelegate, self).__init__(parent)
self._data = data self._data = data
self._mode = mode self._mode = mode
self._trad = trad self._trad = trad
self._ic_spec_lst = ic_spec_lst self._dif_spec_lst = dif_spec_lst
def createEditor(self, parent, option, index): def createEditor(self, parent, option, index):
self.editor = QComboBox(parent) self.editor = QComboBox(parent)
val = [] val = []
if self._mode == "rk": if self._mode == "rk":
reach_id = self._ic_spec_lst[index.row()].reach reach_id = self._dif_spec_lst[index.row()].reach
reach = next(filter( reach = next(
filter(
lambda edge: edge.id == reach_id, self._data.edges() lambda edge: edge.id == reach_id, self._data.edges()
)) ),
None
)
if reach_id is not None: if reach_id is not None:
val = list( val = list(
@ -118,9 +121,16 @@ class DIFTableModel(PamhyrTableModel):
super(DIFTableModel, self).__init__(data=data, **kwargs) super(DIFTableModel, self).__init__(data=data, **kwargs)
self._data = data self._data = data
if self._undo is not None:
self._undo.indexChanged.connect(lambda _: self.update())
def _setup_lst(self): def _setup_lst(self):
self._lst = self._data._data self._lst = list(
filter(
lambda dif: dif._deleted is False,
self._data._data
)
)
def rowCount(self, parent): def rowCount(self, parent):
return len(self._lst) return len(self._lst)
@ -183,7 +193,10 @@ class DIFTableModel(PamhyrTableModel):
if self._headers[column] != "reach": if self._headers[column] != "reach":
self._undo.push( self._undo.push(
SetCommandSpec( SetCommandSpec(
self._lst, row, self._headers[column], value self._lst,
row,
self._headers[column],
value
) )
) )
elif self._headers[column] == "reach": elif self._headers[column] == "reach":
@ -211,25 +224,34 @@ class DIFTableModel(PamhyrTableModel):
) )
) )
self._setup_lst()
self.endInsertRows() self.endInsertRows()
self.layoutChanged.emit() self.layoutChanged.emit()
def delete(self, rows, parent=QModelIndex()): def delete(self, rows, parent=QModelIndex()):
self.beginRemoveRows(parent, rows[0], rows[-1]) self.beginRemoveRows(parent, rows[0], rows[-1])
data_rows = {
id(dif): i for i, dif in enumerate(self._data._data)
}
self._undo.push( self._undo.push(
DelCommand( DelCommand(
self._data, self._lst, rows self._data,
self._data._data,
[data_rows[id(self._lst[row])] for row in rows
if 0 <= row < len(self._lst)]
) )
) )
self._setup_lst()
self.endRemoveRows() self.endRemoveRows()
self.layoutChanged.emit() self.layoutChanged.emit()
def undo(self): def undo(self):
self._undo.undo() self._undo.undo()
self._setup_lst()
self.layoutChanged.emit() self.layoutChanged.emit()
def redo(self): def redo(self):
self._undo.redo() self._undo.redo()
self._setup_lst()
self.layoutChanged.emit() self.layoutChanged.emit()

View File

@ -136,11 +136,11 @@ class SetCommandSpec(QUndoCommand):
class AddCommand(QUndoCommand): class AddCommand(QUndoCommand):
def __init__(self, data, ics_spec, index): def __init__(self, data, dif_spec, index):
QUndoCommand.__init__(self) QUndoCommand.__init__(self)
self._data = data self._data = data
self._ics_spec = ics_spec self._dif_spec = dif_spec
self._index = index self._index = index
self._new = None self._new = None
@ -155,21 +155,20 @@ class AddCommand(QUndoCommand):
class DelCommand(QUndoCommand): class DelCommand(QUndoCommand):
def __init__(self, data, ics_spec, rows): def __init__(self, data, dif_spec, rows):
QUndoCommand.__init__(self) QUndoCommand.__init__(self)
self._data = data self._data = data
self._ics_spec = ics_spec self._dif_spec = dif_spec
self._rows = rows self._rows = rows
# self._data = data
self._ic = [] self._dif = []
for row in rows: for row in rows:
self._ic.append((row, self._ics_spec[row])) self._dif.append((row, self._dif_spec[row]))
self._ic.sort() self._dif.sort()
def undo(self): def undo(self):
for row, el in self._ic: for row, el in self._dif:
self._data.insert(row, el) self._data.insert(row, el)
def redo(self): def redo(self):

View File

@ -51,6 +51,8 @@ from View.DIFAdisTS.Table import (
DIFTableModel, ComboBoxDelegate, DIFTableModel, ComboBoxDelegate,
) )
from View.DIFAdisTS.UndoCommand import SetCommand
from View.DIFAdisTS.translate import DIFAdisTSTranslate from View.DIFAdisTS.translate import DIFAdisTSTranslate
from Solver.Mage import Mage8 from Solver.Mage import Mage8
@ -100,7 +102,7 @@ class DIFAdisTSWindow(PamhyrWindow):
self._delegate_method = ComboBoxDelegate( self._delegate_method = ComboBoxDelegate(
trad=self._trad, trad=self._trad,
data=self._study.river, data=self._study.river,
ic_spec_lst=self._data[0]._data, dif_spec_lst=self._data[0]._data,
parent=self, parent=self,
mode="method" mode="method"
) )
@ -144,14 +146,14 @@ class DIFAdisTSWindow(PamhyrWindow):
self._delegate_reach = ComboBoxDelegate( self._delegate_reach = ComboBoxDelegate(
trad=self._trad, trad=self._trad,
data=self._study.river, data=self._study.river,
ic_spec_lst=self._data[0]._data, dif_spec_lst=self._data[0]._data,
parent=self, parent=self,
mode="reaches" mode="reaches"
) )
self._delegate_rk = ComboBoxDelegate( self._delegate_rk = ComboBoxDelegate(
trad=self._trad, trad=self._trad,
data=self._study.river, data=self._study.river,
ic_spec_lst=self._data[0]._data, dif_spec_lst=self._data[0]._data,
parent=self, parent=self,
mode="rk" mode="rk"
) )
@ -272,11 +274,25 @@ class DIFAdisTSWindow(PamhyrWindow):
self._update() self._update()
def _undo(self): def _undo(self):
undo_stack = self._undo_stack
if undo_stack is None or not undo_stack.canUndo():
return
if isinstance(undo_stack.command(undo_stack.index() - 1), SetCommand):
self._table.undo() self._table.undo()
else:
self._table_spec.undo()
self._update() self._update()
def _redo(self): def _redo(self):
undo_stack = self._undo_stack
if undo_stack is None or not undo_stack.canRedo():
return
if isinstance(undo_stack.command(undo_stack.index()), SetCommand):
self._table.redo() self._table.redo()
else:
self._table_spec.redo()
self._update() self._update()
def add(self): def add(self):

View File

@ -245,8 +245,10 @@ class InitialConditionTableModel(PamhyrTableModel):
def undo(self): def undo(self):
self._undo.undo() self._undo.undo()
self._setup_lst()
self.layoutChanged.emit() self.layoutChanged.emit()
def redo(self): def redo(self):
self._undo.redo() self._undo.redo()
self._setup_lst()
self.layoutChanged.emit() self.layoutChanged.emit()

View File

@ -273,11 +273,27 @@ class InitialConditionsAdisTSWindow(PamhyrWindow):
self._update() self._update()
def _undo(self): def _undo(self):
undo_stack = self._undo_stack
if undo_stack is None or not undo_stack.canUndo():
return
if isinstance(undo_stack.command(undo_stack.index() - 1), SetCommand):
self._table.undo() self._table.undo()
else:
self._table_spec.undo()
self._update() self._update()
def _redo(self): def _redo(self):
undo_stack = self._undo_stack
if undo_stack is None or not undo_stack.canRedo():
return
if isinstance(undo_stack.command(undo_stack.index()), SetCommand):
self._table.redo() self._table.redo()
else:
self._table_spec.redo()
self._update() self._update()
def add(self): def add(self):

View File

@ -52,6 +52,23 @@ logger = logging.getLogger()
class TableModel(PamhyrTableModel): class TableModel(PamhyrTableModel):
def get_true_data_row(self, row):
if len(self._data.data) > 0:
lc = self._data.data[row]
else:
return 0
return next(
map(
lambda e: e[0],
filter(
lambda e: e[1] == lc,
enumerate(self._data._data)
)
), 0
)
def data(self, index, role): def data(self, index, role):
if role == Qt.TextAlignmentRole: if role == Qt.TextAlignmentRole:
return Qt.AlignHCenter | Qt.AlignVCenter return Qt.AlignHCenter | Qt.AlignVCenter
@ -65,6 +82,7 @@ class TableModel(PamhyrTableModel):
value = QVariant() value = QVariant()
if 0 <= column < 2: if 0 <= column < 2:
row = self.get_true_data_row(row)
v = self._data._data[row][column] v = self._data._data[row][column]
if self._data._types[column] == float: if self._data._types[column] == float:
value = f"{v:.4f}" value = f"{v:.4f}"
@ -86,6 +104,8 @@ class TableModel(PamhyrTableModel):
column = index.column() column = index.column()
try: try:
row = self.get_true_data_row(row)
self._undo.push( self._undo.push(
SetDataCommand( SetDataCommand(
self._data, row, column, value self._data, row, column, value
@ -113,10 +133,18 @@ class TableModel(PamhyrTableModel):
def delete(self, rows, parent=QModelIndex()): def delete(self, rows, parent=QModelIndex()):
self.beginRemoveRows(parent, rows[0], rows[-1]) self.beginRemoveRows(parent, rows[0], rows[-1])
_rows = list(
map(
lambda r: self.get_true_data_row(r),
rows
)
)
self._undo.push( self._undo.push(
DelCommand( DelCommand(
self._data, rows self._data, _rows
) )
) )
self.endRemoveRows() self.endRemoveRows()
self.layoutChanged.emit()

View File

@ -76,8 +76,8 @@ class DelCommand(QUndoCommand):
def undo(self): def undo(self):
for row, el in self._lc: for row, el in self._lc:
self._data._data.insert(row, el) el.set_as_not_deleted()
def redo(self): def redo(self):
for row in self._rows: for row, el in self._lc:
del self._data._data[row] el.set_as_deleted()

View File

@ -91,7 +91,7 @@ class AddCommand(QUndoCommand):
self._new = None self._new = None
def undo(self): def undo(self):
self._lcs.delete_i(self._index) self._lcs.delete_i([self._index])
def redo(self): def redo(self):
if self._new is None: if self._new is None:

View File

@ -321,7 +321,7 @@ def timestamp_to_old_pamhyr_date_adists(time: int):
minutes = (dt.seconds % 3600) // 60 minutes = (dt.seconds % 3600) // 60
seconds = dt.seconds % 60 seconds = dt.seconds % 60
s = f"{dt.days:>3}:{hours:>2}:{minutes:>2}" s = f"{dt.days:>3}:{hours:>2}:{minutes:>2}:{seconds:>2}"
s = s.replace(" ", "0") s = s.replace(" ", "0")
return s return s