mirror of https://gitlab.com/pamhyr/pamhyr2
AdditionalFiles: Add model, view and solver export.
parent
db416d25de
commit
48e30125bb
|
|
@ -0,0 +1,148 @@
|
||||||
|
# AddFile.py -- Pamhyr
|
||||||
|
# Copyright (C) 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 functools import reduce
|
||||||
|
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrDB import SQLSubModel
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
|
||||||
|
class AddFile(SQLSubModel):
|
||||||
|
_sub_classes = []
|
||||||
|
_id_cnt = 0
|
||||||
|
|
||||||
|
def __init__(self, id: int = -1, enabled=True,
|
||||||
|
name="", path="", text="",
|
||||||
|
status=None):
|
||||||
|
super(AddFile, self).__init__()
|
||||||
|
|
||||||
|
if id == -1:
|
||||||
|
self.id = AddFile._id_cnt
|
||||||
|
else:
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
self._status = status
|
||||||
|
|
||||||
|
self._enabled = enabled
|
||||||
|
self._name = f"File {self.id}" if name == "" else name
|
||||||
|
self._path = path
|
||||||
|
self._text = text
|
||||||
|
|
||||||
|
AddFile._id_cnt = max(id, AddFile._id_cnt+1)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enabled(self):
|
||||||
|
return self._enabled
|
||||||
|
|
||||||
|
@enabled.setter
|
||||||
|
def enabled(self, enabled):
|
||||||
|
self._enabled = enabled
|
||||||
|
|
||||||
|
def is_enabled(self):
|
||||||
|
return self._enabled
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
def name(self, name):
|
||||||
|
self._name = name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def path(self):
|
||||||
|
return self._path
|
||||||
|
|
||||||
|
@path.setter
|
||||||
|
def path(self, path):
|
||||||
|
self._path = path
|
||||||
|
|
||||||
|
@property
|
||||||
|
def text(self):
|
||||||
|
return self._text
|
||||||
|
|
||||||
|
@text.setter
|
||||||
|
def text(self, text):
|
||||||
|
self._text = text
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute):
|
||||||
|
execute("""
|
||||||
|
CREATE TABLE additional_files(
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
enabled BOOLEAN NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
path TEXT NOT NULL,
|
||||||
|
text TEXT 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) < 8:
|
||||||
|
cls._db_create(execute)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
table = execute(
|
||||||
|
"SELECT id, enabled, name, path, text " +
|
||||||
|
"FROM additional_files"
|
||||||
|
)
|
||||||
|
|
||||||
|
for row in table:
|
||||||
|
it = iter(row)
|
||||||
|
|
||||||
|
id = next(it)
|
||||||
|
enabled = (next(it) == 1)
|
||||||
|
name = next(it)
|
||||||
|
path = next(it)
|
||||||
|
text = next(it)
|
||||||
|
|
||||||
|
f = cls(
|
||||||
|
id=id, enabled=enabled, name=name, path=path, text=text,
|
||||||
|
status=data['status']
|
||||||
|
)
|
||||||
|
|
||||||
|
new.append(f)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
sql = (
|
||||||
|
"INSERT INTO " +
|
||||||
|
"additional_files(id, enabled, name, path, text) " +
|
||||||
|
"VALUES (" +
|
||||||
|
f"{self.id}, {self._enabled}, " +
|
||||||
|
f"'{self._db_format(self._name)}', " +
|
||||||
|
f"'{self._db_format(self._path)}', " +
|
||||||
|
f"'{self._db_format(self._text)}'" +
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
execute(sql)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
# AddFileList.py -- Pamhyr
|
||||||
|
# Copyright (C) 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 tools import trace, timer
|
||||||
|
|
||||||
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
from Model.Tools.PamhyrList import PamhyrModelList
|
||||||
|
from Model.AdditionalFile.AddFile import AddFile
|
||||||
|
|
||||||
|
|
||||||
|
class AddFileList(PamhyrModelList):
|
||||||
|
_sub_classes = [AddFile]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = cls(status=data["status"])
|
||||||
|
|
||||||
|
new._lst = AddFile._db_load(execute, data)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
ok = True
|
||||||
|
|
||||||
|
# Delete previous data
|
||||||
|
execute("DELETE FROM additional_files")
|
||||||
|
|
||||||
|
for af in self._lst:
|
||||||
|
ok &= af._db_save(execute, data)
|
||||||
|
|
||||||
|
return ok
|
||||||
|
|
||||||
|
@property
|
||||||
|
def files(self):
|
||||||
|
return self.lst
|
||||||
|
|
||||||
|
def new(self, index):
|
||||||
|
n = AddFile(status=self._status)
|
||||||
|
self.insert(index, n)
|
||||||
|
self._status.modified()
|
||||||
|
return n
|
||||||
|
|
@ -40,6 +40,7 @@ from Model.Reservoir.ReservoirList import ReservoirList
|
||||||
from Model.HydraulicStructures.HydraulicStructuresList import (
|
from Model.HydraulicStructures.HydraulicStructuresList import (
|
||||||
HydraulicStructureList,
|
HydraulicStructureList,
|
||||||
)
|
)
|
||||||
|
from Model.AdditionalFile.AddFileList import AddFileList
|
||||||
|
|
||||||
from Solver.Solvers import solver_type_list
|
from Solver.Solvers import solver_type_list
|
||||||
|
|
||||||
|
|
@ -224,6 +225,7 @@ class River(Graph, SQLSubModel):
|
||||||
SedimentLayerList,
|
SedimentLayerList,
|
||||||
ReservoirList,
|
ReservoirList,
|
||||||
HydraulicStructureList,
|
HydraulicStructureList,
|
||||||
|
AddFileList,
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, status=None):
|
def __init__(self, status=None):
|
||||||
|
|
@ -245,6 +247,7 @@ class River(Graph, SQLSubModel):
|
||||||
self._hydraulic_structures = HydraulicStructureList(
|
self._hydraulic_structures = HydraulicStructureList(
|
||||||
status=self._status
|
status=self._status
|
||||||
)
|
)
|
||||||
|
self._additional_files = AddFileList(status=self._status)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_create(cls, execute):
|
def _db_create(cls, execute):
|
||||||
|
|
@ -263,64 +266,59 @@ class River(Graph, SQLSubModel):
|
||||||
# Stricklers (Stricklers is load in first because it's needed
|
# Stricklers (Stricklers is load in first because it's needed
|
||||||
# for reachs)
|
# for reachs)
|
||||||
new._stricklers = StricklersList._db_load(
|
new._stricklers = StricklersList._db_load(
|
||||||
execute,
|
execute, data
|
||||||
data
|
|
||||||
)
|
)
|
||||||
data["stricklers"] = new._stricklers
|
data["stricklers"] = new._stricklers
|
||||||
|
|
||||||
# Initial conditions
|
# Initial conditions
|
||||||
new._sediment_layers = SedimentLayerList._db_load(
|
new._sediment_layers = SedimentLayerList._db_load(
|
||||||
execute,
|
execute, data
|
||||||
data
|
|
||||||
)
|
)
|
||||||
data["sediment_layers_list"] = new._sediment_layers
|
data["sediment_layers_list"] = new._sediment_layers
|
||||||
|
|
||||||
# Network
|
# Network
|
||||||
new._nodes = RiverNode._db_load(
|
new._nodes = RiverNode._db_load(
|
||||||
execute,
|
execute, data
|
||||||
data
|
|
||||||
)
|
)
|
||||||
data["nodes"] = new.nodes()
|
data["nodes"] = new.nodes()
|
||||||
|
|
||||||
new._edges = RiverReach._db_load(
|
new._edges = RiverReach._db_load(
|
||||||
execute,
|
execute, data
|
||||||
data
|
|
||||||
)
|
)
|
||||||
data["edges"] = new.edges()
|
data["edges"] = new.edges()
|
||||||
|
|
||||||
# Boundary Condition
|
# Boundary Condition
|
||||||
new._boundary_condition = BoundaryConditionList._db_load(
|
new._boundary_condition = BoundaryConditionList._db_load(
|
||||||
execute,
|
execute, data
|
||||||
data
|
|
||||||
)
|
)
|
||||||
# Lateral Contribution
|
# Lateral Contribution
|
||||||
new._lateral_contribution = LateralContributionList._db_load(
|
new._lateral_contribution = LateralContributionList._db_load(
|
||||||
execute,
|
execute, data
|
||||||
data
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Initial conditions
|
# Initial conditions
|
||||||
new._initial_conditions = InitialConditionsDict._db_load(
|
new._initial_conditions = InitialConditionsDict._db_load(
|
||||||
execute,
|
execute, data
|
||||||
data
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Reservoir
|
# Reservoir
|
||||||
new._reservoir = ReservoirList._db_load(
|
new._reservoir = ReservoirList._db_load(
|
||||||
execute,
|
execute, data
|
||||||
data
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Hydraulic Structures
|
# Hydraulic Structures
|
||||||
new._hydraulic_structures = HydraulicStructureList._db_load(
|
new._hydraulic_structures = HydraulicStructureList._db_load(
|
||||||
execute,
|
execute, data
|
||||||
data
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Parameters
|
# Parameters
|
||||||
new._parameters = SolverParametersList._db_load(
|
new._parameters = SolverParametersList._db_load(
|
||||||
execute,
|
execute, data
|
||||||
data
|
)
|
||||||
|
|
||||||
|
# Additional Files
|
||||||
|
new._additional_files = AddFileList._db_load(
|
||||||
|
execute, data
|
||||||
)
|
)
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
@ -336,6 +334,7 @@ class River(Graph, SQLSubModel):
|
||||||
objs.append(self._stricklers)
|
objs.append(self._stricklers)
|
||||||
objs.append(self._reservoir)
|
objs.append(self._reservoir)
|
||||||
objs.append(self._hydraulic_structures)
|
objs.append(self._hydraulic_structures)
|
||||||
|
objs.append(self._additional_files)
|
||||||
|
|
||||||
for solver in self._parameters:
|
for solver in self._parameters:
|
||||||
objs.append(self._parameters[solver])
|
objs.append(self._parameters[solver])
|
||||||
|
|
@ -373,11 +372,27 @@ class River(Graph, SQLSubModel):
|
||||||
logger_exception(e)
|
logger_exception(e)
|
||||||
|
|
||||||
def init_default(self):
|
def init_default(self):
|
||||||
|
self.init_default_network()
|
||||||
|
self.init_default_additional_files()
|
||||||
|
|
||||||
|
def init_default_network(self):
|
||||||
n1 = self.add_node(880.0, 950.0)
|
n1 = self.add_node(880.0, 950.0)
|
||||||
n2 = self.add_node(1120.0, 1020.0)
|
n2 = self.add_node(1120.0, 1020.0)
|
||||||
|
|
||||||
e = self.add_edge(n1, n2)
|
e = self.add_edge(n1, n2)
|
||||||
|
|
||||||
|
def init_default_additional_files(self):
|
||||||
|
add_file = self._additional_files.new(0)
|
||||||
|
add_file.name = "Pamhyr2 stamp file"
|
||||||
|
add_file.path = "Pamhyr2.txt"
|
||||||
|
add_file.text = """This repository has been generated by Pamhyr2 \
|
||||||
|
version "@version" !
|
||||||
|
|
||||||
|
All hand made file modification could be erased by the next solver
|
||||||
|
execution...
|
||||||
|
|
||||||
|
Last export at: @date."""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def boundary_condition(self):
|
def boundary_condition(self):
|
||||||
return self._boundary_condition
|
return self._boundary_condition
|
||||||
|
|
@ -419,6 +434,10 @@ class River(Graph, SQLSubModel):
|
||||||
def hydraulic_structures(self):
|
def hydraulic_structures(self):
|
||||||
return self._hydraulic_structures
|
return self._hydraulic_structures
|
||||||
|
|
||||||
|
@property
|
||||||
|
def additional_files(self):
|
||||||
|
return self._additional_files
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def parameters(self):
|
def parameters(self):
|
||||||
return self._parameters
|
return self._parameters
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ class Study(SQLModel):
|
||||||
|
|
||||||
def __init__(self, filename=None, init_new=True):
|
def __init__(self, filename=None, init_new=True):
|
||||||
# Metadata
|
# Metadata
|
||||||
self._version = "0.0.7"
|
self._version = "0.0.8"
|
||||||
self.creation_date = datetime.now()
|
self.creation_date = datetime.now()
|
||||||
self.last_modification_date = datetime.now()
|
self.last_modification_date = datetime.now()
|
||||||
self.last_save_date = datetime.now()
|
self.last_save_date = datetime.now()
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ class Modules(Flag):
|
||||||
HYDRAULIC_STRUCTURES = auto()
|
HYDRAULIC_STRUCTURES = auto()
|
||||||
RESERVOIR = auto()
|
RESERVOIR = auto()
|
||||||
SEDIMENT_LAYER = auto()
|
SEDIMENT_LAYER = auto()
|
||||||
|
ADDITIONAL_FILES = auto()
|
||||||
|
|
||||||
# Results
|
# Results
|
||||||
RESULTS = auto()
|
RESULTS = auto()
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from tools import timer, parse_command_line
|
from datetime import datetime
|
||||||
|
from tools import timer, parse_command_line, get_version
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Installation allow Unix-like signal
|
# Installation allow Unix-like signal
|
||||||
|
|
@ -124,6 +125,39 @@ class CommandLineSolver(AbstractSolver):
|
||||||
"""
|
"""
|
||||||
raise NotImplementedMethodeError(self, self.log_file)
|
raise NotImplementedMethodeError(self, self.log_file)
|
||||||
|
|
||||||
|
def export_additional_files(self, study, repertory, qlog, name="0"):
|
||||||
|
files = []
|
||||||
|
|
||||||
|
if qlog is not None:
|
||||||
|
qlog.put("Export additional files")
|
||||||
|
|
||||||
|
files = study.river.additional_files.files
|
||||||
|
for add_file in files:
|
||||||
|
self.export_additional_file(
|
||||||
|
add_file, repertory, files
|
||||||
|
)
|
||||||
|
|
||||||
|
def export_additional_file(self, add_file, repertory, files):
|
||||||
|
if add_file.path == "" or not add_file.is_enabled():
|
||||||
|
return files
|
||||||
|
|
||||||
|
path = os.path.join(repertory, add_file.path)
|
||||||
|
os.makedirs(
|
||||||
|
os.path.dirname(path),
|
||||||
|
exist_ok=True
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(path, "w+") as f:
|
||||||
|
files.append(add_file.path)
|
||||||
|
|
||||||
|
txt = add_file.text
|
||||||
|
txt = txt.replace("@version", get_version())
|
||||||
|
txt = txt.replace("@date", datetime.now().isoformat(sep=" "))
|
||||||
|
|
||||||
|
f.write(txt)
|
||||||
|
|
||||||
|
return files
|
||||||
|
|
||||||
#######
|
#######
|
||||||
# Run #
|
# Run #
|
||||||
#######
|
#######
|
||||||
|
|
|
||||||
|
|
@ -671,6 +671,7 @@ class Mage(CommandLineSolver):
|
||||||
self._bin_file = f"{name}.BIN"
|
self._bin_file = f"{name}.BIN"
|
||||||
|
|
||||||
self._export_ST(study, repertory, qlog, name=name)
|
self._export_ST(study, repertory, qlog, name=name)
|
||||||
|
self.export_additional_files(study, repertory, qlog, name=name)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
@ -886,6 +887,10 @@ class Mage8(Mage):
|
||||||
files = files + self._export_VAR(study, repertory, qlog, name=name)
|
files = files + self._export_VAR(study, repertory, qlog, name=name)
|
||||||
files = files + self._export_CAS(study, repertory, qlog, name=name)
|
files = files + self._export_CAS(study, repertory, qlog, name=name)
|
||||||
files = files + self._export_DEV(study, repertory, qlog, name=name)
|
files = files + self._export_DEV(study, repertory, qlog, name=name)
|
||||||
|
files = files + self.export_additional_files(
|
||||||
|
study, repertory, qlog, name=name
|
||||||
|
)
|
||||||
|
|
||||||
self._export_REP(study, repertory, files, qlog, name=name)
|
self._export_REP(study, repertory, files, qlog, name=name)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
# Window.py -- Pamhyr
|
||||||
|
# Copyright (C) 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 Modules import Modules
|
||||||
|
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QLabel, QPlainTextEdit, QPushButton,
|
||||||
|
QCheckBox,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.AdditionalFiles.Translate import AddFileTranslate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class EditAddFileWindow(PamhyrWindow):
|
||||||
|
_pamhyr_ui = "AdditionalFile"
|
||||||
|
_pamhyr_name = "Edit additional file"
|
||||||
|
|
||||||
|
def __init__(self, study=None, config=None, add_file=None,
|
||||||
|
trad=None, parent=None):
|
||||||
|
|
||||||
|
name = trad[self._pamhyr_name] + " - " + study.name
|
||||||
|
super(EditAddFileWindow, self).__init__(
|
||||||
|
title=name,
|
||||||
|
study=study,
|
||||||
|
config=config,
|
||||||
|
options=[],
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._add_file = add_file
|
||||||
|
self._hash_data.append(self._add_file)
|
||||||
|
|
||||||
|
self.setup_values()
|
||||||
|
self.setup_connection()
|
||||||
|
|
||||||
|
def setup_values(self):
|
||||||
|
self.set_check_box("checkBox", self._add_file.enabled)
|
||||||
|
self.set_line_edit_text("lineEdit_name", self._add_file.name)
|
||||||
|
self.set_line_edit_text("lineEdit_path", self._add_file.path)
|
||||||
|
self.set_plaintext_edit_text("plainTextEdit", self._add_file.text)
|
||||||
|
|
||||||
|
def setup_connection(self):
|
||||||
|
self.find(QPushButton, "pushButton_cancel")\
|
||||||
|
.clicked.connect(self.close)
|
||||||
|
self.find(QPushButton, "pushButton_ok")\
|
||||||
|
.clicked.connect(self.accept)
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
is_enabled = self.get_check_box("checkBox")
|
||||||
|
name = self.get_line_edit_text("lineEdit_name")
|
||||||
|
path = self.get_line_edit_text("lineEdit_path")
|
||||||
|
text = self.get_plaintext_edit_text("plainTextEdit")
|
||||||
|
|
||||||
|
self._add_file.enabled = is_enabled
|
||||||
|
self._add_file.name = name
|
||||||
|
self._add_file.path = path
|
||||||
|
self._add_file.text = text
|
||||||
|
|
||||||
|
self._propagate_update(key=Modules.ADDITIONAL_FILES)
|
||||||
|
self.close()
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
# List.py -- Pamhyr
|
||||||
|
# Copyright (C) 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
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtGui import (
|
||||||
|
QColor, QBrush,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.PamhyrList import PamhyrListModel
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class ListModel(PamhyrListModel):
|
||||||
|
def data(self, index, role):
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
file = self._data.files[row]
|
||||||
|
|
||||||
|
if role == Qt.ForegroundRole:
|
||||||
|
color = Qt.gray
|
||||||
|
|
||||||
|
if file.is_enabled():
|
||||||
|
color = QColor("black")
|
||||||
|
else:
|
||||||
|
color = QColor("grey")
|
||||||
|
|
||||||
|
return QBrush(color)
|
||||||
|
|
||||||
|
if role == Qt.ItemDataRole.DisplayRole:
|
||||||
|
text = f"{file.name}: '{file.path}'"
|
||||||
|
|
||||||
|
if not file.is_enabled():
|
||||||
|
text += " (disabled)"
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
def add(self, row):
|
||||||
|
self._data.new(row)
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def delete(self, rows):
|
||||||
|
logger.info(f"add_files: delete {rows}")
|
||||||
|
self._data.delete_i(rows)
|
||||||
|
self.update()
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Translate.py -- Pamhyr
|
||||||
|
# Copyright (C) 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 AddFileTranslate(MainTranslate):
|
||||||
|
def __init__(self):
|
||||||
|
super(AddFileTranslate, self).__init__()
|
||||||
|
|
||||||
|
self._dict["Additional files"] = _translate(
|
||||||
|
"AdditionalFiles", "Additional files"
|
||||||
|
)
|
||||||
|
|
||||||
|
self._dict["Edit additional file"] = _translate(
|
||||||
|
"AdditionalFiles", "Edit additional file"
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
# Window.py -- Pamhyr
|
||||||
|
# Copyright (C) 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 tools import trace, timer
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QAction, QListView,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||||
|
|
||||||
|
from View.AdditionalFiles.List import ListModel
|
||||||
|
from View.AdditionalFiles.Translate import AddFileTranslate
|
||||||
|
from View.AdditionalFiles.Edit.Window import EditAddFileWindow
|
||||||
|
|
||||||
|
|
||||||
|
class AddFileListWindow(PamhyrWindow):
|
||||||
|
_pamhyr_ui = "AdditionalFileList"
|
||||||
|
_pamhyr_name = "Additional files"
|
||||||
|
|
||||||
|
def __init__(self, study=None, config=None,
|
||||||
|
parent=None):
|
||||||
|
trad = AddFileTranslate()
|
||||||
|
name = trad[self._pamhyr_name] + " - " + study.name
|
||||||
|
|
||||||
|
super(AddFileListWindow, self).__init__(
|
||||||
|
title=name,
|
||||||
|
study=study,
|
||||||
|
config=config,
|
||||||
|
trad=trad,
|
||||||
|
options=[],
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self.setup_list()
|
||||||
|
self.setup_connections()
|
||||||
|
|
||||||
|
def setup_list(self):
|
||||||
|
lst = self.find(QListView, f"listView")
|
||||||
|
self._list = ListModel(
|
||||||
|
list_view=lst,
|
||||||
|
data=self._study.river.additional_files,
|
||||||
|
)
|
||||||
|
|
||||||
|
def setup_connections(self):
|
||||||
|
self.find(QAction, "action_add").triggered.connect(self.add)
|
||||||
|
self.find(QAction, "action_delete").triggered.connect(self.delete)
|
||||||
|
self.find(QAction, "action_edit").triggered.connect(self.edit)
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
self._list.update()
|
||||||
|
|
||||||
|
def selected_rows(self):
|
||||||
|
lst = self.find(QListView, f"listView")
|
||||||
|
return list(map(lambda i: i.row(), lst.selectedIndexes()))
|
||||||
|
|
||||||
|
def add(self):
|
||||||
|
rows = self.selected_rows()
|
||||||
|
if len(rows) > 0:
|
||||||
|
row = rows[0]
|
||||||
|
else:
|
||||||
|
row = 0
|
||||||
|
|
||||||
|
self._list.add(row)
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
rows = self.selected_rows()
|
||||||
|
self._list.delete(rows)
|
||||||
|
|
||||||
|
def edit(self):
|
||||||
|
rows = self.selected_rows()
|
||||||
|
|
||||||
|
for row in rows:
|
||||||
|
add_file = self._study.river.additional_files.files[row]
|
||||||
|
|
||||||
|
if self.sub_window_exists(
|
||||||
|
EditAddFileWindow,
|
||||||
|
data=[self._study, self._config, add_file]
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
|
||||||
|
win = EditAddFileWindow(
|
||||||
|
study=self._study,
|
||||||
|
config=self._config,
|
||||||
|
add_file=add_file,
|
||||||
|
trad=self._trad,
|
||||||
|
parent=self,
|
||||||
|
)
|
||||||
|
win.show()
|
||||||
|
|
@ -67,6 +67,7 @@ from View.Stricklers.Window import StricklersWindow
|
||||||
from View.Frictions.Window import FrictionsWindow
|
from View.Frictions.Window import FrictionsWindow
|
||||||
from View.SedimentLayers.Window import SedimentLayersWindow
|
from View.SedimentLayers.Window import SedimentLayersWindow
|
||||||
from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow
|
from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow
|
||||||
|
from View.AdditionalFiles.Window import AddFileListWindow
|
||||||
from View.SolverParameters.Window import SolverParametersWindow
|
from View.SolverParameters.Window import SolverParametersWindow
|
||||||
from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow
|
from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow
|
||||||
from View.CheckList.Window import CheckListWindow
|
from View.CheckList.Window import CheckListWindow
|
||||||
|
|
@ -117,7 +118,7 @@ define_model_action = [
|
||||||
"action_menu_edit_friction", "action_menu_edit_lateral_contribution",
|
"action_menu_edit_friction", "action_menu_edit_lateral_contribution",
|
||||||
"action_menu_run_solver", "action_menu_sediment_layers",
|
"action_menu_run_solver", "action_menu_sediment_layers",
|
||||||
"action_menu_edit_reach_sediment_layers", "action_menu_edit_reservoirs",
|
"action_menu_edit_reach_sediment_layers", "action_menu_edit_reservoirs",
|
||||||
"action_menu_edit_hydraulic_structures",
|
"action_menu_edit_hydraulic_structures", "action_menu_additional_file",
|
||||||
"action_menu_results_last", "action_open_results_from_file",
|
"action_menu_results_last", "action_open_results_from_file",
|
||||||
"action_menu_boundary_conditions_sediment",
|
"action_menu_boundary_conditions_sediment",
|
||||||
]
|
]
|
||||||
|
|
@ -252,6 +253,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
"action_menu_sediment_layers": self.open_sediment_layers,
|
"action_menu_sediment_layers": self.open_sediment_layers,
|
||||||
"action_menu_edit_reach_sediment_layers":
|
"action_menu_edit_reach_sediment_layers":
|
||||||
self.open_reach_sediment_layers,
|
self.open_reach_sediment_layers,
|
||||||
|
"action_menu_additional_file": self.open_additional_files,
|
||||||
"action_menu_close": self.close_model,
|
"action_menu_close": self.close_model,
|
||||||
"action_menu_results_last": self.open_last_results,
|
"action_menu_results_last": self.open_last_results,
|
||||||
"action_open_results_from_file": self.open_results_from_file,
|
"action_open_results_from_file": self.open_results_from_file,
|
||||||
|
|
@ -1063,6 +1065,19 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
else:
|
else:
|
||||||
self.msg_select_reach()
|
self.msg_select_reach()
|
||||||
|
|
||||||
|
def open_additional_files(self):
|
||||||
|
if self._study is not None:
|
||||||
|
if self.sub_window_exists(
|
||||||
|
AddFileListWindow,
|
||||||
|
data=[self._study, None]
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
self.additonal_files = AddFileListWindow(
|
||||||
|
study=self._study, parent=self
|
||||||
|
)
|
||||||
|
self.additonal_files.show()
|
||||||
|
|
||||||
def open_solver_parameters(self):
|
def open_solver_parameters(self):
|
||||||
if self.sub_window_exists(
|
if self.sub_window_exists(
|
||||||
SolverParametersWindow,
|
SolverParametersWindow,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
<?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>896</width>
|
||||||
|
<height>504</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>MainWindow</string>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="English" country="Europe"/>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<item row="2" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButton_cancel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Cancel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButton_ok">
|
||||||
|
<property name="text">
|
||||||
|
<string>Ok</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" colspan="2">
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="title">
|
||||||
|
<string>File text</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QPlainTextEdit" name="plainTextEdit"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" colspan="2">
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Information</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QCheckBox" name="checkBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Enabled</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_path">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>The relative file path on executable directory</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_name"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Name</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Path</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?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>896</width>
|
||||||
|
<height>504</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="QListView" name="listView"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<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_delete"/>
|
||||||
|
<addaction name="action_edit"/>
|
||||||
|
</widget>
|
||||||
|
<action name="action_add">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/gtk-add.png</normaloff>ressources/gtk-add.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Add</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Add a new file</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_delete">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/gtk-remove.png</normaloff>ressources/gtk-remove.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Delete</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Delete selected file(s)</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_edit">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>ressources/edit.png</normaloff>ressources/edit.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Edit</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Edit file</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
|
|
@ -204,11 +204,18 @@
|
||||||
<string>&Windows</string>
|
<string>&Windows</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QMenu" name="menu_Avensed">
|
||||||
|
<property name="title">
|
||||||
|
<string>&Advansed</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="action_menu_additional_file"/>
|
||||||
|
</widget>
|
||||||
<addaction name="menu_File"/>
|
<addaction name="menu_File"/>
|
||||||
<addaction name="menu_network"/>
|
<addaction name="menu_network"/>
|
||||||
<addaction name="menu_geometry"/>
|
<addaction name="menu_geometry"/>
|
||||||
<addaction name="menu_Hydraulics"/>
|
<addaction name="menu_Hydraulics"/>
|
||||||
<addaction name="menuSediment"/>
|
<addaction name="menuSediment"/>
|
||||||
|
<addaction name="menu_Avensed"/>
|
||||||
<addaction name="menu_run"/>
|
<addaction name="menu_run"/>
|
||||||
<addaction name="menu_results"/>
|
<addaction name="menu_results"/>
|
||||||
<addaction name="menu_cartography"/>
|
<addaction name="menu_cartography"/>
|
||||||
|
|
@ -988,6 +995,11 @@
|
||||||
<string>Boundary conditions and punctual contributions</string>
|
<string>Boundary conditions and punctual contributions</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="action_menu_additional_file">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Additional file</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
|
|
|
||||||
10
src/tools.py
10
src/tools.py
|
|
@ -279,10 +279,20 @@ def get_user_name():
|
||||||
return "Me"
|
return "Me"
|
||||||
|
|
||||||
|
|
||||||
|
def get_version():
|
||||||
|
with open(os.path.abspath(
|
||||||
|
os.path.join(
|
||||||
|
os.path.dirname(__file__),
|
||||||
|
"VERSION"
|
||||||
|
)
|
||||||
|
), "r") as f:
|
||||||
|
return f.readline().strip()
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# COMMAND LINE PARSER #
|
# COMMAND LINE PARSER #
|
||||||
#######################
|
#######################
|
||||||
|
|
||||||
|
|
||||||
parser_special_char = ["\"", "\'"]
|
parser_special_char = ["\"", "\'"]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue