mirror of https://gitlab.com/pamhyr/pamhyr2
AddFile: Add deleted flags.
parent
8c99268bb8
commit
ac32995e01
|
|
@ -112,6 +112,7 @@ class AddFile(SQLSubModel):
|
|||
CREATE TABLE additional_files{ext} (
|
||||
{cls.create_db_add_pamhyr_id()},
|
||||
enabled BOOLEAN NOT NULL,
|
||||
deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
name TEXT NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
text TEXT NOT NULL,
|
||||
|
|
@ -126,9 +127,9 @@ class AddFile(SQLSubModel):
|
|||
@classmethod
|
||||
def _db_update(cls, execute, version, data=None):
|
||||
major, minor, release = version.strip().split(".")
|
||||
if major == minor == "0":
|
||||
release = int(release)
|
||||
release = int(release)
|
||||
|
||||
if major == minor == "0":
|
||||
if release < 8:
|
||||
cls._db_create(execute)
|
||||
return True
|
||||
|
|
@ -136,6 +137,13 @@ class AddFile(SQLSubModel):
|
|||
if 8 < release < 13:
|
||||
cls._db_update_to_0_0_13(execute, data)
|
||||
|
||||
if major == "0" and minor == "1":
|
||||
if release < 2:
|
||||
execute(
|
||||
"ALTER TABLE additional_files " +
|
||||
"ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE"
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
|
|
@ -166,7 +174,7 @@ class AddFile(SQLSubModel):
|
|||
return new
|
||||
|
||||
table = execute(
|
||||
"SELECT pamhyr_id, enabled, name, path, text, scenario " +
|
||||
"SELECT pamhyr_id, enabled, deleted, name, path, text, scenario " +
|
||||
"FROM additional_files " +
|
||||
f"WHERE scenario = {scenario.id} " +
|
||||
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))})"
|
||||
|
|
@ -177,6 +185,7 @@ class AddFile(SQLSubModel):
|
|||
|
||||
id = next(it)
|
||||
enabled = (next(it) == 1)
|
||||
deleted = (next(it) == 1)
|
||||
name = next(it)
|
||||
path = next(it)
|
||||
text = next(it)
|
||||
|
|
@ -186,6 +195,8 @@ class AddFile(SQLSubModel):
|
|||
id=id, enabled=enabled, name=name, path=path, text=text,
|
||||
status=data['status'], owner_scenario=owner_scenario
|
||||
)
|
||||
if deleted:
|
||||
f.set_as_deleted()
|
||||
|
||||
loaded.add(id)
|
||||
new.append(f)
|
||||
|
|
@ -200,18 +211,17 @@ class AddFile(SQLSubModel):
|
|||
if not self.must_be_saved():
|
||||
return True
|
||||
|
||||
sql = (
|
||||
execute(
|
||||
"INSERT INTO " +
|
||||
"additional_files(pamhyr_id, enabled, " +
|
||||
"additional_files(pamhyr_id, enabled, deleted, " +
|
||||
"name, path, text, scenario) " +
|
||||
"VALUES (" +
|
||||
f"{self._pamhyr_id}, {self._enabled}, " +
|
||||
f"{self._pamhyr_id}, {self._enabled}, {self.is_deleted()}, " +
|
||||
f"'{self._db_format(self._name)}', " +
|
||||
f"'{self._db_format(self._path)}', " +
|
||||
f"'{self._db_format(self._text)}', " +
|
||||
f"{self._status.scenario_id}"
|
||||
")"
|
||||
)
|
||||
execute(sql)
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -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.AdditionalFile.AddFile import AddFile
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -162,6 +162,17 @@ class SQLSubModel(PamhyrID):
|
|||
super(SQLSubModel, self).__init__(id)
|
||||
|
||||
self._status = status
|
||||
|
||||
# Deletion status of the model object. This status MUST be set
|
||||
# to True if an object that exists in a parent scenario is
|
||||
# deleted in current scenario.
|
||||
self._deleted = False
|
||||
|
||||
# The 'owner_scenario' is the id of the scenario to which the
|
||||
# object belongs. This id CAN be different to current
|
||||
# scenario, but in case of object modification, this id MUST
|
||||
# be set to current scenario id. (This action is made in
|
||||
# 'modified' method.)
|
||||
self._owner_scenario = 0
|
||||
if owner_scenario == -1:
|
||||
if status is not None:
|
||||
|
|
@ -170,12 +181,49 @@ class SQLSubModel(PamhyrID):
|
|||
self._owner_scenario = owner_scenario
|
||||
|
||||
def must_be_saved(self):
|
||||
"""Return True if this object MUST be save in the save file.
|
||||
|
||||
Returns:
|
||||
True if this object MUST be save, otherelse False
|
||||
"""
|
||||
return self._owner_scenario == self._status.scenario_id
|
||||
|
||||
def modified(self):
|
||||
"""Set study status to modified and update the object
|
||||
owner_scenario to current scenario
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
self._owner_scenario = self._status.scenario_id
|
||||
self._status.modified()
|
||||
|
||||
def is_deleted(self):
|
||||
"""This object is deleted?
|
||||
|
||||
Returns:
|
||||
True if this object is deleted, otherelse False
|
||||
"""
|
||||
return self._deleted
|
||||
|
||||
def set_as_deleted(self):
|
||||
"""Set object deleted flag to True.
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
self._deleted = True
|
||||
self.modified()
|
||||
|
||||
def set_as_not_deleted(self):
|
||||
"""Set object deleted flag to False.
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
self._deleted = False
|
||||
self.modified()
|
||||
|
||||
def _db_format(self, value):
|
||||
# Replace ''' by ''' to preserve SQL injection
|
||||
if type(value) is str:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,324 @@
|
|||
# PamhyrList.py -- Pamhyr Abstract List object for the Model
|
||||
# Copyright (C) 2023-2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
|
||||
from copy import copy
|
||||
from tools import trace, timer
|
||||
|
||||
from Model.Tools.PamhyrDB import SQLSubModel
|
||||
from Model.Except import NotImplementedMethodeError
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class PamhyrModelList(SQLSubModel):
|
||||
_sub_classes = []
|
||||
|
||||
def __init__(self, status=None):
|
||||
super(PamhyrModelList, self).__init__()
|
||||
|
||||
self._status = status
|
||||
self._lst = []
|
||||
|
||||
#######
|
||||
# SQL #
|
||||
#######
|
||||
|
||||
@classmethod
|
||||
def _db_create(cls, execute):
|
||||
return cls._create_submodel(execute)
|
||||
|
||||
@classmethod
|
||||
def _db_update(cls, execute, version, data=None):
|
||||
return cls._update_submodel(execute, version, data)
|
||||
|
||||
@classmethod
|
||||
def _db_load(cls, execute, data=None):
|
||||
raise NotImplementedMethodeError(cls, cls._db_load)
|
||||
|
||||
def _db_save(self, execute, data=None):
|
||||
raise NotImplementedMethodeError(self, self._db_save)
|
||||
|
||||
################
|
||||
# MODEL METHOD #
|
||||
################
|
||||
|
||||
@property
|
||||
def lst(self):
|
||||
"""Return the PamhyrList as a Python list
|
||||
|
||||
Return the PamhyrList as a Python list. This list is the
|
||||
current list witout deleted object used in the PamhyrList
|
||||
object. **If you need to modify it, please make a copy.**
|
||||
|
||||
Returns: The Python list
|
||||
"""
|
||||
return list(
|
||||
filter(
|
||||
lambda el: not el.is_deleted(),
|
||||
self._lst
|
||||
)
|
||||
)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.lst)
|
||||
|
||||
def index(self, el):
|
||||
return self.lst.index(el)
|
||||
|
||||
def get(self, index):
|
||||
return self.lst[index]
|
||||
|
||||
def set(self, index, new):
|
||||
self.lst[index] = new
|
||||
if self._status is not None:
|
||||
self._status.modified()
|
||||
|
||||
def new(self, index):
|
||||
"""Create new elements and add it to list
|
||||
|
||||
Args:
|
||||
index: The index of new elements
|
||||
|
||||
Returns:
|
||||
The new elements
|
||||
"""
|
||||
raise NotImplementedMethodeError(self, self.new)
|
||||
|
||||
def insert(self, index, new):
|
||||
self._lst.insert(index, new)
|
||||
|
||||
if self._status is not None:
|
||||
self._status.modified()
|
||||
|
||||
def undelete(self, lst):
|
||||
"""Delete a list of elements
|
||||
|
||||
Args:
|
||||
lst: The list of elements
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
for el in lst:
|
||||
el.set_as_not_deleted()
|
||||
|
||||
def delete(self, lst):
|
||||
"""Delete a list of elements
|
||||
|
||||
Args:
|
||||
lst: The list of elements
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
for el in lst:
|
||||
el.set_as_deleted()
|
||||
|
||||
def delete_i(self, indexes):
|
||||
"""Delete elements from list of indexes
|
||||
|
||||
Args:
|
||||
indexes: The elements indexes
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
lst = list(
|
||||
map(
|
||||
lambda x: x[1],
|
||||
filter(
|
||||
lambda x: x[0] in indexes,
|
||||
enumerate(self.lst)
|
||||
)
|
||||
)
|
||||
)
|
||||
self.delete(lst)
|
||||
|
||||
def sort(self, reverse=False, key=None):
|
||||
self._lst.sort(reverse=reverse, key=key)
|
||||
|
||||
if self._status is not None:
|
||||
self._status.modified()
|
||||
|
||||
def move_up(self, index):
|
||||
if index < len(self._lst):
|
||||
next = index - 1
|
||||
|
||||
lst = self._lst
|
||||
lst[index], lst[next] = lst[next], lst[index]
|
||||
|
||||
if self._status is not None:
|
||||
self._status.modified()
|
||||
|
||||
def move_down(self, index):
|
||||
if index >= 0:
|
||||
prev = index + 1
|
||||
|
||||
lst = self._lst
|
||||
lst[index], lst[prev] = lst[prev], lst[index]
|
||||
|
||||
if self._status is not None:
|
||||
self._status.modified()
|
||||
|
||||
|
||||
class PamhyrModelListWithTab(SQLSubModel):
|
||||
_tabs_list = []
|
||||
_sub_classes = []
|
||||
|
||||
def __init__(self, status=None):
|
||||
super(PamhyrModelListWithTab, self).__init__()
|
||||
|
||||
self._status = status
|
||||
self._tabs = {}
|
||||
for tab in self._tabs_list:
|
||||
self._tabs[tab] = []
|
||||
|
||||
#######
|
||||
# SQL #
|
||||
#######
|
||||
|
||||
@classmethod
|
||||
def _db_create(cls, execute):
|
||||
return cls._create_submodel(execute)
|
||||
|
||||
@classmethod
|
||||
def _db_update(cls, execute, version, data=None):
|
||||
return cls._update_submodel(execute, version, data)
|
||||
|
||||
@classmethod
|
||||
def _db_load(cls, execute, data=None):
|
||||
raise NotImplementedMethodeError(cls, cls._db_load)
|
||||
|
||||
def _db_save(self, execute, data=None):
|
||||
raise NotImplementedMethodeError(self, self._db_save)
|
||||
|
||||
################
|
||||
# MODEL METHOD #
|
||||
################
|
||||
|
||||
def len(self, lst):
|
||||
"""Size of tab list
|
||||
|
||||
Args:
|
||||
lst: The tab name
|
||||
|
||||
Returns:
|
||||
The size of the tab list
|
||||
"""
|
||||
return len(self._tabs[lst])
|
||||
|
||||
def get_tab(self, lst):
|
||||
"""Get tab list (copy) from name
|
||||
|
||||
Args:
|
||||
lst: The tab name
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
return self._tabs[lst].copy()
|
||||
|
||||
def get(self, lst, index):
|
||||
return self._tabs[lst][index]
|
||||
|
||||
def set(self, lst, index, new):
|
||||
self._tabs[lst][index] = new
|
||||
self._status.modified()
|
||||
|
||||
def new(self, lst, index):
|
||||
"""Create new elements and add it to list
|
||||
|
||||
Args:
|
||||
lst: The tab name
|
||||
index: The index of new elements
|
||||
|
||||
Returns:
|
||||
The new elements
|
||||
"""
|
||||
raise NotImplementedMethodeError(self, self.new)
|
||||
|
||||
def insert(self, lst, index, new):
|
||||
"""Insert element in tab
|
||||
|
||||
Args:
|
||||
lst: The tab name
|
||||
index: The index of new element
|
||||
new: The new elements
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
self._tabs[lst].insert(index, new)
|
||||
self._status.modified()
|
||||
|
||||
def delete(self, lst, els):
|
||||
"""Delete elements from specific tab
|
||||
|
||||
Args:
|
||||
lst: The tab name
|
||||
els: The elements list
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
for el in els:
|
||||
self._tabs[lst].remove(el)
|
||||
self._status.modified()
|
||||
|
||||
def delete_i(self, lst, indexes):
|
||||
"""Delete elements from specific tab
|
||||
|
||||
Args:
|
||||
lst: The tab name
|
||||
indexes: The elements indexes
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
els = list(
|
||||
map(
|
||||
lambda x: x[1],
|
||||
filter(
|
||||
lambda x: x[0] in indexes,
|
||||
enumerate(self._tabs[lst])
|
||||
)
|
||||
)
|
||||
)
|
||||
self.delete(lst, els)
|
||||
|
||||
def sort(self, lst, reverse=False, key=None):
|
||||
self._tabs[lst].sort(reverse=reverse, key=key)
|
||||
self._status.modified()
|
||||
|
||||
def move_up(self, lst, index):
|
||||
if index < len(self._tabs[lst]):
|
||||
next = index - 1
|
||||
|
||||
lst = self._tabs[lst]
|
||||
lst[index], lst[next] = lst[next], lst[index]
|
||||
self._status.modified()
|
||||
|
||||
def move_down(self, lst, index):
|
||||
if index >= 0:
|
||||
prev = index + 1
|
||||
|
||||
lst = self._tabs[lst]
|
||||
lst[index], lst[prev] = lst[prev], lst[index]
|
||||
self._status.modified()
|
||||
|
|
@ -64,7 +64,8 @@ class AddCommand(QUndoCommand):
|
|||
if self._new is None:
|
||||
self._new = self._files.new(self._row)
|
||||
else:
|
||||
self._files.insert(self._row, self._new)
|
||||
self._files.undelete([self._new])
|
||||
# self._files.insert(self._row, self._new)
|
||||
|
||||
|
||||
class DelCommand(QUndoCommand):
|
||||
|
|
@ -76,7 +77,8 @@ class DelCommand(QUndoCommand):
|
|||
self._old = self._files.get(row)
|
||||
|
||||
def undo(self):
|
||||
self._files.insert(self._row, self._old)
|
||||
self._files.undelete([self._old])
|
||||
# self._files.insert(self._row, self._old)
|
||||
|
||||
def redo(self):
|
||||
self._files.delete_i([self._row])
|
||||
|
|
|
|||
Loading…
Reference in New Issue