diff --git a/src/Model/BoundaryCondition/BoundaryCondition.py b/src/Model/BoundaryCondition/BoundaryCondition.py index 0c401b75..37f00750 100644 --- a/src/Model/BoundaryCondition/BoundaryCondition.py +++ b/src/Model/BoundaryCondition/BoundaryCondition.py @@ -341,7 +341,7 @@ class BoundaryCondition(SQLSubModel): owner_scenario=owner_scenario ) if deleted: - f.set_as_deleted() + bc.set_as_deleted() bc.node = None if node != -1: @@ -549,6 +549,12 @@ class BoundaryCondition(SQLSubModel): self.modified() + def undelete(self, els): + for el in els: + el.set_as_not_deleted() + + self.modified() + def sort(self, _reverse=False, key=None): if key is None: self._data.sort(reverse=_reverse) diff --git a/src/Model/SedimentLayer/SedimentLayer.py b/src/Model/SedimentLayer/SedimentLayer.py index 7c32ec94..a81fb3a0 100644 --- a/src/Model/SedimentLayer/SedimentLayer.py +++ b/src/Model/SedimentLayer/SedimentLayer.py @@ -33,10 +33,12 @@ class Layer(SQLSubModel): type="", height=0.0, d50=0.0, sigma=0.0, critical_constraint=0.0, - sl=None, status=None): - super(Layer, self).__init__(id) - - self._status = status + sl=None, status=None, + owner_scenario=-1): + super(Layer, self).__init__( + id=id, status=status, + owner_scenario=owner_scenario + ) self._name = name self._type = type @@ -102,6 +104,7 @@ class Layer(SQLSubModel): execute(f""" CREATE TABLE sedimentary_layer_layer{ext} ( {cls.create_db_add_pamhyr_id()}, + deleted BOOLEAN NOT NULL DEFAULT FALSE, ind INTEGER NOT NULL, name TEXT NOT NULL, type TEXT NOT NULL, @@ -129,6 +132,13 @@ class Layer(SQLSubModel): else: cls._db_update_to_0_1_0(execute, data) + if major == "0" and minor == "1": + if int(release) < 2: + execute( + "ALTER TABLE sedimentary_layer_layer " + + "ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE" + ) + return cls._update_submodel(execute, version, data) @classmethod @@ -176,12 +186,19 @@ class Layer(SQLSubModel): def _db_load(cls, execute, data=None): new = [] sl = data["sl"] + scenario = data["scenario"] + loaded = data['loaded_pid'] + + if scenario is None: + return new table = execute( - "SELECT pamhyr_id, name, type, height, " + - "d50, sigma, critical_constraint " + + "SELECT pamhyr_id, deleted, name, type, height, " + + "d50, sigma, critical_constraint, scenario " + "FROM sedimentary_layer_layer " + f"WHERE sl = {sl} " + + f"AND scenario = {scenario.id} " + + f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) " + "ORDER BY ind ASC" ) @@ -189,38 +206,55 @@ class Layer(SQLSubModel): it = iter(row) pid = next(it) + deleted = (next(it) == 1) name = next(it) type = next(it) height = next(it) d50 = next(it) sigma = next(it) critical_constraint = next(it) + owner_scenario = next(it) layer = cls( id=pid, name=name, type=type, height=height, d50=d50, sigma=sigma, critical_constraint=critical_constraint, - sl=sl, status=data['status'] + sl=sl, status=data['status'], + owner_scenario=owner_scenario ) + if deleted: + layer.set_as_deleted() + loaded.add(pid) new.append(layer) + data["scenario"] = scenario.parent + new += cls._db_load(execute, data) + data["scenario"] = scenario + return new def _db_save(self, execute, data=None): + if not self.must_be_saved(): + return True + ind = data["ind"] sl = data["sl"] execute( "INSERT INTO " + - "sedimentary_layer_layer(pamhyr_id, ind, name, type, height, " + - "d50, sigma, critical_constraint, sl) " + + "sedimentary_layer_layer(" + + "pamhyr_id, deleted, ind, name, type, height, " + + "d50, sigma, critical_constraint, sl, scenario" + + ") " + "VALUES (" + - f"{self.pamhyr_id}, {ind}, '{self._db_format(self._name)}', " + + f"{self.pamhyr_id}, {self._db_format(self.is_deleted())}, " + + f"{ind}, '{self._db_format(self._name)}', " + f"'{self._db_format(self._type)}', {self._height}, " + f"{self._d50}, {self._sigma}, {self._critical_constraint}, " + - f"{sl.pamhyr_id}" + + f"{sl.pamhyr_id}, " + + f"{self._status.scenario_id}" + ")" ) @@ -232,10 +266,12 @@ class SedimentLayer(SQLSubModel): def __init__(self, id: int = -1, name: str = "", comment: str = "", - status=None): - super(SedimentLayer, self).__init__(id) + status=None, owner_scenario=-1): + super(SedimentLayer, self).__init__( + id=id, status=status, + owner_scenario=owner_scenario + ) - self._status = status self._name = name self._comment = comment self._layers = [] @@ -249,15 +285,28 @@ class SedimentLayer(SQLSubModel): return s def __len__(self): - return len(self._layers) + return len( + list( + filter( + lambda el: not el.is_deleted(), + self._layers + ) + ) + ) @property def layers(self): - return self._layers.copy() + return list( + filter( + lambda el: not el.is_deleted(), + self._layers + ) + ) def height(self): return list( - map(lambda layer: layer.height, self._layers) + map(lambda layer: layer.height, + self.layers) ) @property @@ -273,7 +322,10 @@ class SedimentLayer(SQLSubModel): def names(self): return list( - map(lambda layer: layer.name, self._layers) + map( + lambda layer: layer.name, + self.layers + ) ) @property @@ -289,6 +341,7 @@ class SedimentLayer(SQLSubModel): execute(f""" CREATE TABLE sedimentary_layer{ext} ( {cls.create_db_add_pamhyr_id()}, + deleted BOOLEAN NOT NULL DEFAULT FALSE, name TEXT NOT NULL, comment TEXT NOT NULL, {Scenario.create_db_add_scenario()}, @@ -312,6 +365,13 @@ class SedimentLayer(SQLSubModel): else: cls._db_update_to_0_1_0(execute, data) + if major == "0" and minor == "1": + if int(release) < 2: + execute( + "ALTER TABLE sedimentary_layer " + + "ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE" + ) + return cls._update_submodel(execute, version, data) @classmethod @@ -336,36 +396,64 @@ class SedimentLayer(SQLSubModel): @classmethod def _db_load(cls, execute, data=None): new = [] + scenario = data["scenario"] + loaded = data['loaded_pid'] + + if scenario is None: + return new table = execute( - "SELECT pamhyr_id, name, comment " + - "FROM sedimentary_layer " + "SELECT pamhyr_id, deleted, name, comment, scenario " + + "FROM sedimentary_layer " + + f"WHERE scenario = {scenario.id} " + + f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) " ) for row in table: + it = iter(row) + + pid = next(it) + deleted = (next(it) == 1) + name = next(it) + comment = next(it) + owner_scenario = next(it) + sl = cls( - id=row[0], - name=row[1], - comment=row[2], - status=data['status'] + id=pid, + name=name, + comment=comment, + status=data['status'], + owner_scenario=owner_scenario ) + if deleted: + sl.set_as_deleted() data["sl"] = sl.id sl._layers = Layer._db_load(execute, data) + loaded.add(pid) new.append(sl) + data["scenario"] = scenario.parent + new += cls._db_load(execute, data) + data["scenario"] = scenario + return new def _db_save(self, execute, data=None): - if data is None: - data = {} + if not self.must_be_saved(): + return True execute( - "INSERT INTO sedimentary_layer (pamhyr_id, name, comment) " + - f"VALUES ({self.pamhyr_id}, " + + "INSERT INTO sedimentary_layer (" + + "pamhyr_id, deleted, name, comment, scenario" + + ") " + + "VALUES (" + + f"{self._pamhyr_id}, {self._db_format(self.is_deleted())}, " + f"'{self._db_format(self._name)}', " + - f"'{self._db_format(self._comment)}')" + f"'{self._db_format(self._comment)}', " + + f"{self._status.scenario_id}" + + ")" ) data["sl"] = self @@ -379,38 +467,45 @@ class SedimentLayer(SQLSubModel): return True def get(self, index): - return self._layers[index] + return self.layers[index] - def set(self, index, new): - self._layers[index] = new - self._status.modified() + # def set(self, index, new): + # self._layers[index] = new + # self.modified() def insert(self, index, new): self._layers.insert(index, new) - self._status.modified() + self.modified() def new(self, index): n = Layer(sl=self, status=self._status) self.insert(index, n) - self._status.modified() + self.modified() return n + def undelete(self, els): + for el in els: + el.set_as_not_deleted() + + self.modified() + def delete(self, els): for el in els: - self._layers.remove(el) - self._status.modified() + el.set_as_deleted() + + self.modified() def delete_i(self, indexes): - els = list( + list( map( - lambda x: x[1], + lambda e: e[1].set_as_deleted(), filter( - lambda x: x[0] in indexes, + lambda e: e[0] in indexes, enumerate(self._layers) ) ) ) - self.delete(els) + self.modified() def move_up(self, index): if index >= 0: @@ -419,7 +514,7 @@ class SedimentLayer(SQLSubModel): lst = self._layers lst[index], lst[next] = lst[next], lst[index] - self._status.modified() + self.modified() def move_down(self, index): if index + 1 < len(self._layers): @@ -428,7 +523,7 @@ class SedimentLayer(SQLSubModel): lst = self._layers lst[index], lst[prev] = lst[prev], lst[index] - self._status.modified() + self.modified() def compute_height_from_bottom(self, bottom_elevation: list): sl_height = self.height() diff --git a/src/Model/SedimentLayer/SedimentLayerList.py b/src/Model/SedimentLayer/SedimentLayerList.py index 5e429c95..55acc177 100644 --- a/src/Model/SedimentLayer/SedimentLayerList.py +++ b/src/Model/SedimentLayer/SedimentLayerList.py @@ -19,7 +19,7 @@ from tools import trace, timer from Model.Except import NotImplementedMethodeError -from Model.Tools.PamhyrList import PamhyrModelList +from Model.Tools.PamhyrListExt import PamhyrModelList from Model.SedimentLayer.SedimentLayer import SedimentLayer @@ -35,11 +35,16 @@ class SedimentLayerList(PamhyrModelList): return new def _db_save(self, execute, data=None): - ok = True + execute( + "DELETE FROM sedimentary_layer" + + f"WHERE scenario = {self._status.scenario_id}" + ) + execute( + "DELETE FROM sedimentary_layer_layer" + + f"WHERE scenario = {self._status.scenario_id}" + ) - # Delete previous data - execute("DELETE FROM sedimentary_layer") - execute("DELETE FROM sedimentary_layer_layer") + ok = True for sl in self._lst: ok &= sl._db_save(execute, data) diff --git a/src/View/SedimentLayers/Edit/UndoCommand.py b/src/View/SedimentLayers/Edit/UndoCommand.py index 0118e038..6e62a4cb 100644 --- a/src/View/SedimentLayers/Edit/UndoCommand.py +++ b/src/View/SedimentLayers/Edit/UndoCommand.py @@ -132,13 +132,13 @@ class AddCommand(QUndoCommand): self._new = None def undo(self): - self._sediment_layers.delete_i([self._index]) + self._sediment_layers.delete([self._new]) def redo(self): if self._new is None: self._new = self._sediment_layers.new(self._index) else: - self._sediment_layers.insert(self._index, self._new) + self._sediment_layers.undelete([self._new]) class DelCommand(QUndoCommand): @@ -148,17 +148,15 @@ class DelCommand(QUndoCommand): self._sediment_layers = sediment_layers self._rows = rows - self._sl_pos = [] + self._sl = [] for row in rows: - self._sl_pos.append((row, self._sediment_layers.get(row))) - self._sl_pos.sort() + self._sl.append(self._sediment_layers.get(row)) def undo(self): - for row, el in self._sl_pos: - self._sediment_layers.insert(row, el) + self._sediment_layers.undelete(self._sl) def redo(self): - self._sediment_layers.delete_i(self._rows) + self._sediment_layers.delete(self._sl) class MoveCommand(QUndoCommand): diff --git a/src/View/SedimentLayers/UndoCommand.py b/src/View/SedimentLayers/UndoCommand.py index 03aca97b..7b154fe6 100644 --- a/src/View/SedimentLayers/UndoCommand.py +++ b/src/View/SedimentLayers/UndoCommand.py @@ -68,13 +68,13 @@ class AddCommand(QUndoCommand): self._new = None def undo(self): - self._sediment_layers_list.delete_i([self._index]) + self._sediment_layers_list.delete([self._new]) def redo(self): if self._new is None: self._new = self._sediment_layers_list.new(self._index) else: - self._sediment_layers_list.insert(self._index, self._new) + self._sediment_layers_list.undelete([self._new]) class DelCommand(QUndoCommand): @@ -84,17 +84,15 @@ class DelCommand(QUndoCommand): self._sediment_layers_list = sediment_layers_list self._rows = rows - self._sl_pos = [] + self._sl = [] for row in rows: - self._sl_pos.append((row, self._sediment_layers_list.get(row))) - self._sl_pos.sort() + self._sl.append(self._sediment_layers_list.get(row)) def undo(self): - for row, el in self._sl_pos: - self._sediment_layers_list.insert(row, el) + self._sediment_layers_list.undelete(self._sl) def redo(self): - self._sediment_layers_list.delete_i(self._rows) + self._sediment_layers_list.delete(self._sl) class MoveCommand(QUndoCommand):