diff --git a/src/View/BoundaryCondition/Edit/Table.py b/src/View/BoundaryCondition/Edit/Table.py index 5a73fd78..363aa19f 100644 --- a/src/View/BoundaryCondition/Edit/Table.py +++ b/src/View/BoundaryCondition/Edit/Table.py @@ -143,21 +143,43 @@ class TableModel(PamhyrTableModel): self.update() def delete(self, rows, parent=QModelIndex()): - self.beginRemoveRows(parent, rows[0], rows[-1]) + if not rows: + return - rows = list(map( - lambda r: self.get_true_data_row(r), - rows)) + rows = sorted(set(rows)) + rows = [ + self.get_true_data_row(row) + for row in rows + ] - self._undo.push( - DelCommand( - self._data, rows + # A multiple selection may contain non-contiguous rows. A model reset + # accurately represents this atomic undo command, unlike one + # beginRemoveRows() call spanning rows that are not all removed. + self.beginResetModel() + try: + self._undo.push( + DelCommand( + self._data, rows + ) ) - ) - - self.endRemoveRows() + finally: + self.endResetModel() self.update() + def undo(self): + self.beginResetModel() + try: + self._undo.undo() + finally: + self.endResetModel() + + def redo(self): + self.beginResetModel() + try: + self._undo.redo() + finally: + self.endResetModel() + def sort(self, _reverse, parent=QModelIndex()): self.layoutAboutToBeChanged.emit() diff --git a/src/View/BoundaryCondition/Edit/UndoCommand.py b/src/View/BoundaryCondition/Edit/UndoCommand.py index 06b598a1..82c2bca5 100644 --- a/src/View/BoundaryCondition/Edit/UndoCommand.py +++ b/src/View/BoundaryCondition/Edit/UndoCommand.py @@ -97,12 +97,11 @@ class DelCommand(QUndoCommand): QUndoCommand.__init__(self) self._data = data - self._rows = rows - - self._bc = [] - for row in rows: - self._bc.append(self._data.get_i(row)) - self._bc.sort() + self._rows = sorted(set(rows)) + self._bc = [ + self._data.get_i(row) + for row in self._rows + ] def undo(self): for el in self._bc: @@ -120,13 +119,17 @@ class SortCommand(QUndoCommand): self._data = data self._reverse = _reverse - self._old = self._data.data - self._indexes = None + # Keep the order of the complete underlying list, including soft + # deleted items. ``data`` only exposes visible items and therefore + # cannot reliably restore a sort after a delete/undelete operation. + self._old_positions = { + id(item): index + for index, item in enumerate(self._data._data) + } def undo(self): - ll = self._data.data self._data.sort( - key=lambda x: self._indexes[ll.index(x)] + key=lambda item: self._old_positions[id(item)] ) def redo(self): @@ -134,14 +137,6 @@ class SortCommand(QUndoCommand): _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 class MoveCommand(QUndoCommand):