mirror of https://gitlab.com/pamhyr/pamhyr2
DIF Model
parent
95a0dabe68
commit
de72e2e96b
|
|
@ -0,0 +1,258 @@
|
||||||
|
# DIFAdisTS.py -- Pamhyr
|
||||||
|
# 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 functools import reduce
|
||||||
|
|
||||||
|
from tools import trace, timer, old_pamhyr_date_to_timestamp
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrDB import SQLSubModel
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
from Model.DIFAdisTS.DIFAdisTSSpec import DIFAdisTSSpec
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
class DIFAdisTS(SQLSubModel):
|
||||||
|
_sub_classes = [
|
||||||
|
DIFAdisTSSpec,
|
||||||
|
]
|
||||||
|
_id_cnt = 0
|
||||||
|
|
||||||
|
def __init__(self, id: int = -1, name: str = "default",
|
||||||
|
status=None):
|
||||||
|
super(DIFAdisTS, self).__init__()
|
||||||
|
|
||||||
|
self._status = status
|
||||||
|
|
||||||
|
if id == -1:
|
||||||
|
self.id = DIFAdisTS._id_cnt
|
||||||
|
else:
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
self._name = name
|
||||||
|
self._method = None
|
||||||
|
self._dif = None
|
||||||
|
self._b = None
|
||||||
|
self._c = None
|
||||||
|
self._enabled = True
|
||||||
|
self._types = ["iwasa", "fisher", "elder", "constante", "generique"]
|
||||||
|
self._data = []
|
||||||
|
|
||||||
|
DIFAdisTS._id_cnt = max(
|
||||||
|
DIFAdisTS._id_cnt + 1,
|
||||||
|
self.id
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute):
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE dif_adists(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
method TEXT NOT NULL,
|
||||||
|
dif REAL NOT NULL,
|
||||||
|
b REAL,
|
||||||
|
c REAL,
|
||||||
|
enabled BOOLEAN NOT NULL
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version):
|
||||||
|
major, minor, release = version.strip().split(".")
|
||||||
|
if major == minor == "0":
|
||||||
|
if int(release) < 6:
|
||||||
|
cls._db_create(execute)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
table = execute(
|
||||||
|
"SELECT id, name, method, dif, b, c, enabled " +
|
||||||
|
"FROM dif_adists"
|
||||||
|
)
|
||||||
|
|
||||||
|
if table is not None:
|
||||||
|
for row in table:
|
||||||
|
dif_id = row[0]
|
||||||
|
name = row[1]
|
||||||
|
method = row[2]
|
||||||
|
dif = row[3]
|
||||||
|
b = row[4]
|
||||||
|
c = row[5]
|
||||||
|
enabled = (row[6] == 1)
|
||||||
|
|
||||||
|
DIF = cls(
|
||||||
|
id=dif_id,
|
||||||
|
name=name,
|
||||||
|
status=data['status']
|
||||||
|
)
|
||||||
|
|
||||||
|
DIF.method = method
|
||||||
|
DIF.dif = dif
|
||||||
|
DIF.b = b
|
||||||
|
DIF.c = c
|
||||||
|
DIF.enabled = enabled
|
||||||
|
|
||||||
|
data['dif_default_id'] = dif_id
|
||||||
|
DIF._data = DIFAdisTSSpec._db_load(execute, data)
|
||||||
|
|
||||||
|
new.append(DIF)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
execute(f"DELETE FROM dif_adists WHERE id = {self.id}")
|
||||||
|
|
||||||
|
method = ""
|
||||||
|
if self.method is not None:
|
||||||
|
method = self.method
|
||||||
|
|
||||||
|
dif = -1.
|
||||||
|
if self.dif is not None:
|
||||||
|
dif = self.dif
|
||||||
|
|
||||||
|
b = -1.
|
||||||
|
if self.b is not None:
|
||||||
|
b = self.b
|
||||||
|
|
||||||
|
c = -1.
|
||||||
|
if self.dif is not None:
|
||||||
|
c = self.c
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"dif_adists(" +
|
||||||
|
"id, name, method, dif, b, c, enabled" +
|
||||||
|
") " +
|
||||||
|
"VALUES (" +
|
||||||
|
f"{self.id}, '{self._db_format(self._name)}', " +
|
||||||
|
f"'{self._db_format(self._method)}', " +
|
||||||
|
f"{dif}, {b}, {c}, {self._enabled}" +
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
data['dif_default_id'] = self.id
|
||||||
|
execute(
|
||||||
|
"DELETE FROM dif_spec " +
|
||||||
|
f"WHERE dif_default = {self.id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
for dif_spec in self._data:
|
||||||
|
dif_spec._db_save(execute, data)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._data)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
def name(self, name):
|
||||||
|
self._name = name
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def method(self):
|
||||||
|
return self._method
|
||||||
|
|
||||||
|
@method.setter
|
||||||
|
def method(self, method):
|
||||||
|
self._method = method
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def types(self):
|
||||||
|
return self._types
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dif(self):
|
||||||
|
return self._dif
|
||||||
|
|
||||||
|
@dif.setter
|
||||||
|
def dif(self, dif):
|
||||||
|
self._dif = dif
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def b(self):
|
||||||
|
return self._b
|
||||||
|
|
||||||
|
@b.setter
|
||||||
|
def b(self, b):
|
||||||
|
self._b = b
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def c(self):
|
||||||
|
return self._c
|
||||||
|
|
||||||
|
@c.setter
|
||||||
|
def c(self, c):
|
||||||
|
self._c = c
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enabled(self):
|
||||||
|
return self._enabled
|
||||||
|
|
||||||
|
@enabled.setter
|
||||||
|
def enabled(self, enabled):
|
||||||
|
self._enabled = enabled
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def new(self, index):
|
||||||
|
n = DIFAdisTSSpec(status=self._status)
|
||||||
|
self._data.insert(index, n)
|
||||||
|
self._status.modified()
|
||||||
|
return n
|
||||||
|
|
||||||
|
def delete(self, data):
|
||||||
|
self._data = list(
|
||||||
|
filter(
|
||||||
|
lambda x: x not in data,
|
||||||
|
self._data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def delete_i(self, indexes):
|
||||||
|
for ind in indexes:
|
||||||
|
del self._data[ind]
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
def insert(self, index, data):
|
||||||
|
self._data.insert(index, data)
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
# DIFAdisTSList.py -- Pamhyr
|
||||||
|
# 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 -*-
|
||||||
|
|
||||||
|
from copy import copy
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrList import PamhyrModelList
|
||||||
|
from Model.DIFAdisTS.DIFAdisTS import DIFAdisTS
|
||||||
|
|
||||||
|
class DIFAdisTSList(PamhyrModelList):
|
||||||
|
_sub_classes = [
|
||||||
|
DIFAdisTS,
|
||||||
|
]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = cls(status=data['status'])
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
new._lst = DIFAdisTS._db_load(
|
||||||
|
execute, data
|
||||||
|
)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
execute("DELETE FROM dif_adists")
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
for dif in self._lst:
|
||||||
|
dif._db_save(execute, data=data)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def new(self, index):
|
||||||
|
n = DIFAdisTS(status=self._status)
|
||||||
|
self._lst.insert(index, n)
|
||||||
|
self._status.modified()
|
||||||
|
return n
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,228 @@
|
||||||
|
# DIFAdisTSSpec.py -- Pamhyr
|
||||||
|
# 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 tools import trace, timer
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrDB import SQLSubModel
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
class DIFAdisTSSpec(SQLSubModel):
|
||||||
|
_sub_classes = [
|
||||||
|
]
|
||||||
|
_id_cnt = 0
|
||||||
|
|
||||||
|
def __init__(self, id: int = -1, method: str = "",
|
||||||
|
status=None):
|
||||||
|
super(DIFAdisTSSpec, self).__init__()
|
||||||
|
|
||||||
|
self._status = status
|
||||||
|
|
||||||
|
if id == -1:
|
||||||
|
self.id = DIFAdisTSSpec._id_cnt
|
||||||
|
else:
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
self._method = method
|
||||||
|
self._reach = None
|
||||||
|
self._start_kp = None
|
||||||
|
self._end_kp = None
|
||||||
|
self._dif = None
|
||||||
|
self._b = None
|
||||||
|
self._c = None
|
||||||
|
self._enabled = True
|
||||||
|
|
||||||
|
DIFAdisTSSpec._id_cnt = max(DIFAdisTSSpec._id_cnt + 1, self.id)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute):
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE dif_spec(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
dif_default INTEGER NOT NULL,
|
||||||
|
method TEXT NOT NULL,
|
||||||
|
reach INTEGER NOT NULL,
|
||||||
|
start_kp REAL NOT NULL,
|
||||||
|
end_kp REAL NOT NULL,
|
||||||
|
dif REAL NOT NULL,
|
||||||
|
b REAL,
|
||||||
|
c REAL,
|
||||||
|
enabled BOOLEAN NOT NULL,
|
||||||
|
FOREIGN KEY(dif_default) REFERENCES dif_adists(id),
|
||||||
|
FOREIGN KEY(reach) REFERENCES river_reach(id)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version):
|
||||||
|
major, minor, release = version.strip().split(".")
|
||||||
|
if major == minor == "0":
|
||||||
|
if int(release) < 6:
|
||||||
|
cls._db_create(execute)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
table = execute(
|
||||||
|
"SELECT id, dif_default, method, reach, start_kp, end_kp, " +
|
||||||
|
"dif, b, c, enabled " +
|
||||||
|
"FROM dif_spec " +
|
||||||
|
f"WHERE dif_default = {data['dif_default_id']} "
|
||||||
|
)
|
||||||
|
|
||||||
|
for row in table:
|
||||||
|
id = row[0]
|
||||||
|
method = row[2]
|
||||||
|
reach = row[3]
|
||||||
|
start_kp = row[4]
|
||||||
|
end_kp = row[5]
|
||||||
|
dif = row[6]
|
||||||
|
b = row[7]
|
||||||
|
c = row[8]
|
||||||
|
enabled = (row[9] == 1)
|
||||||
|
|
||||||
|
new_spec = cls(
|
||||||
|
id=id,
|
||||||
|
method=method,
|
||||||
|
status=data['status']
|
||||||
|
)
|
||||||
|
|
||||||
|
new_spec.reach = reach
|
||||||
|
new_spec.start_kp = start_kp
|
||||||
|
new_spec.end_kp = end_kp
|
||||||
|
new_spec.dif = dif
|
||||||
|
new_spec.b = b
|
||||||
|
new_spec.c = c
|
||||||
|
new_spec.enabled = enabled
|
||||||
|
|
||||||
|
new.append(new_spec)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
dif_default = data['dif_default_id']
|
||||||
|
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"dif_spec(id, dif_default, method, reach, " +
|
||||||
|
"start_kp, end_kp, dif, b, c, enabled) " +
|
||||||
|
"VALUES (" +
|
||||||
|
f"{self.id}, " +
|
||||||
|
f"{dif_default}, " +
|
||||||
|
f"'{self._db_format(self._method)}', " +
|
||||||
|
f"{self._reach}, " +
|
||||||
|
f"{self._start_kp}, " +
|
||||||
|
f"{self._end_kp}, " +
|
||||||
|
f"{self._dif}, " +
|
||||||
|
f"{self._b}, " +
|
||||||
|
f"{self._c}, " +
|
||||||
|
f"{self._enabled}" +
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def method(self):
|
||||||
|
return self._method
|
||||||
|
|
||||||
|
@method.setter
|
||||||
|
def method(self, method):
|
||||||
|
self._method = method
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reach(self):
|
||||||
|
return self._reach
|
||||||
|
|
||||||
|
@reach.setter
|
||||||
|
def reach(self, reach):
|
||||||
|
self._reach = reach
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def start_kp(self):
|
||||||
|
return self._start_kp
|
||||||
|
|
||||||
|
@start_kp.setter
|
||||||
|
def start_kp(self, start_kp):
|
||||||
|
self._start_kp = start_kp
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def end_kp(self):
|
||||||
|
return self._end_kp
|
||||||
|
|
||||||
|
@end_kp.setter
|
||||||
|
def end_kp(self, end_kp):
|
||||||
|
self._end_kp = end_kp
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dif(self):
|
||||||
|
return self._dif
|
||||||
|
|
||||||
|
@dif.setter
|
||||||
|
def dif(self, dif):
|
||||||
|
self._dif = dif
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def b(self):
|
||||||
|
return self._b
|
||||||
|
|
||||||
|
@b.setter
|
||||||
|
def b(self, b):
|
||||||
|
self._b = b
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def c(self):
|
||||||
|
return self._c
|
||||||
|
|
||||||
|
@c.setter
|
||||||
|
def c(self, c):
|
||||||
|
self._c = c
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enabled(self):
|
||||||
|
return self._enabled
|
||||||
|
|
||||||
|
@enabled.setter
|
||||||
|
def enabled(self, enabled):
|
||||||
|
self._enabled = enabled
|
||||||
|
self._status.modified()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -51,6 +51,7 @@ from Model.InitialConditionsAdisTS.InitialConditionsAdisTSList import InitialCon
|
||||||
from Model.BoundaryConditionsAdisTS.BoundaryConditionsAdisTSList import BoundaryConditionsAdisTSList
|
from Model.BoundaryConditionsAdisTS.BoundaryConditionsAdisTSList import BoundaryConditionsAdisTSList
|
||||||
from Model.LateralContributionsAdisTS.LateralContributionsAdisTSList import LateralContributionsAdisTSList
|
from Model.LateralContributionsAdisTS.LateralContributionsAdisTSList import LateralContributionsAdisTSList
|
||||||
from Model.D90AdisTS.D90AdisTSList import D90AdisTSList
|
from Model.D90AdisTS.D90AdisTSList import D90AdisTSList
|
||||||
|
from Model.DIFAdisTS.DIFAdisTSList import DIFAdisTSList
|
||||||
|
|
||||||
|
|
||||||
class RiverNode(Node, SQLSubModel):
|
class RiverNode(Node, SQLSubModel):
|
||||||
|
|
@ -241,6 +242,7 @@ class River(Graph, SQLSubModel):
|
||||||
BoundaryConditionsAdisTSList,
|
BoundaryConditionsAdisTSList,
|
||||||
LateralContributionsAdisTSList,
|
LateralContributionsAdisTSList,
|
||||||
D90AdisTSList,
|
D90AdisTSList,
|
||||||
|
DIFAdisTSList,
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, status=None):
|
def __init__(self, status=None):
|
||||||
|
|
@ -270,6 +272,7 @@ class River(Graph, SQLSubModel):
|
||||||
self._BoundaryConditionsAdisTS = BoundaryConditionsAdisTSList(status=self._status)
|
self._BoundaryConditionsAdisTS = BoundaryConditionsAdisTSList(status=self._status)
|
||||||
self._LateralContributionsAdisTS = LateralContributionsAdisTSList(status=self._status)
|
self._LateralContributionsAdisTS = LateralContributionsAdisTSList(status=self._status)
|
||||||
self._D90AdisTS = D90AdisTSList(status=self._status)
|
self._D90AdisTS = D90AdisTSList(status=self._status)
|
||||||
|
self._DIFAdisTS = DIFAdisTSList(status=self._status)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_create(cls, execute):
|
def _db_create(cls, execute):
|
||||||
|
|
@ -358,6 +361,8 @@ class River(Graph, SQLSubModel):
|
||||||
|
|
||||||
new._D90AdisTS = D90AdisTSList._db_load(execute, data)
|
new._D90AdisTS = D90AdisTSList._db_load(execute, data)
|
||||||
|
|
||||||
|
new._DIFAdisTS = DIFAdisTSList._db_load(execute, data)
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
def _db_save(self, execute, data=None):
|
def _db_save(self, execute, data=None):
|
||||||
|
|
@ -383,6 +388,7 @@ class River(Graph, SQLSubModel):
|
||||||
objs.append(self._BoundaryConditionsAdisTS)
|
objs.append(self._BoundaryConditionsAdisTS)
|
||||||
objs.append(self._LateralContributionsAdisTS)
|
objs.append(self._LateralContributionsAdisTS)
|
||||||
objs.append(self._D90AdisTS)
|
objs.append(self._D90AdisTS)
|
||||||
|
objs.append(self._DIFAdisTS)
|
||||||
|
|
||||||
self._save_submodel(execute, objs, data)
|
self._save_submodel(execute, objs, data)
|
||||||
return True
|
return True
|
||||||
|
|
@ -530,6 +536,10 @@ Last export at: @date."""
|
||||||
def d90_adists(self):
|
def d90_adists(self):
|
||||||
return self._D90AdisTS
|
return self._D90AdisTS
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dif_adists(self):
|
||||||
|
return self._DIFAdisTS
|
||||||
|
|
||||||
def get_params(self, solver):
|
def get_params(self, solver):
|
||||||
if solver in self._parameters:
|
if solver in self._parameters:
|
||||||
return self._parameters[solver]
|
return self._parameters[solver]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,217 @@
|
||||||
|
# Table.py -- Pamhyr
|
||||||
|
# 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
|
||||||
|
import traceback
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
||||||
|
from View.D90AdisTS.UndoCommand import (
|
||||||
|
SetCommand, AddCommand, SetCommandSpec,
|
||||||
|
DelCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
|
class ComboBoxDelegate(QItemDelegate):
|
||||||
|
def __init__(self, data=None, ic_spec_lst=None, trad=None, parent=None, mode="reaches"):
|
||||||
|
super(ComboBoxDelegate, self).__init__(parent)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._mode = mode
|
||||||
|
self._trad = trad
|
||||||
|
self._ic_spec_lst = ic_spec_lst
|
||||||
|
|
||||||
|
def createEditor(self, parent, option, index):
|
||||||
|
self.editor = QComboBox(parent)
|
||||||
|
|
||||||
|
val = []
|
||||||
|
if self._mode == "kp":
|
||||||
|
reach_id = self._ic_spec_lst[index.row()].reach
|
||||||
|
|
||||||
|
reach = next(filter(lambda edge: edge.id == reach_id, self._data.edges()))
|
||||||
|
|
||||||
|
if reach_id is not None:
|
||||||
|
val = list(
|
||||||
|
map(
|
||||||
|
lambda kp: str(kp), reach.reach.get_kp()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
val = list(
|
||||||
|
map(
|
||||||
|
lambda n: n.name, self._data.edges()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.editor.addItems(
|
||||||
|
[self._trad['not_associated']] +
|
||||||
|
val
|
||||||
|
)
|
||||||
|
|
||||||
|
self.editor.setCurrentText(str(index.data(Qt.DisplayRole)))
|
||||||
|
return self.editor
|
||||||
|
|
||||||
|
def setEditorData(self, editor, index):
|
||||||
|
value = index.data(Qt.DisplayRole)
|
||||||
|
self.editor.currentTextChanged.connect(self.currentItemChanged)
|
||||||
|
|
||||||
|
def setModelData(self, editor, model, index):
|
||||||
|
text = str(editor.currentText())
|
||||||
|
model.setData(index, text)
|
||||||
|
editor.close()
|
||||||
|
editor.deleteLater()
|
||||||
|
|
||||||
|
def updateEditorGeometry(self, editor, option, index):
|
||||||
|
r = QRect(option.rect)
|
||||||
|
if self.editor.windowFlags() & Qt.Popup:
|
||||||
|
if editor.parent() is not None:
|
||||||
|
r.setTopLeft(self.editor.parent().mapToGlobal(r.topLeft()))
|
||||||
|
editor.setGeometry(r)
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def currentItemChanged(self):
|
||||||
|
self.commitData.emit(self.sender())
|
||||||
|
|
||||||
|
|
||||||
|
class D90TableModel(PamhyrTableModel):
|
||||||
|
def __init__(self, river=None, data=None, **kwargs):
|
||||||
|
self._river = river
|
||||||
|
|
||||||
|
super(D90TableModel, self).__init__(data=data, **kwargs)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
|
||||||
|
def _setup_lst(self):
|
||||||
|
self._lst = self._data._data
|
||||||
|
|
||||||
|
def rowCount(self, parent):
|
||||||
|
return len(self._lst)
|
||||||
|
|
||||||
|
def data(self, index, role):
|
||||||
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
if self._headers[column] is "name":
|
||||||
|
n = self._lst[row].name
|
||||||
|
if n is None or n == "":
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "reach":
|
||||||
|
n = self._lst[row].reach
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return next(filter(lambda edge: edge.id == n, self._river.edges())).name
|
||||||
|
elif self._headers[column] is "start_kp":
|
||||||
|
n = self._lst[row].start_kp
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "end_kp":
|
||||||
|
n = self._lst[row].end_kp
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
elif self._headers[column] is "d90":
|
||||||
|
n = self._lst[row].d90
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
def setData(self, index, value, role=Qt.EditRole):
|
||||||
|
if not index.isValid() or role != Qt.EditRole:
|
||||||
|
return False
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self._headers[column] != "reach":
|
||||||
|
self._undo.push(
|
||||||
|
SetCommandSpec(
|
||||||
|
self._lst, row, self._headers[column], value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif self._headers[column] == "reach":
|
||||||
|
print(self._river.edge(value).id)
|
||||||
|
self._undo.push(
|
||||||
|
SetCommandSpec(
|
||||||
|
self._lst, row, self._headers[column], self._river.edge(value).id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(e)
|
||||||
|
logger.debug(traceback.format_exc())
|
||||||
|
|
||||||
|
self.dataChanged.emit(index, index)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def add(self, row, parent=QModelIndex()):
|
||||||
|
self.beginInsertRows(parent, row, row - 1)
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
AddCommand(
|
||||||
|
self._data, self._lst, row
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.endInsertRows()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def delete(self, rows, parent=QModelIndex()):
|
||||||
|
self.beginRemoveRows(parent, rows[0], rows[-1])
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
DelCommand(
|
||||||
|
self._data, self._lst, rows
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.endRemoveRows()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._undo.undo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._undo.redo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
# Table.py -- Pamhyr
|
||||||
|
# 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
|
||||||
|
import traceback
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
||||||
|
from View.D90AdisTS.UndoCommand import (
|
||||||
|
SetCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
class D90TableDefaultModel(PamhyrTableModel):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(D90TableDefaultModel, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def data(self, index, role):
|
||||||
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
if self._headers[column] is "name":
|
||||||
|
return self._data[row].name
|
||||||
|
elif self._headers[column] is "d90":
|
||||||
|
n = self._data[row].d90
|
||||||
|
if n is None:
|
||||||
|
return self._trad['not_associated']
|
||||||
|
return n
|
||||||
|
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
def setData(self, index, value, role=Qt.EditRole):
|
||||||
|
if not index.isValid() or role != Qt.EditRole:
|
||||||
|
return False
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self._headers[column] is not None:
|
||||||
|
self._undo.push(
|
||||||
|
SetCommand(
|
||||||
|
self._data, row, self._headers[column], value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(e)
|
||||||
|
logger.debug(traceback.format_exc())
|
||||||
|
|
||||||
|
self.dataChanged.emit(index, index)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._undo.undo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._undo.redo()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
||||||
|
|
@ -0,0 +1,150 @@
|
||||||
|
# UndoCommand.py -- Pamhyr
|
||||||
|
# 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 -*-
|
||||||
|
|
||||||
|
from copy import deepcopy
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QMessageBox, QUndoCommand, QUndoStack,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Model.D90AdisTS.D90AdisTS import D90AdisTS
|
||||||
|
from Model.D90AdisTS.D90AdisTSList import D90AdisTSList
|
||||||
|
|
||||||
|
|
||||||
|
class SetCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, row, column, new_value):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._row = row
|
||||||
|
self._column = column
|
||||||
|
|
||||||
|
if self._column == "name":
|
||||||
|
self._old = self._data[self._row].name
|
||||||
|
elif self._column == "d90":
|
||||||
|
self._old = self._data[self._row].d90
|
||||||
|
|
||||||
|
_type = float
|
||||||
|
if column == "name":
|
||||||
|
_type = str
|
||||||
|
|
||||||
|
self._new = _type(new_value)
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
if self._column == "name":
|
||||||
|
self._data[self._row].name = self._old
|
||||||
|
elif self._column == "d90":
|
||||||
|
self._data[self._row].d90 = self._old
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._column == "name":
|
||||||
|
self._data[self._row].name = self._new
|
||||||
|
elif self._column == "d90":
|
||||||
|
self._data[self._row].d90 = self._new
|
||||||
|
|
||||||
|
class SetCommandSpec(QUndoCommand):
|
||||||
|
def __init__(self, data, row, column, new_value):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._row = row
|
||||||
|
self._column = column
|
||||||
|
|
||||||
|
if self._column == "name":
|
||||||
|
self._old = self._data[self._row].name
|
||||||
|
elif self._column == "reach":
|
||||||
|
self._old = self._data[self._row].reach
|
||||||
|
elif self._column == "start_kp":
|
||||||
|
self._old = self._data[self._row].start_kp
|
||||||
|
elif self._column == "end_kp":
|
||||||
|
self._old = self._data[self._row].end_kp
|
||||||
|
elif self._column == "d90":
|
||||||
|
self._old = self._data[self._row].d90
|
||||||
|
|
||||||
|
_type = float
|
||||||
|
if column == "name":
|
||||||
|
_type = str
|
||||||
|
elif column == "reach":
|
||||||
|
_type = int
|
||||||
|
|
||||||
|
self._new = _type(new_value)
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
if self._column == "name":
|
||||||
|
self._data[self._row].name = self._old
|
||||||
|
elif self._column == "reach":
|
||||||
|
self._data[self._row].reach = self._old
|
||||||
|
elif self._column == "start_kp":
|
||||||
|
self._data[self._row].start_kp = self._old
|
||||||
|
elif self._column == "end_kp":
|
||||||
|
self._data[self._row].end_kp = self._old
|
||||||
|
elif self._column == "d90":
|
||||||
|
self._data[self._row].d90 = self._old
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._column == "name":
|
||||||
|
self._data[self._row].name = self._new
|
||||||
|
elif self._column == "reach":
|
||||||
|
self._data[self._row].reach = self._new
|
||||||
|
elif self._column == "start_kp":
|
||||||
|
self._data[self._row].start_kp = self._new
|
||||||
|
elif self._column == "end_kp":
|
||||||
|
self._data[self._row].end_kp = self._new
|
||||||
|
elif self._column == "d90":
|
||||||
|
self._data[self._row].d90 = self._new
|
||||||
|
|
||||||
|
class AddCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, ics_spec, index):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._ics_spec = ics_spec
|
||||||
|
self._index = index
|
||||||
|
self._new = None
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._data.delete_i([self._index])
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
if self._new is None:
|
||||||
|
self._new = self._data.new(self._index)
|
||||||
|
else:
|
||||||
|
self._data.insert(self._index, self._new)
|
||||||
|
|
||||||
|
class DelCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, ics_spec, rows):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._ics_spec = ics_spec
|
||||||
|
self._rows = rows
|
||||||
|
#self._data = data
|
||||||
|
|
||||||
|
self._ic = []
|
||||||
|
for row in rows:
|
||||||
|
self._ic.append((row, self._ics_spec[row]))
|
||||||
|
self._ic.sort()
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
for row, el in self._ic:
|
||||||
|
self._data.insert(row, el)
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._data.delete_i(self._rows)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,283 @@
|
||||||
|
# Window.py -- Pamhyr
|
||||||
|
# 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 os
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from tools import trace, timer, logger_exception
|
||||||
|
|
||||||
|
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||||
|
|
||||||
|
from PyQt5.QtGui import (
|
||||||
|
QKeySequence, QIcon,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect, QItemSelectionModel,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
||||||
|
QVBoxLayout, QToolBar, QAction, QToolButton,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Modules import Modules
|
||||||
|
|
||||||
|
from View.InitialConditionsAdisTS.UndoCommand import (
|
||||||
|
SetCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.D90AdisTS.TableDefault import (
|
||||||
|
D90TableDefaultModel,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.D90AdisTS.Table import (
|
||||||
|
D90TableModel, ComboBoxDelegate,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.D90AdisTS.translate import D90AdisTSTranslate
|
||||||
|
|
||||||
|
from Solver.Mage import Mage8
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class D90AdisTSWindow(PamhyrWindow):
|
||||||
|
_pamhyr_ui = "D90AdisTS"
|
||||||
|
_pamhyr_name = "D90 AdisTS"
|
||||||
|
|
||||||
|
def __init__(self, data=None, study=None, config=None, parent=None):
|
||||||
|
self._data = []
|
||||||
|
self._data.append(data)
|
||||||
|
trad = D90AdisTSTranslate()
|
||||||
|
|
||||||
|
name = (
|
||||||
|
trad[self._pamhyr_name] +
|
||||||
|
" - " + study.name +
|
||||||
|
" - " + self._data[0].name
|
||||||
|
)
|
||||||
|
|
||||||
|
super(D90AdisTSWindow, self).__init__(
|
||||||
|
title=name,
|
||||||
|
study=study,
|
||||||
|
config=config,
|
||||||
|
trad=trad,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._hash_data.append(data)
|
||||||
|
|
||||||
|
self._d90_adists_lst = study.river.d90_adists
|
||||||
|
|
||||||
|
self.setup_table()
|
||||||
|
|
||||||
|
self.ui.setWindowTitle(self._title)
|
||||||
|
|
||||||
|
def setup_table(self):
|
||||||
|
|
||||||
|
path_icons = os.path.join(self._get_ui_directory(), f"ressources")
|
||||||
|
|
||||||
|
table_default = self.find(QTableView, f"tableView")
|
||||||
|
|
||||||
|
self._table = D90TableDefaultModel(
|
||||||
|
table_view=table_default,
|
||||||
|
table_headers=self._trad.get_dict("table_headers"),
|
||||||
|
editable_headers=["name", "d90"],
|
||||||
|
delegates={},
|
||||||
|
data=self._data,
|
||||||
|
undo=self._undo_stack,
|
||||||
|
trad=self._trad
|
||||||
|
)
|
||||||
|
|
||||||
|
table_default.setModel(self._table)
|
||||||
|
table_default.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||||
|
table_default.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||||
|
table_default.setAlternatingRowColors(True)
|
||||||
|
|
||||||
|
layout = self.find(QVBoxLayout, f"verticalLayout_1")
|
||||||
|
toolBar = QToolBar()
|
||||||
|
layout.addWidget(toolBar)
|
||||||
|
|
||||||
|
action_add = QAction(self)
|
||||||
|
action_add.setIcon(QIcon(os.path.join(path_icons, f"add.png")))
|
||||||
|
action_add.triggered.connect(self.add)
|
||||||
|
action_delete = QAction(self)
|
||||||
|
action_delete.setIcon(QIcon(os.path.join(path_icons, f"del.png")))
|
||||||
|
action_delete.triggered.connect(self.delete)
|
||||||
|
|
||||||
|
toolBar.addAction(action_add)
|
||||||
|
toolBar.addAction(action_delete)
|
||||||
|
|
||||||
|
self.table_spec = QTableView()
|
||||||
|
layout.addWidget(self.table_spec)
|
||||||
|
|
||||||
|
self._delegate_reach = ComboBoxDelegate(
|
||||||
|
trad=self._trad,
|
||||||
|
data=self._study.river,
|
||||||
|
ic_spec_lst=self._data[0]._data,
|
||||||
|
parent=self,
|
||||||
|
mode="reaches"
|
||||||
|
)
|
||||||
|
self._delegate_kp = ComboBoxDelegate(
|
||||||
|
trad=self._trad,
|
||||||
|
data=self._study.river,
|
||||||
|
ic_spec_lst=self._data[0]._data,
|
||||||
|
parent=self,
|
||||||
|
mode="kp"
|
||||||
|
)
|
||||||
|
|
||||||
|
self._table_spec = D90TableModel(
|
||||||
|
table_view=self.table_spec,
|
||||||
|
table_headers=self._trad.get_dict("table_headers_spec"),
|
||||||
|
editable_headers=["name", "reach", "start_kp", "end_kp", "d90"],
|
||||||
|
delegates={
|
||||||
|
"reach": self._delegate_reach,
|
||||||
|
"start_kp": self._delegate_kp,
|
||||||
|
"end_kp": self._delegate_kp
|
||||||
|
},
|
||||||
|
data=self._data[0],
|
||||||
|
undo=self._undo_stack,
|
||||||
|
trad=self._trad,
|
||||||
|
river=self._study.river
|
||||||
|
)
|
||||||
|
|
||||||
|
self.table_spec.setModel(self._table_spec)
|
||||||
|
self.table_spec.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||||
|
self.table_spec.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||||
|
self.table_spec.setAlternatingRowColors(True)
|
||||||
|
|
||||||
|
selectionModel = self.table_spec.selectionModel()
|
||||||
|
index = self.table_spec.model().index(0, 0)
|
||||||
|
|
||||||
|
selectionModel.select(
|
||||||
|
index,
|
||||||
|
QItemSelectionModel.Rows |
|
||||||
|
QItemSelectionModel.ClearAndSelect |
|
||||||
|
QItemSelectionModel.Select
|
||||||
|
)
|
||||||
|
self.table_spec.scrollTo(index)
|
||||||
|
|
||||||
|
def index_selected_row(self):
|
||||||
|
#table = self.find(QTableView, f"tableView")
|
||||||
|
table = self.table_spec
|
||||||
|
rows = table.selectionModel()\
|
||||||
|
.selectedRows()
|
||||||
|
|
||||||
|
if len(rows) == 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return rows[0].row()
|
||||||
|
|
||||||
|
def index_selected_rows(self):
|
||||||
|
#table = self.find(QTableView, f"tableView")
|
||||||
|
table = self.table_spec
|
||||||
|
return list(
|
||||||
|
# Delete duplicate
|
||||||
|
set(
|
||||||
|
map(
|
||||||
|
lambda i: i.row(),
|
||||||
|
table.selectedIndexes()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def move_up(self):
|
||||||
|
row = self.index_selected_row()
|
||||||
|
self._table.move_up(row)
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def move_down(self):
|
||||||
|
row = self.index_selected_row()
|
||||||
|
self._table.move_down(row)
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def _copy(self):
|
||||||
|
rows = list(
|
||||||
|
map(
|
||||||
|
lambda row: row.row(),
|
||||||
|
self.tableView.selectionModel().selectedRows()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
table = list(
|
||||||
|
map(
|
||||||
|
lambda eic: list(
|
||||||
|
map(
|
||||||
|
lambda k: eic[1][k],
|
||||||
|
["kp", "discharge", "elevation"]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
filter(
|
||||||
|
lambda eic: eic[0] in rows,
|
||||||
|
enumerate(self._ics.lst())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.copyTableIntoClipboard(table)
|
||||||
|
|
||||||
|
def _paste(self):
|
||||||
|
header, data = self.parseClipboardTable()
|
||||||
|
|
||||||
|
if len(data) + len(header) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
"IC: Paste: " +
|
||||||
|
f"header = {header}, " +
|
||||||
|
f"data = {data}"
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
row = self.index_selected_row()
|
||||||
|
# self._table.paste(row, header, data)
|
||||||
|
self._table.paste(row, [], data)
|
||||||
|
except Exception as e:
|
||||||
|
logger_exception(e)
|
||||||
|
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def _undo(self):
|
||||||
|
self._table.undo()
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def _redo(self):
|
||||||
|
self._table.redo()
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def add(self):
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
if len(self._data[0]._data) == 0 or len(rows) == 0:
|
||||||
|
self._table_spec.add(0)
|
||||||
|
else:
|
||||||
|
self._table_spec.add(rows[0])
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
print("del")
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
if len(rows) == 0:
|
||||||
|
print("len 0")
|
||||||
|
return
|
||||||
|
self._table_spec.delete(rows)
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
# translate.py -- Pamhyr
|
||||||
|
# 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 -*-
|
||||||
|
|
||||||
|
from PyQt5.QtCore import QCoreApplication
|
||||||
|
|
||||||
|
from View.Translate import MainTranslate
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
|
class D90AdisTSTranslate(MainTranslate):
|
||||||
|
def __init__(self):
|
||||||
|
super(D90AdisTSTranslate, self).__init__()
|
||||||
|
|
||||||
|
self._dict["D90 AdisTS"] = _translate(
|
||||||
|
"D90AdisTS", "D90 AdisTS")
|
||||||
|
|
||||||
|
self._dict["kp"] = self._dict["unit_kp"]
|
||||||
|
|
||||||
|
self._sub_dict["table_headers"] = {
|
||||||
|
"name": self._dict["name"],
|
||||||
|
"d90": _translate("Unit", "D90"),
|
||||||
|
}
|
||||||
|
|
||||||
|
self._sub_dict["table_headers_spec"] = {
|
||||||
|
"name": self._dict["name"],
|
||||||
|
"reach": self._dict["reach"],
|
||||||
|
"start_kp": _translate("Unit", "Start_KP (m)"),
|
||||||
|
"end_kp": _translate("Unit", "End_KP (m)"),
|
||||||
|
"d90": _translate("Unit", "D90"),
|
||||||
|
}
|
||||||
|
|
@ -78,6 +78,7 @@ from View.Debug.Window import ReplWindow
|
||||||
from View.OutputKpAdisTS.Window import OutputKpAdisTSWindow
|
from View.OutputKpAdisTS.Window import OutputKpAdisTSWindow
|
||||||
from View.Pollutants.Window import PollutantsWindow
|
from View.Pollutants.Window import PollutantsWindow
|
||||||
from View.D90AdisTS.Window import D90AdisTSWindow
|
from View.D90AdisTS.Window import D90AdisTSWindow
|
||||||
|
from View.DIFAdisTS.Window import D90AdisTSWindow
|
||||||
|
|
||||||
# Optional internal display of documentation for make the application
|
# Optional internal display of documentation for make the application
|
||||||
# package lighter...
|
# package lighter...
|
||||||
|
|
@ -123,7 +124,7 @@ define_model_action = [
|
||||||
"action_menu_boundary_conditions_sediment",
|
"action_menu_boundary_conditions_sediment",
|
||||||
"action_menu_rep_additional_lines", "action_menu_output_kp",
|
"action_menu_rep_additional_lines", "action_menu_output_kp",
|
||||||
"action_menu_run_adists", "action_menu_pollutants",
|
"action_menu_run_adists", "action_menu_pollutants",
|
||||||
"action_menu_d90",
|
"action_menu_d90", "action_menu_dif",
|
||||||
]
|
]
|
||||||
|
|
||||||
action = (
|
action = (
|
||||||
|
|
@ -237,6 +238,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
"""
|
"""
|
||||||
actions = {
|
actions = {
|
||||||
# Menu action
|
# Menu action
|
||||||
|
"action_menu_dif": self.open_dif,
|
||||||
"action_menu_d90": self.open_d90,
|
"action_menu_d90": self.open_d90,
|
||||||
"action_menu_pollutants": self.open_pollutants,
|
"action_menu_pollutants": self.open_pollutants,
|
||||||
"action_menu_run_adists":self.run_solver_adists,
|
"action_menu_run_adists":self.run_solver_adists,
|
||||||
|
|
@ -888,6 +890,25 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
)
|
)
|
||||||
D90AdisTS.show()
|
D90AdisTS.show()
|
||||||
|
|
||||||
|
def open_dif(self):
|
||||||
|
if len(self._study.river.d90_adists.lst) != 0:
|
||||||
|
d90_default = self._study.river.d90_adists.lst[0]
|
||||||
|
else:
|
||||||
|
d90_default = self._study.river.d90_adists.new(0)
|
||||||
|
|
||||||
|
if self.sub_window_exists(
|
||||||
|
D90AdisTSWindow,
|
||||||
|
data=[self._study, None, d90_default]
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
D90AdisTS = D90AdisTSWindow(
|
||||||
|
study=self._study,
|
||||||
|
parent=self,
|
||||||
|
data=d90_default
|
||||||
|
)
|
||||||
|
D90AdisTS.show()
|
||||||
|
|
||||||
def open_pollutants(self):
|
def open_pollutants(self):
|
||||||
if self.sub_window_exists(
|
if self.sub_window_exists(
|
||||||
PollutantsWindow,
|
PollutantsWindow,
|
||||||
|
|
|
||||||
|
|
@ -220,6 +220,7 @@
|
||||||
<addaction name="action_menu_output_kp"/>
|
<addaction name="action_menu_output_kp"/>
|
||||||
<addaction name="action_menu_pollutants"/>
|
<addaction name="action_menu_pollutants"/>
|
||||||
<addaction name="action_menu_d90"/>
|
<addaction name="action_menu_d90"/>
|
||||||
|
<addaction name="action_menu_dif"/>
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="menu_File"/>
|
<addaction name="menu_File"/>
|
||||||
<addaction name="menu_network"/>
|
<addaction name="menu_network"/>
|
||||||
|
|
@ -767,6 +768,11 @@
|
||||||
<string>D90</string>
|
<string>D90</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="action_menu_dif">
|
||||||
|
<property name="text">
|
||||||
|
<string>DIF</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue