mirror of https://gitlab.com/pamhyr/pamhyr2
Temperature: Interface for temperature's initial conditions
parent
333a8a0970
commit
95dd648b90
|
|
@ -0,0 +1,229 @@
|
|||
# InitialConditionsTemperature.py -- Pamhyr
|
||||
# Copyright (C) 2023-2025 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.Scenario import Scenario
|
||||
|
||||
from Model.InitialConditionsTemperature.InitialConditionsTemperatureSpec \
|
||||
import ICTemperatureSpec
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class InitialConditionsTemperature(SQLSubModel):
|
||||
_sub_classes = [
|
||||
ICTemperatureSpec,
|
||||
]
|
||||
|
||||
def __init__(self, id: int = -1, name: str = "default",
|
||||
status=None, owner_scenario=-1):
|
||||
super(InitialConditionsTemperature, self).__init__(
|
||||
id=id, status=status,
|
||||
owner_scenario=owner_scenario
|
||||
)
|
||||
self._status = status
|
||||
|
||||
self._name = name
|
||||
self._temperature = None
|
||||
self._data = []
|
||||
|
||||
@classmethod
|
||||
def _db_create(cls, execute, ext=""):
|
||||
execute(f"""
|
||||
CREATE TABLE initial_conditions_temperature{ext}(
|
||||
{cls.create_db_add_pamhyr_id()},
|
||||
deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
name TEXT NOT NULL,
|
||||
temperature REAL NOT NULL,
|
||||
{Scenario.create_db_add_scenario()},
|
||||
{Scenario.create_db_add_scenario_fk()}
|
||||
)
|
||||
""")
|
||||
|
||||
return cls._create_submodel(execute)
|
||||
|
||||
@classmethod
|
||||
def _db_update(cls, execute, version, data=None):
|
||||
major, minor, release = version.strip().split(".")
|
||||
|
||||
if major == "0":
|
||||
if int(minor) < 2 or (int(minor) == 2 and int(release) < 7):
|
||||
table_name = "initial_conditions_temperature"
|
||||
if not cls.is_table_exists(execute, table_name):
|
||||
cls._db_create(execute)
|
||||
|
||||
return cls._update_submodel(execute, version, data)
|
||||
|
||||
@classmethod
|
||||
def _db_load(cls, execute, data=None):
|
||||
new = []
|
||||
status = data['status']
|
||||
scenario = data["scenario"]
|
||||
loaded = data['loaded_pid']
|
||||
|
||||
if scenario is None:
|
||||
return new
|
||||
|
||||
table = execute(
|
||||
"SELECT pamhyr_id, deleted, " +
|
||||
"name, temperature, scenario " +
|
||||
"FROM initial_conditions_temperature " +
|
||||
f"WHERE scenario = {scenario.id} " +
|
||||
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))})"
|
||||
)
|
||||
|
||||
if table is not None:
|
||||
for row in table:
|
||||
it = iter(row)
|
||||
|
||||
pid = next(it)
|
||||
deleted = (next(it) == 1)
|
||||
name = next(it)
|
||||
temperature = next(it)
|
||||
owner_scenario = next(it)
|
||||
|
||||
ic = cls(
|
||||
id=pid,
|
||||
name=name,
|
||||
status=status,
|
||||
owner_scenario=owner_scenario
|
||||
)
|
||||
if deleted:
|
||||
ic.set_as_deleted()
|
||||
|
||||
ic.temperature = temperature
|
||||
|
||||
data['ic_default_id'] = pid
|
||||
ic._data = ICTemperatureSpec._db_load(execute, data)
|
||||
|
||||
loaded.add(pid)
|
||||
new.append(ic)
|
||||
|
||||
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
|
||||
|
||||
execute(
|
||||
"DELETE FROM initial_conditions_temperature " +
|
||||
f"WHERE pamhyr_id = {self.id} " +
|
||||
f"AND scenario = {self._status.scenario_id}"
|
||||
)
|
||||
|
||||
temperature = self._temperature if \
|
||||
self._temperature is not None else 0.0
|
||||
|
||||
sql = (
|
||||
"INSERT INTO " +
|
||||
"initial_conditions_temperature(" +
|
||||
"pamhyr_id, deleted, name, temperature, " +
|
||||
"scenario" +
|
||||
") " +
|
||||
"VALUES (" +
|
||||
f"{self.id}, {self.is_deleted()}, " +
|
||||
f"'{self._db_format(self._name)}', " +
|
||||
f"{temperature}, {self._status.scenario_id}" +
|
||||
")"
|
||||
)
|
||||
|
||||
execute(sql)
|
||||
|
||||
data['ic_default_id'] = self.id
|
||||
execute(
|
||||
"DELETE FROM initial_conditions_temperature_spec " +
|
||||
f"WHERE ic_default = {self.id} " +
|
||||
f"AND scenario = {self._status.scenario_id}"
|
||||
)
|
||||
|
||||
for ic_spec in self._data:
|
||||
ic_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.modified()
|
||||
|
||||
@property
|
||||
def temperature(self):
|
||||
return self._temperature
|
||||
|
||||
@temperature.setter
|
||||
def temperature(self, temperature):
|
||||
self._temperature = temperature
|
||||
self.modified()
|
||||
|
||||
def new(self, index):
|
||||
n = ICTemperatureSpec(status=self._status)
|
||||
self._data.insert(index, n)
|
||||
self.modified()
|
||||
return n
|
||||
|
||||
def delete(self, data):
|
||||
list(
|
||||
map(
|
||||
lambda x: x.set_as_deleted(),
|
||||
data
|
||||
)
|
||||
)
|
||||
self.modified()
|
||||
|
||||
def delete_i(self, indexes):
|
||||
list(
|
||||
map(
|
||||
lambda e: e[1].set_as_deleted(),
|
||||
filter(
|
||||
lambda e: e[0] in indexes,
|
||||
enumerate(self._data)
|
||||
)
|
||||
)
|
||||
)
|
||||
self.modified()
|
||||
|
||||
def insert(self, index, data):
|
||||
if data in self._data:
|
||||
self.undelete([data])
|
||||
else:
|
||||
self._data.insert(index, data)
|
||||
|
||||
self.modified()
|
||||
|
||||
def undelete(self, lst):
|
||||
for x in lst:
|
||||
x.set_as_not_deleted()
|
||||
|
||||
self.modified()
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
# InitialConditionsTemperatureList.py -- Pamhyr
|
||||
# Copyright (C) 2023-2025 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.PamhyrListExt import PamhyrModelList
|
||||
from Model.InitialConditionsTemperature.InitialConditionsTemperature \
|
||||
import InitialConditionsTemperature
|
||||
|
||||
|
||||
class InitialConditionsTemperatureList(PamhyrModelList):
|
||||
_sub_classes = [
|
||||
InitialConditionsTemperature,
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def _db_load(cls, execute, data=None):
|
||||
new = cls(status=data['status'])
|
||||
|
||||
if data is None:
|
||||
data = {}
|
||||
|
||||
new._lst = InitialConditionsTemperature._db_load(
|
||||
execute, data
|
||||
)
|
||||
|
||||
return new
|
||||
|
||||
def _db_save(self, execute, data=None):
|
||||
execute(
|
||||
"DELETE FROM initial_conditions_temperature " +
|
||||
f"WHERE scenario = {self._status.scenario_id}"
|
||||
)
|
||||
|
||||
if data is None:
|
||||
data = {}
|
||||
|
||||
for ic in self._lst:
|
||||
ic._db_save(execute, data=data)
|
||||
|
||||
return True
|
||||
|
||||
def new(self, index):
|
||||
n = InitialConditionsTemperature(status=self._status)
|
||||
self._lst.insert(index, n)
|
||||
self._status.modified()
|
||||
return n
|
||||
|
||||
@property
|
||||
def Initial_Conditions_List(self):
|
||||
return self.lst
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
# InitialConditionsAdisTSSpec.py -- Pamhyr
|
||||
# Copyright (C) 2023-2025 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
|
||||
from Model.Scenario import Scenario
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class ICTemperatureSpec(SQLSubModel):
|
||||
_sub_classes = []
|
||||
|
||||
def __init__(self, id: int = -1, name: str = "",
|
||||
status=None, owner_scenario=None):
|
||||
super(ICTemperatureSpec, self).__init__()
|
||||
|
||||
self._status = status
|
||||
|
||||
self._name_section = name
|
||||
self._reach = None
|
||||
self._start_rk = None
|
||||
self._end_rk = None
|
||||
self._temperature = None
|
||||
|
||||
@classmethod
|
||||
def _db_create(cls, execute, ext=""):
|
||||
execute(f"""
|
||||
CREATE TABLE initial_conditions_temperature_spec{ext}(
|
||||
{cls.create_db_add_pamhyr_id()},
|
||||
deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
ic_default INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
reach INTEGER NOT NULL,
|
||||
start_rk REAL NOT NULL,
|
||||
end_rk REAL NOT NULL,
|
||||
temperature REAL NOT NULL,
|
||||
{Scenario.create_db_add_scenario()},
|
||||
{Scenario.create_db_add_scenario_fk()},
|
||||
FOREIGN KEY(ic_default)
|
||||
REFERENCES initial_conditions_temperature(pamhyr_id),
|
||||
FOREIGN KEY(reach) REFERENCES river_reach(pamhyr_id)
|
||||
)
|
||||
""")
|
||||
|
||||
return cls._create_submodel(execute)
|
||||
|
||||
@classmethod
|
||||
def _db_update(cls, execute, version, data=None):
|
||||
major, minor, release = version.strip().split(".")
|
||||
|
||||
if major == "0":
|
||||
if int(minor) < 2 or (int(minor) == 2 and int(release) < 7):
|
||||
table_name = "initial_conditions_temperature_spec"
|
||||
if not cls.is_table_exists(execute, table_name):
|
||||
cls._db_create(execute)
|
||||
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def _db_load(cls, execute, data=None):
|
||||
new = []
|
||||
status = data['status']
|
||||
reachs = data["edges"]
|
||||
scenario = data["scenario"]
|
||||
loaded = data['loaded_pid']
|
||||
|
||||
if scenario is None:
|
||||
return new
|
||||
|
||||
table = execute(
|
||||
"SELECT pamhyr_id, deleted, name, reach, start_rk, end_rk, " +
|
||||
"temperature, scenario " +
|
||||
"FROM initial_conditions_temperature_spec " +
|
||||
f"WHERE ic_default = {data['ic_default_id']} " +
|
||||
f"AND scenario = {scenario.id} " +
|
||||
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) "
|
||||
)
|
||||
|
||||
if table is not None:
|
||||
for row in table:
|
||||
it = iter(row)
|
||||
|
||||
id = next(it)
|
||||
deleted = (next(it) == 1)
|
||||
name = next(it)
|
||||
reach = next(it)
|
||||
start_rk = next(it)
|
||||
end_rk = next(it)
|
||||
temperature = next(it)
|
||||
owner_scenario = next(it)
|
||||
|
||||
new_spec = cls(
|
||||
id=id, name=name,
|
||||
status=status,
|
||||
owner_scenario=owner_scenario
|
||||
)
|
||||
if deleted:
|
||||
new_spec.set_as_deleted()
|
||||
|
||||
new_spec.reach = reach
|
||||
new_spec.start_rk = start_rk
|
||||
new_spec.end_rk = end_rk
|
||||
new_spec.temperature = temperature
|
||||
|
||||
# loaded.add(pid)
|
||||
new.append(new_spec)
|
||||
|
||||
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
|
||||
|
||||
ic_default = data['ic_default_id']
|
||||
|
||||
sql = (
|
||||
"INSERT INTO " +
|
||||
"initial_conditions_temperature_spec(pamhyr_id, deleted, " +
|
||||
"ic_default, name, reach, " +
|
||||
"start_rk, end_rk, temperature, scenario) " +
|
||||
"VALUES (" +
|
||||
f"{self.id}, {self._db_format(self.is_deleted())}, " +
|
||||
f"{ic_default}, " +
|
||||
f"'{self._db_format(self._name_section)}', " +
|
||||
f"{self._reach}, " +
|
||||
f"{self._start_rk}, {self._end_rk}, " +
|
||||
f"{self._temperature}, " +
|
||||
f"{self._status.scenario_id}" +
|
||||
")"
|
||||
)
|
||||
execute(sql)
|
||||
|
||||
return True
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name_section
|
||||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
self._name_section = name
|
||||
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_rk(self):
|
||||
return self._start_rk
|
||||
|
||||
@start_rk.setter
|
||||
def start_rk(self, start_rk):
|
||||
self._start_rk = start_rk
|
||||
self._status.modified()
|
||||
|
||||
@property
|
||||
def end_rk(self):
|
||||
return self._end_rk
|
||||
|
||||
@end_rk.setter
|
||||
def end_rk(self, end_rk):
|
||||
self._end_rk = end_rk
|
||||
self._status.modified()
|
||||
|
||||
@property
|
||||
def temperature(self):
|
||||
return self._temperature
|
||||
|
||||
@temperature.setter
|
||||
def temperature(self, temperature):
|
||||
self._temperature = temperature
|
||||
self._status.modified()
|
||||
|
|
@ -59,6 +59,10 @@ from Model.LateralContributionsAdisTS.LateralContributionsAdisTSList \
|
|||
import LateralContributionsAdisTSList
|
||||
from Model.D90AdisTS.D90AdisTSList import D90AdisTSList
|
||||
from Model.DIFAdisTS.DIFAdisTSList import DIFAdisTSList
|
||||
|
||||
from Model.InitialConditionsTemperature.InitialConditionsTemperatureList \
|
||||
import InitialConditionsTemperatureList
|
||||
|
||||
from Model.GeoTIFF.GeoTIFFList import GeoTIFFList
|
||||
from Model.Results.Results import Results
|
||||
|
||||
|
|
@ -475,6 +479,7 @@ class River(Graph):
|
|||
LateralContributionsAdisTSList,
|
||||
D90AdisTSList,
|
||||
DIFAdisTSList,
|
||||
InitialConditionsTemperatureList,
|
||||
GeoTIFFList,
|
||||
Results
|
||||
]
|
||||
|
|
@ -512,6 +517,8 @@ class River(Graph):
|
|||
status=self._status)
|
||||
self._D90AdisTS = D90AdisTSList(status=self._status)
|
||||
self._DIFAdisTS = DIFAdisTSList(status=self._status)
|
||||
self._InitialConditionsTemperature = InitialConditionsTemperatureList(
|
||||
status=self._status)
|
||||
|
||||
self._geotiff = GeoTIFFList(status=self._status)
|
||||
|
||||
|
|
@ -627,6 +634,9 @@ class River(Graph):
|
|||
|
||||
new._DIFAdisTS = DIFAdisTSList._db_load(execute, data)
|
||||
|
||||
new._InitialConditionsTemperature = \
|
||||
InitialConditionsTemperatureList._db_load(execute, data)
|
||||
|
||||
new._geotiff = GeoTIFFList._db_load(execute, data)
|
||||
|
||||
return new
|
||||
|
|
@ -661,6 +671,7 @@ class River(Graph):
|
|||
objs.append(self._LateralContributionsAdisTS)
|
||||
objs.append(self._D90AdisTS)
|
||||
objs.append(self._DIFAdisTS)
|
||||
objs.append(self._InitialConditionsTemperature)
|
||||
|
||||
objs.append(self._geotiff)
|
||||
|
||||
|
|
@ -740,6 +751,7 @@ class River(Graph):
|
|||
self._BoundaryConditionsAdisTS,
|
||||
self._LateralContributionsAdisTS,
|
||||
self._D90AdisTS, self._DIFAdisTS,
|
||||
self._InitialConditionsTemperature,
|
||||
self._geotiff,
|
||||
]
|
||||
|
||||
|
|
@ -873,6 +885,10 @@ Last export at: @date."""
|
|||
def dif_adists(self):
|
||||
return self._DIFAdisTS
|
||||
|
||||
@property
|
||||
def ic_temperature(self):
|
||||
return self._InitialConditionsTemperature
|
||||
|
||||
def get_params(self, solver):
|
||||
if solver in self._parameters:
|
||||
return self._parameters[solver]
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ logger = logging.getLogger()
|
|||
|
||||
|
||||
class Study(SQLModel):
|
||||
_version = "0.2.6"
|
||||
_version = "0.2.7"
|
||||
|
||||
_sub_classes = [
|
||||
Scenario,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,240 @@
|
|||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023-2025 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.InitialConditionsTemperature.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 == "rk":
|
||||
reach_id = self._ic_spec_lst[index.row()].reach
|
||||
|
||||
reach = next(filter(lambda edge: edge.id == reach_id,
|
||||
self._data.edges()), None)
|
||||
|
||||
if reach_id is not None:
|
||||
val = list(
|
||||
map(
|
||||
lambda rk: str(rk), reach.reach.get_rk()
|
||||
)
|
||||
)
|
||||
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 InitialConditionTableModel(PamhyrTableModel):
|
||||
def __init__(self, river=None, data=None, **kwargs):
|
||||
self._river = river
|
||||
|
||||
super(InitialConditionTableModel, self).__init__(data=data, **kwargs)
|
||||
|
||||
self._data = data
|
||||
|
||||
def _setup_lst(self):
|
||||
self._lst = list(
|
||||
filter(
|
||||
lambda ica: ica._deleted is False,
|
||||
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] == "name":
|
||||
n = self._lst[row].name
|
||||
if n is None or n == "":
|
||||
return self._trad['not_associated']
|
||||
return n
|
||||
elif self._headers[column] == "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] == "start_rk":
|
||||
n = self._lst[row].start_rk
|
||||
if n is None:
|
||||
return self._trad['not_associated']
|
||||
return n
|
||||
elif self._headers[column] == "end_rk":
|
||||
n = self._lst[row].end_rk
|
||||
if n is None:
|
||||
return self._trad['not_associated']
|
||||
return n
|
||||
elif self._headers[column] == "temperature":
|
||||
n = self._lst[row].temperature
|
||||
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
|
||||
|
||||
if self.is_same_data(index, value):
|
||||
return False
|
||||
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
try:
|
||||
if self._headers[column] in ["name", "temperature"]:
|
||||
self._undo.push(
|
||||
SetCommand(
|
||||
self._lst, row, self._headers[column], value
|
||||
)
|
||||
)
|
||||
else:
|
||||
self._undo.push(
|
||||
SetCommandSpec(
|
||||
self._lst, row, self._headers[column],
|
||||
(self._river.edge(value).id
|
||||
if self._headers[column] == "reach"
|
||||
else value
|
||||
)
|
||||
)
|
||||
)
|
||||
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._setup_lst()
|
||||
self.endInsertRows()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def delete(self, rows, parent=QModelIndex()):
|
||||
self.beginRemoveRows(parent, rows[0], rows[-1])
|
||||
|
||||
data_rows = {
|
||||
id(ica): i for i, ica in enumerate(self._data._data)
|
||||
}
|
||||
self._undo.push(
|
||||
DelCommand(
|
||||
self._data,
|
||||
self._data._data,
|
||||
[data_rows[id(self._lst[row])] for row in rows]
|
||||
)
|
||||
)
|
||||
|
||||
self._setup_lst()
|
||||
self.endRemoveRows()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def undo(self):
|
||||
self._undo.undo()
|
||||
self._setup_lst()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def redo(self):
|
||||
self._undo.redo()
|
||||
self._setup_lst()
|
||||
self.layoutChanged.emit()
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023-2025 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.InitialConditionsTemperature.UndoCommand import (
|
||||
SetCommand,
|
||||
)
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class InitialConditionTableDefaultModel(PamhyrTableModel):
|
||||
def __init__(self, **kwargs):
|
||||
super(InitialConditionTableDefaultModel, 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] == "name":
|
||||
return self._data[row].name
|
||||
elif self._headers[column] == "temperature":
|
||||
n = self._data[row].temperature
|
||||
if n is None:
|
||||
return 0
|
||||
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,153 @@
|
|||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023-2025 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.InitialConditionsTemperature.InitialConditionsTemperature \
|
||||
import InitialConditionsTemperature
|
||||
from Model.InitialConditionsTemperature.InitialConditionsTemperatureList \
|
||||
import InitialConditionsTemperatureList
|
||||
|
||||
|
||||
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 == "temperature":
|
||||
self._old = self._data[self._row].temperature
|
||||
|
||||
_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 == "temperature":
|
||||
self._data[self._row].temperature = self._old
|
||||
|
||||
def redo(self):
|
||||
if self._column == "name":
|
||||
self._data[self._row].name = self._new
|
||||
elif self._column == "temperature":
|
||||
self._data[self._row].temperature = 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_rk":
|
||||
self._old = self._data[self._row].start_rk
|
||||
elif self._column == "end_rk":
|
||||
self._old = self._data[self._row].end_rk
|
||||
elif self._column == "temperature":
|
||||
self._old = self._data[self._row].temperature
|
||||
|
||||
_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_rk":
|
||||
self._data[self._row].start_rk = self._old
|
||||
elif self._column == "end_rk":
|
||||
self._data[self._row].end_rk = self._old
|
||||
elif self._column == "temperature":
|
||||
self._data[self._row].temperature = 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_rk":
|
||||
self._data[self._row].start_rk = self._new
|
||||
elif self._column == "end_rk":
|
||||
self._data[self._row].end_rk = self._new
|
||||
elif self._column == "temperature":
|
||||
self._data[self._row].temperature = 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._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,312 @@
|
|||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023-2025 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.InitialConditionsTemperature.UndoCommand import (
|
||||
SetCommand,
|
||||
)
|
||||
|
||||
from View.InitialConditionsTemperature.TableDefault import (
|
||||
InitialConditionTableDefaultModel,
|
||||
)
|
||||
|
||||
from View.InitialConditionsTemperature.Table import (
|
||||
InitialConditionTableModel, ComboBoxDelegate,
|
||||
)
|
||||
|
||||
from View.InitialConditionsTemperature.translate import IcTemperatureTranslate
|
||||
|
||||
from Solver.Mage import Mage8
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class InitialConditionsTemperatureWindow(PamhyrWindow):
|
||||
_pamhyr_ui = "InitialConditionsTemperature"
|
||||
_pamhyr_name = "Initial condition Temperature"
|
||||
|
||||
def __init__(self, data=None, study=None,
|
||||
config=None, parent=None):
|
||||
self._data = []
|
||||
self._data.append(data)
|
||||
trad = IcTemperatureTranslate()
|
||||
|
||||
name = (
|
||||
trad[self._pamhyr_name] +
|
||||
" - " + study.name
|
||||
)
|
||||
|
||||
super(InitialConditionsTemperatureWindow, self).__init__(
|
||||
title=name,
|
||||
study=study,
|
||||
config=config,
|
||||
trad=trad,
|
||||
parent=parent
|
||||
)
|
||||
self._hash_data.append(data)
|
||||
|
||||
# self._ics_Temperature_lst = study.river.ic_Temperature
|
||||
|
||||
self.setup_table()
|
||||
|
||||
def setup_table(self):
|
||||
|
||||
path_icons = os.path.join(self._get_ui_directory(), f"ressources")
|
||||
|
||||
table_default = self.find(QTableView, f"tableView")
|
||||
|
||||
if self._study.is_editable():
|
||||
editable_headers = self._trad.get_dict("table_headers")
|
||||
else:
|
||||
editable_headers = []
|
||||
|
||||
self._table = InitialConditionTableDefaultModel(
|
||||
table_view=table_default,
|
||||
table_headers=self._trad.get_dict("table_headers"),
|
||||
editable_headers=editable_headers,
|
||||
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")))
|
||||
|
||||
if self._study.is_editable():
|
||||
action_add.triggered.connect(self.add)
|
||||
action_delete = QAction(self)
|
||||
action_delete.setIcon(QIcon(os.path.join(path_icons, f"del.png")))
|
||||
|
||||
if self._study.is_editable():
|
||||
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_rk = ComboBoxDelegate(
|
||||
trad=self._trad,
|
||||
data=self._study.river,
|
||||
ic_spec_lst=self._data[0]._data,
|
||||
parent=self,
|
||||
mode="rk"
|
||||
)
|
||||
|
||||
if self._study.is_editable():
|
||||
editable_headers_spec = self._trad.get_dict("table_headers_spec")
|
||||
else:
|
||||
editable_headers_spec = []
|
||||
|
||||
self._table_spec = InitialConditionTableModel(
|
||||
table_view=self.table_spec,
|
||||
table_headers=self._trad.get_dict("table_headers_spec"),
|
||||
editable_headers=editable_headers_spec,
|
||||
delegates={
|
||||
"reach": self._delegate_reach,
|
||||
"start_rk": self._delegate_rk,
|
||||
"end_rk": self._delegate_rk
|
||||
},
|
||||
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],
|
||||
["rk", "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):
|
||||
undo_stack = self._undo_stack
|
||||
if undo_stack is None or not undo_stack.canUndo():
|
||||
return
|
||||
|
||||
if isinstance(undo_stack.command(undo_stack.index() - 1), SetCommand):
|
||||
self._table.undo()
|
||||
else:
|
||||
self._table_spec.undo()
|
||||
|
||||
self._update()
|
||||
|
||||
def _redo(self):
|
||||
undo_stack = self._undo_stack
|
||||
if undo_stack is None or not undo_stack.canRedo():
|
||||
return
|
||||
|
||||
if isinstance(undo_stack.command(undo_stack.index()), SetCommand):
|
||||
self._table.redo()
|
||||
else:
|
||||
self._table_spec.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):
|
||||
rows = self.index_selected_rows()
|
||||
if len(rows) == 0:
|
||||
return
|
||||
self._table_spec.delete(rows)
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# translate.py -- Pamhyr
|
||||
# Copyright (C) 2023-2025 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 IcTemperatureTranslate(MainTranslate):
|
||||
def __init__(self):
|
||||
super(IcTemperatureTranslate, self).__init__()
|
||||
|
||||
self._dict["Initial condition Temperature"] = _translate(
|
||||
"InitialConditionTemperature", "Initial condition temperature")
|
||||
|
||||
self._dict["rk"] = self._dict["unit_rk"]
|
||||
|
||||
self._sub_dict["table_headers"] = {
|
||||
"name": self._dict["name"],
|
||||
"temperature": self._dict["unit_temperature"],
|
||||
}
|
||||
|
||||
self._sub_dict["table_headers_spec"] = {
|
||||
"name": self._dict["name"],
|
||||
"reach": self._dict["reach"],
|
||||
"start_rk": _translate("Unit", "Start_RK (m)"),
|
||||
"end_rk": _translate("Unit", "End_RK (m)"),
|
||||
"temperature": self._dict["unit_temperature"],
|
||||
}
|
||||
|
|
@ -106,6 +106,10 @@ from View.Pollutants.Window import PollutantsWindow
|
|||
from View.D90AdisTS.Window import D90AdisTSWindow
|
||||
from View.DIFAdisTS.Window import DIFAdisTSWindow
|
||||
|
||||
from View.InitialConditionsTemperature.Window import (
|
||||
InitialConditionsTemperatureWindow
|
||||
)
|
||||
|
||||
from Solver.Solvers import GenericSolver
|
||||
|
||||
from Model.Results.Results import Results
|
||||
|
|
@ -157,7 +161,10 @@ define_model_action = [
|
|||
"action_menu_boundary_conditions_sediment",
|
||||
"action_menu_rep_additional_lines", "action_menu_output_rk",
|
||||
"action_menu_run_adists", "action_menu_pollutants",
|
||||
"action_menu_d90", "action_menu_dif", "action_menu_edit_geotiff"
|
||||
"action_menu_d90", "action_menu_dif", "action_menu_edit_geotiff",
|
||||
"action_menu_boundary_conditions_temperature",
|
||||
"action_menu_initial_conditions_temperature",
|
||||
"action_menu_weather_parameters",
|
||||
]
|
||||
|
||||
action = (
|
||||
|
|
@ -267,6 +274,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||
"""
|
||||
actions = {
|
||||
# Menu action
|
||||
"action_menu_initial_conditions_temperature":
|
||||
self.open_initial_conditions_temperature,
|
||||
"action_menu_dif": self.open_dif,
|
||||
"action_menu_d90": self.open_d90,
|
||||
"action_menu_pollutants": self.open_pollutants,
|
||||
|
|
@ -1022,6 +1031,27 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||
# SUB WINDOWS #
|
||||
###############
|
||||
|
||||
def open_initial_conditions_temperature(self):
|
||||
|
||||
iclist = self._study.river.ic_temperature.lst
|
||||
if len(iclist) != 0:
|
||||
ic_default = iclist[0]
|
||||
else:
|
||||
ic_default = self._study.river.ic_temperature.new(0)
|
||||
|
||||
if self.sub_window_exists(
|
||||
InitialConditionsTemperatureWindow,
|
||||
data=[self._study, None, ic_default]
|
||||
):
|
||||
return
|
||||
|
||||
InitialConditions = InitialConditionsTemperatureWindow(
|
||||
study=self._study,
|
||||
parent=self,
|
||||
data=ic_default
|
||||
)
|
||||
InitialConditions.show()
|
||||
|
||||
def open_d90(self):
|
||||
if len(self._study.river.d90_adists.lst) != 0:
|
||||
d90_default = self._study.river.d90_adists.lst[0]
|
||||
|
|
|
|||
|
|
@ -161,6 +161,8 @@ class UnitTranslate(CommonWordTranslate):
|
|||
self._dict["unit_mass"] = _translate("Unit", "Mass (kg)")
|
||||
self._dict["unit_concentration"] = _translate(
|
||||
"Unit", "Concentration") + " (kg/m³)"
|
||||
self._dict["unit_temperature"] = _translate(
|
||||
"Unit", "Temperature") + " (°C)"
|
||||
|
||||
|
||||
class MainTranslate(UnitTranslate):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,118 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>849</width>
|
||||
<height>576</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QSplitter" name="splitter_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QTableView" name="tableView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_1"/>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>849</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="windowTitle">
|
||||
<string>toolBar</string>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="action_add"/>
|
||||
<addaction name="action_del"/>
|
||||
<addaction name="action_sort"/>
|
||||
</widget>
|
||||
<action name="action_add">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>ressources/add.png</normaloff>ressources/add.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Add new initial condition</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_del">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>ressources/del.png</normaloff>ressources/del.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>delete</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Delete inital condition</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_sort">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>ressources/sort_1-9.png</normaloff>ressources/sort_1-9.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>sort</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Sort inital conditions</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_import">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>ressources/import.png</normaloff>ressources/import.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Import</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Import from file</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -232,11 +232,11 @@
|
|||
<property name="title">
|
||||
<string>Temperature</string>
|
||||
</property>
|
||||
<addaction name="action_menu_boundary_conditions_temp"/>
|
||||
<addaction name="action_menu_initial_conditions_temp"/>
|
||||
<addaction name="action_menu_boundary_conditions_temperature"/>
|
||||
<addaction name="action_menu_initial_conditions_temperature"/>
|
||||
<addaction name="action_menu_weather_parameters"/>
|
||||
<addaction name="action_menu_dif_temp"/>
|
||||
<addaction name="action_menu_lateral_contribution"/>
|
||||
<addaction name="action_menu_dif_temperature"/>
|
||||
<addaction name="action_menu_lateral_contribution_temperature"/>
|
||||
</widget>
|
||||
<addaction name="menu_File"/>
|
||||
<addaction name="menu_scenarios"/>
|
||||
|
|
@ -822,12 +822,12 @@
|
|||
<string>GeoTIFF</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_menu_initial_conditions_temp">
|
||||
<action name="action_menu_initial_conditions_temperature">
|
||||
<property name="text">
|
||||
<string>Initial conditions</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_menu_boundary_conditions_temp">
|
||||
<action name="action_menu_boundary_conditions_temperature">
|
||||
<property name="text">
|
||||
<string>Boundary conditions</string>
|
||||
</property>
|
||||
|
|
@ -837,12 +837,12 @@
|
|||
<string>Weather parameters</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_menu_dif_temp">
|
||||
<action name="action_menu_dif_temperature">
|
||||
<property name="text">
|
||||
<string>DIF ?</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_menu_lateral_contribution">
|
||||
<action name="action_menu_lateral_contribution_temperature">
|
||||
<property name="text">
|
||||
<string>Lateral contributions ?</string>
|
||||
</property>
|
||||
|
|
|
|||
172
src/lang/fr.ts
172
src/lang/fr.ts
|
|
@ -1650,6 +1650,14 @@ Some profiles don't contain any point.</source>
|
|||
<translation>Conditions initiales AdisTS</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InitialConditionTemperature</name>
|
||||
<message>
|
||||
<location filename="../View/InitialConditionsTemperature/translate.py" line="30"/>
|
||||
<source>Initial condition temperature</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>LateralContribution</name>
|
||||
<message>
|
||||
|
|
@ -1884,7 +1892,7 @@ Some profiles don't contain any point.</source>
|
|||
<translation>&Fenêtres</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="351"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="362"/>
|
||||
<source>New study</source>
|
||||
<translation>Nouvelle étude</translation>
|
||||
</message>
|
||||
|
|
@ -1894,82 +1902,82 @@ Some profiles don't contain any point.</source>
|
|||
<translation>Ctrl+N</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="379"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="390"/>
|
||||
<source>Open a study</source>
|
||||
<translation>Ouvrir une étude</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="382"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="393"/>
|
||||
<source>Ctrl+O</source>
|
||||
<translation>Ctrl+O</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="391"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="402"/>
|
||||
<source>Close</source>
|
||||
<translation>Fermer</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="564"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="575"/>
|
||||
<source>Close current study</source>
|
||||
<translation>Fermer l'étude en cours</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="403"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="414"/>
|
||||
<source>Save</source>
|
||||
<translation>Sauvegarder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="406"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="417"/>
|
||||
<source>Save study</source>
|
||||
<translation>Sauvegarder l'étude</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="409"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="420"/>
|
||||
<source>Ctrl+S</source>
|
||||
<translation>Ctrl+S</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="418"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="429"/>
|
||||
<source>Save as ...</source>
|
||||
<translation>Sauvegarder sous ...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="421"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="432"/>
|
||||
<source>Save study as ...</source>
|
||||
<translation>Sauvegarder l'étude sous ...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="424"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="435"/>
|
||||
<source>Ctrl+Shift+S</source>
|
||||
<translation>Ctrl+Shift+S</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="429"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="440"/>
|
||||
<source>Pamhyr2 configuration</source>
|
||||
<translation>Configuration de Pamhyr2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="438"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="449"/>
|
||||
<source>Quit</source>
|
||||
<translation>Quitter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="441"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="452"/>
|
||||
<source>Quit application</source>
|
||||
<translation>Quitter l'application</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="444"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="455"/>
|
||||
<source>Ctrl+F4</source>
|
||||
<translation>Ctrl+F4</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="594"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="605"/>
|
||||
<source>Edit river network</source>
|
||||
<translation>Éditer le réseau</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="462"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="473"/>
|
||||
<source>Edit geometry</source>
|
||||
<translation>Éditer la géométrie</translation>
|
||||
</message>
|
||||
|
|
@ -1984,37 +1992,37 @@ Some profiles don't contain any point.</source>
|
|||
<translation>Exporter la géométrie</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="470"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="481"/>
|
||||
<source>Numerical parameters of solvers</source>
|
||||
<translation>Paramètres numériques des solveurs</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="738"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="749"/>
|
||||
<source>Boundary conditions and point sources</source>
|
||||
<translation>Conditions aux limites et apports ponctuels</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="666"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="827"/>
|
||||
<source>Initial conditions</source>
|
||||
<translation>Conditions initiales</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="645"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="656"/>
|
||||
<source>Edit friction</source>
|
||||
<translation>Éditer les frottements</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="633"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="644"/>
|
||||
<source>Edit lateral sources</source>
|
||||
<translation>Éditer les contributions latérales</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="579"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="590"/>
|
||||
<source>Run solver</source>
|
||||
<translation>Lancer le solveur</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="521"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="532"/>
|
||||
<source>F5</source>
|
||||
<translation>F5</translation>
|
||||
</message>
|
||||
|
|
@ -2024,137 +2032,137 @@ Some profiles don't contain any point.</source>
|
|||
<translation>Ouvrir</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="529"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="540"/>
|
||||
<source>Visualize last results</source>
|
||||
<translation>Visualisation des derniers résultats</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="532"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="543"/>
|
||||
<source>Visualize the last results</source>
|
||||
<translation>Visualisation des derniers résultats</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="540"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="551"/>
|
||||
<source>About</source>
|
||||
<translation>À propos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="549"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="560"/>
|
||||
<source>Save current study</source>
|
||||
<translation>Sauvegarder l'étude</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="552"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="563"/>
|
||||
<source>Save the study (Ctrl+S)</source>
|
||||
<translation>Sauvegarde de l'étude (Ctrl+S)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="567"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="578"/>
|
||||
<source>Close the study (Ctrl+F)</source>
|
||||
<translation>Fermeture de l'étude (Ctrl+F)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="570"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="581"/>
|
||||
<source>Ctrl+F</source>
|
||||
<translation>Ctrl+F</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="582"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="593"/>
|
||||
<source>Run a solver</source>
|
||||
<translation>Lancer un solveur</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="591"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="602"/>
|
||||
<source>River network</source>
|
||||
<translation>Réseau</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="603"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="614"/>
|
||||
<source>Geometry</source>
|
||||
<translation>Géometrie</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="606"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="617"/>
|
||||
<source>Edit reach geometry</source>
|
||||
<translation>Éditer la géométrie du bief actuel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="615"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="832"/>
|
||||
<source>Boundary conditions</source>
|
||||
<translation>Conditions aux limites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="618"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="629"/>
|
||||
<source>Edit boundary conditions and point sources</source>
|
||||
<translation>Éditer les conditions aux limites et les apports ponctuels</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="630"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="641"/>
|
||||
<source>Lateral sources</source>
|
||||
<translation>Contributions latérales</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="642"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="653"/>
|
||||
<source>Friction</source>
|
||||
<translation>Frottements</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="654"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="665"/>
|
||||
<source>Edit study</source>
|
||||
<translation>Éditer l'étude</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="669"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="680"/>
|
||||
<source>Define initial conditions</source>
|
||||
<translation>Définir les conditions initiales</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="674"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="685"/>
|
||||
<source>Sediment layers</source>
|
||||
<translation>Couches sédimentaires</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="677"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="688"/>
|
||||
<source>Define sediment layers</source>
|
||||
<translation>Définition des couches sédimentaires</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="682"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="693"/>
|
||||
<source>Edit reach sediment layers</source>
|
||||
<translation>Éditer les couches sédimentaires</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="687"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="698"/>
|
||||
<source>Mage</source>
|
||||
<translation>Mage</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="690"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="701"/>
|
||||
<source>Open Mage documentation</source>
|
||||
<translation>Ouvrir la documentation de Mage</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="695"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="706"/>
|
||||
<source>Users (wiki)</source>
|
||||
<translation>Utilisateurs (wiki)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="700"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="711"/>
|
||||
<source>Developers (pdf)</source>
|
||||
<translation>Développeurs (pdf)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="705"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="716"/>
|
||||
<source>Developers (html)</source>
|
||||
<translation>Développeurs (html)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="710"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="721"/>
|
||||
<source>Reservoirs</source>
|
||||
<translation>Casiers</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="713"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="724"/>
|
||||
<source>Edit reservoirs</source>
|
||||
<translation>Éditer les casiers</translation>
|
||||
</message>
|
||||
|
|
@ -2164,12 +2172,12 @@ Some profiles don't contain any point.</source>
|
|||
<translation>Ouvrages hydrauliques</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="721"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="732"/>
|
||||
<source>Edit hydraulic structures</source>
|
||||
<translation>Éditer les ouvrages hydrauliques</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="729"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="740"/>
|
||||
<source>Open results from file</source>
|
||||
<translation>Ouvrir des résultats depuis un fichier</translation>
|
||||
</message>
|
||||
|
|
@ -2504,22 +2512,22 @@ Some profiles don't contain any point.</source>
|
|||
<translation>Éditer les couches sédimentaires du profil</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/InitialConditions.ui" line="105"/>
|
||||
<location filename="../View/ui/InitialConditionsTemperature.ui" line="79"/>
|
||||
<source>Add new initial condition</source>
|
||||
<translation>Ajouter une nouvelle condition initiale</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/InitialConditions.ui" line="117"/>
|
||||
<location filename="../View/ui/InitialConditionsTemperature.ui" line="91"/>
|
||||
<source>Delete inital condition</source>
|
||||
<translation>Supprimer une condition initiale</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/InitialConditions.ui" line="126"/>
|
||||
<location filename="../View/ui/InitialConditionsTemperature.ui" line="100"/>
|
||||
<source>sort</source>
|
||||
<translation>sort</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/InitialConditions.ui" line="129"/>
|
||||
<location filename="../View/ui/InitialConditionsTemperature.ui" line="103"/>
|
||||
<source>Sort inital conditions</source>
|
||||
<translation>Trier les conditions initiales</translation>
|
||||
</message>
|
||||
|
|
@ -2614,12 +2622,12 @@ Some profiles don't contain any point.</source>
|
|||
<translation>&Avancé</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="743"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="754"/>
|
||||
<source>&Additional files</source>
|
||||
<translation>Fichiers &supplémentaires</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="748"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="759"/>
|
||||
<source>REP additional lines</source>
|
||||
<translation>Lignes REP supplémentaires</translation>
|
||||
</message>
|
||||
|
|
@ -2694,7 +2702,7 @@ Some profiles don't contain any point.</source>
|
|||
<translation>Éditer fichier</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="657"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="668"/>
|
||||
<source>Edit the study information</source>
|
||||
<translation>Éditer les informations de l'étude</translation>
|
||||
</message>
|
||||
|
|
@ -2704,12 +2712,12 @@ Some profiles don't contain any point.</source>
|
|||
<translation>toolBar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="321"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="332"/>
|
||||
<source>toolBar_2</source>
|
||||
<translation>toolBar_2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="500"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="511"/>
|
||||
<source>Edit frictions</source>
|
||||
<translation>Éditer les frottements</translation>
|
||||
</message>
|
||||
|
|
@ -2734,7 +2742,7 @@ Some profiles don't contain any point.</source>
|
|||
<translation>Retourner l'ordre des points</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/EditLateralContribution.ui" line="124"/>
|
||||
<location filename="../View/ui/InitialConditionsTemperature.ui" line="115"/>
|
||||
<source>Import from file</source>
|
||||
<translation>Importer depuis un fichier</translation>
|
||||
</message>
|
||||
|
|
@ -2899,32 +2907,32 @@ Some profiles don't contain any point.</source>
|
|||
<translation>AdisTS</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="758"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="769"/>
|
||||
<source>Output RK</source>
|
||||
<translation>Pk de sortie</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="767"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="778"/>
|
||||
<source>Run AdisTS</source>
|
||||
<translation>Lancer AdisTS</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="772"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="783"/>
|
||||
<source>Pollutants</source>
|
||||
<translation>Polluants</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="777"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="788"/>
|
||||
<source>D90</source>
|
||||
<translation>D90</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="782"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="793"/>
|
||||
<source>DIF</source>
|
||||
<translation>DIF</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="798"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="809"/>
|
||||
<source>Open results AdisTS</source>
|
||||
<translation>Ouvrir des résultats AdisTS</translation>
|
||||
</message>
|
||||
|
|
@ -3049,7 +3057,7 @@ Some profiles don't contain any point.</source>
|
|||
<translation>Non</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="806"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="817"/>
|
||||
<source>Compare results</source>
|
||||
<translation>Comparaison de résultats</translation>
|
||||
</message>
|
||||
|
|
@ -3204,12 +3212,12 @@ Some profiles don't contain any point.</source>
|
|||
<translation>Scénarios</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="753"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="764"/>
|
||||
<source>Edit scenarios tree</source>
|
||||
<translation>Editer l'arbre des scénarios</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="811"/>
|
||||
<location filename="../View/ui/MainWindow.ui" line="822"/>
|
||||
<source>GeoTIFF</source>
|
||||
<translation>GeoTIFF</translation>
|
||||
</message>
|
||||
|
|
@ -3248,6 +3256,26 @@ Some profiles don't contain any point.</source>
|
|||
<source>total_sediment.bin file not found</source>
|
||||
<translation type="unfinished">Fichier total_sediment.bin non trouvé</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="233"/>
|
||||
<source>Temperature</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="837"/>
|
||||
<source>Weather parameters</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="842"/>
|
||||
<source>DIF ?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/MainWindow.ui" line="847"/>
|
||||
<source>Lateral contributions ?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MainWindow_reach</name>
|
||||
|
|
|
|||
Loading…
Reference in New Issue