From 516efb64e85813c74e58085161d736c82c670c91 Mon Sep 17 00:00:00 2001 From: Dylan Jeannin Date: Tue, 28 Jul 2026 13:50:21 +0200 Subject: [PATCH] WeatherParam: SetData targets the object, and no longer the line index in the tab, which reduces the risk of error with multiple QUndoCommand, and rewrite of the logic for the other UndoCommand --- .../WeatherParameters/WeatherParameters.py | 51 ++++++++---- src/View/Geometry/Window.py | 13 +++ src/View/WeatherParameters/Edit/Table.py | 23 ++---- .../WeatherParameters/Edit/UndoCommand.py | 80 +++++++++---------- 4 files changed, 91 insertions(+), 76 deletions(-) diff --git a/src/Model/WeatherParameters/WeatherParameters.py b/src/Model/WeatherParameters/WeatherParameters.py index b3637636..eb3a2068 100644 --- a/src/Model/WeatherParameters/WeatherParameters.py +++ b/src/Model/WeatherParameters/WeatherParameters.py @@ -636,14 +636,38 @@ class WeatherParameters(SQLSubModel): def add(self, index: int): value = Data(self._default_0, self._default_1, status=self._status) - self._data.insert(index, value) - self.modified() + self.insert(index, value) return value def insert(self, index: int, value): + visible_data = self.data + if index < len(visible_data): + index = self._data.index(visible_data[index]) + else: + index = len(self._data) self._data.insert(index, value) self.modified() + def set_data_value(self, value, column, data): + value[column] = self._types[column](data) + self.modified() + + def set_deleted(self, values, deleted): + for value in values: + if deleted: + value.set_as_deleted() + else: + value.set_as_not_deleted() + self.modified() + + def reorder(self, values): + values = iter(values) + self._data = [ + value if value.is_deleted() else next(values) + for value in self._data + ] + self.modified() + def delete_i(self, indexes): self._data = list( map( @@ -692,10 +716,7 @@ class WeatherParameters(SQLSubModel): return lst def _set_i_c_v(self, index, column, value): - v = self._data[index] - v[column] = self._types[column](value) - self._data[index] = v - self.modified() + self.set_data_value(self.get_i(index), column, value) def set_i_0(self, index: int, value): self._set_i_c_v(index, 0, value) @@ -726,15 +747,13 @@ class WeatherParameters(SQLSubModel): return new def move_up(self, index): - if index < len(self): - next = index - 1 - d = self._data - d[index], d[next] = d[next], d[index] - self.modified() + if 0 < index < len(self): + data = self.data + data[index - 1], data[index] = data[index], data[index - 1] + self.reorder(data) def move_down(self, index): - if index >= 0: - prev = index + 1 - d = self._data - d[index], d[prev] = d[prev], d[index] - self.modified() + if 0 <= index < len(self) - 1: + data = self.data + data[index], data[index + 1] = data[index + 1], data[index] + self.reorder(data) diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index 0827a094..645a7c07 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -102,6 +102,7 @@ class GeometryWindow(PamhyrWindow): self.setup_plots() self.setup_statusbar() self.setup_connections() + self.update_meshing_action() def setup_table(self): if self._study.is_read_only(): @@ -231,7 +232,16 @@ class GeometryWindow(PamhyrWindow): def update_redraw(self): self._update(redraw=True) + def update_meshing_action(self): + enabled = ( + not self._study.is_read_only() + and self._reach.number_profiles > 0 + ) + self.find(QAction, "action_meshing").setEnabled(enabled) + def _update(self, redraw=False, propagate=True): + self.update_meshing_action() + if redraw: self._plot_xy.redraw(data=self._reach) self._plot_rkc.redraw(data=self._reach) @@ -302,6 +312,9 @@ class GeometryWindow(PamhyrWindow): self.tableView.model().blockSignals(False) def edit_meshing(self): + if self._reach.number_profiles == 0: + return + rows = list( set( (i.row() for i in self.tableView.selectedIndexes()) diff --git a/src/View/WeatherParameters/Edit/Table.py b/src/View/WeatherParameters/Edit/Table.py index 996ef4b7..a77b0e2d 100644 --- a/src/View/WeatherParameters/Edit/Table.py +++ b/src/View/WeatherParameters/Edit/Table.py @@ -145,35 +145,24 @@ class TableModel(PamhyrTableModel): if row <= 0: return - target = row + 2 - - self.beginMoveRows(parent, row - 1, row - 1, parent, target) - - self._undo_stack.push( + self.layoutAboutToBeChanged.emit() + self._undo.push( MoveCommand( self._data, "up", row ) ) - - self.endMoveRows() self.update() - def move_down(self, index, parent=QModelIndex()): - row = index.row() - if row >= len(self._data): + def move_down(self, row, parent=QModelIndex()): + if row < 0 or row >= len(self._data) - 1: return - target = row - - self.beginMoveRows(parent, row + 1, row + 1, parent, target) - - self._undo_stack.push( + self.layoutAboutToBeChanged.emit() + self._undo.push( MoveCommand( self._data, "down", row ) ) - - self.endMoveRows() self.update() def paste(self, row, header, data): diff --git a/src/View/WeatherParameters/Edit/UndoCommand.py b/src/View/WeatherParameters/Edit/UndoCommand.py index f18eab7f..a8164fac 100644 --- a/src/View/WeatherParameters/Edit/UndoCommand.py +++ b/src/View/WeatherParameters/Edit/UndoCommand.py @@ -31,17 +31,17 @@ class SetDataCommand(QUndoCommand): QUndoCommand.__init__(self) self._data = data - self._index = index + self._value = self._data.get_i(index) self._column = column - self._old = self._data.get_i(self._index)[self._column] + self._old = self._value[self._column] _type = self._data.get_type_column(self._column) self._new = _type(new_value) def undo(self): - self._data._set_i_c_v(self._index, self._column, self._old) + self._data.set_data_value(self._value, self._column, self._old) def redo(self): - self._data._set_i_c_v(self._index, self._column, self._new) + self._data.set_data_value(self._value, self._column, self._new) class AddCommand(QUndoCommand): @@ -53,13 +53,13 @@ class AddCommand(QUndoCommand): self._new = None def undo(self): - self._data.delete_i([self._index]) + self._data.set_deleted([self._new], True) def redo(self): if self._new is None: self._new = self._data.add(self._index) else: - self._data.insert(self._index, self._new) + self._data.set_deleted([self._new], False) class DelCommand(QUndoCommand): @@ -75,10 +75,10 @@ class DelCommand(QUndoCommand): self._wp.sort() def undo(self): - self._data.set_as_not_deleted_i(self._rows) + self._data.set_deleted([wp for row, wp in self._wp], False) def redo(self): - self._data.set_as_deleted_i(self._rows) + self._data.set_deleted([wp for row, wp in self._wp], True) class SortCommand(QUndoCommand): @@ -89,27 +89,17 @@ class SortCommand(QUndoCommand): self._reverse = _reverse self._old = self._data.data - self._indexes = None + self._new = sorted( + self._old, + key=lambda value: value[0], + reverse=self._reverse + ) def undo(self): - ll = self._data.data - self._data.sort( - key=lambda x: self._indexes[ll.index(x)] - ) + self._data.reorder(self._old) def redo(self): - self._data.sort( - _reverse=self._reverse, - key=lambda x: x[0] - ) - if self._indexes is None: - self._indexes = list( - map( - lambda p: self._old.index(p), - self._data.data - ) - ) - self._old = None + self._data.reorder(self._new) class MoveCommand(QUndoCommand): @@ -117,20 +107,16 @@ class MoveCommand(QUndoCommand): QUndoCommand.__init__(self) self._data = data - self._up = up == "up" - self._i = i + self._old = self._data.data + self._new = self._old.copy() + other = i - 1 if up == "up" else i + 1 + self._new[i], self._new[other] = self._new[other], self._new[i] def undo(self): - if self._up: - self._data.move_up(self._i) - else: - self._data.move_down(self._i) + self._data.reorder(self._old) def redo(self): - if self._up: - self._data.move_up(self._i) - else: - self._data.move_down(self._i) + self._data.reorder(self._new) class PasteCommand(QUndoCommand): @@ -141,15 +127,18 @@ class PasteCommand(QUndoCommand): self._row = row self._wps = list(wps) self._wps.reverse() + self._inserted = False def undo(self): - self._data.delete_i( - range(self._row, self._row + len(self._wps)) - ) + self._data.set_deleted(self._wps, True) def redo(self): - for wp in self._wps: - self._data.insert(self._row, wp) + if not self._inserted: + for wp in self._wps: + self._data.insert(self._row, wp) + self._inserted = True + else: + self._data.set_deleted(self._wps, False) class DuplicateCommand(QUndoCommand): @@ -160,10 +149,15 @@ class DuplicateCommand(QUndoCommand): self._rows = rows self._wp = deepcopy(bc) self._wp.reverse() + self._inserted = False def undo(self): - self._data.delete(self._wp) + self._data.set_deleted(self._wp, True) def redo(self): - for bc in self._wp: - self._data.insert(self._rows[0], bc) + if not self._inserted: + for bc in self._wp: + self._data.insert(self._rows[0], bc) + self._inserted = True + else: + self._data.set_deleted(self._wp, False)