Merge branch 'master' into scenarios.

test_sound
Pierre-Antoine Rouby 2024-09-24 15:54:10 +02:00
commit 40d90424a3
44 changed files with 1445 additions and 562 deletions

View File

@ -381,8 +381,6 @@ class MeshingWithMageMailleurTT(AMeshingTool):
st_file = self.export_reach_to_st(reach, tmp) st_file = self.export_reach_to_st(reach, tmp)
m_file = st_file.rsplit(".ST", 1)[0] + ".M" m_file = st_file.rsplit(".ST", 1)[0] + ".M"
os.sync()
proc = QProcess() proc = QProcess()
proc.setWorkingDirectory(tmp) proc.setWorkingDirectory(tmp)
@ -397,12 +395,13 @@ class MeshingWithMageMailleurTT(AMeshingTool):
logger.info( logger.info(
f"! {self._exe_path()} " + f"! {self._exe_path()} " +
f"{st_file} {m_file} " + f"{st_file} {m_file} " +
f"update_rk " + f"update_kp " +
f"{str(step)} " + f"{str(step)} " +
f"{limites[0]} {limites[1]} " + f"{limites[0]} {limites[1]} " +
f"{directrices[0]} {directrices[1]} " + f"{directrices[0]} {directrices[1]} " +
f"{orientation} {lm} {linear} " + f"{orientation} {lm} {linear} " +
f"{origin} " f"{origin} " +
f"{origin_value} "
) )
proc.start( proc.start(
self._exe_path(), self._exe_path(),

View File

@ -21,6 +21,7 @@ import logging
from copy import copy, deepcopy from copy import copy, deepcopy
from tools import trace, timer from tools import trace, timer
from functools import reduce from functools import reduce
from numpy import interp
from Model.Tools.PamhyrDB import SQLSubModel from Model.Tools.PamhyrDB import SQLSubModel
from Model.Scenario import Scenario from Model.Scenario import Scenario
@ -485,8 +486,23 @@ class InitialConditions(SQLSubModel):
def get_discharge(self): def get_discharge(self):
return self._data_get("discharge") return self._data_get("discharge")
def generate_growing_constante_height(self, height: float, def _sort_by_z_and_rk(self, profiles):
compute_discharge: bool): profiles.sort(
reverse=False,
key=lambda p: p.rk
)
first_z = profiles[0].z()
last_z = profiles[-1].z()
if first_z > last_z:
profiles.sort(
reverse=True,
key=lambda p: p.rk
)
def generate_growing_constant_depth(self, height: float,
compute_discharge: bool):
profiles = self._reach.reach.profiles.copy() profiles = self._reach.reach.profiles.copy()
previous_elevation = -99999.99 previous_elevation = -99999.99

View File

@ -41,9 +41,9 @@ class Edge(SQLSubModel):
elif name == "id": elif name == "id":
ret = self.pamhyr_id ret = self.pamhyr_id
elif name == "node1": elif name == "node1":
ret = self.node1.name ret = self.node1
elif name == "node2": elif name == "node2":
ret = self.node2.name ret = self.node2
elif name == "enable": elif name == "enable":
ret = self._enable ret = self._enable
@ -69,10 +69,7 @@ class Edge(SQLSubModel):
@property @property
def name(self): def name(self):
name = self._name return self._name
if self._name == "":
name = f"{self.node1.name} -> {self.node2.name}"
return name
def is_enable(self): def is_enable(self):
return self._enable return self._enable

View File

@ -26,11 +26,7 @@ class Node(SQLSubModel):
**kwargs): **kwargs):
super(Node, self).__init__(id=id, **kwargs) super(Node, self).__init__(id=id, **kwargs)
if name == "": self._name = name
self._name = f"Node #{self.pamhyr_id}"
else:
self._name = name
self.pos = Point(x, y) self.pos = Point(x, y)
def __getitem__(self, key): def __getitem__(self, key):

View File

@ -73,7 +73,7 @@ class PamhyrModelDict(SQLSubModel):
if key in self._dict: if key in self._dict:
v = self._dict[key] v = self._dict[key]
if type(v) is types.GeneratorType: if isinstance(v, types.GeneratorType):
return list(v) return list(v)
return v return v

View File

@ -30,13 +30,13 @@ from Model.Results.River.River import River, Reach, Profile
logger = logging.getLogger() logger = logging.getLogger()
class RubarBE(CommandLineSolver): class Rubar3(CommandLineSolver):
_type = "rubarbe" _type = "rubar3"
def __init__(self, name): def __init__(self, name):
super(RubarBE, self).__init__(name) super(Rubar3, self).__init__(name)
self._type = "rubarbe" self._type = "rubar3"
self._cmd_input = "" self._cmd_input = ""
self._cmd_solver = "@path @input -o @output" self._cmd_solver = "@path @input -o @output"
@ -44,9 +44,9 @@ class RubarBE(CommandLineSolver):
@classmethod @classmethod
def default_parameters(cls): def default_parameters(cls):
lst = super(RubarBE, cls).default_parameters() # lst = super(Rubar3, cls).default_parameters()
lst += [ lst = [
("rubarbe_cfl", "0.50000E+00"), ("rubarbe_cfl", "0.50000E+00"),
("rubarbe_condam", "1"), ("rubarbe_condam", "1"),
("rubarbe_condav", "3"), ("rubarbe_condav", "3"),
@ -60,10 +60,10 @@ class RubarBE(CommandLineSolver):
("rubarbe_tinit", "000:00:00:00"), ("rubarbe_tinit", "000:00:00:00"),
("rubarbe_tmax", "999:99:99:00"), ("rubarbe_tmax", "999:99:99:00"),
("rubarbe_tiopdt", "000:00:00:00"), ("rubarbe_tiopdt", "000:00:00:00"),
("rubarbe_dt", "3000.0"), ("rubarbe_dt", "5.0"),
("rubarbe_ts", "999:99:99:00"), ("rubarbe_ts", "999:99:99:00"),
("rubarbe_dtsauv", "999:99:99:00"), ("rubarbe_dtsauv", "00:00:00:05"),
("rubarbe_psave", "999:99:99:00"), ("rubarbe_psave", "00:00:00:05"),
("rubarbe_fdeb1", "1"), ("rubarbe_fdeb1", "1"),
("rubarbe_fdeb2", "10"), ("rubarbe_fdeb2", "10"),
("rubarbe_fdeb3", "100"), ("rubarbe_fdeb3", "100"),
@ -119,21 +119,21 @@ class RubarBE(CommandLineSolver):
########## ##########
def cmd_args(self, study): def cmd_args(self, study):
lst = super(RubarBE, self).cmd_args(study) lst = super(Rubar3, self).cmd_args(study)
return lst return lst
def input_param(self): def input_param(self):
name = self._study.name name = self._study.name
return f"{name}.REP" return f"{name}"
def output_param(self): def output_param(self):
name = self._study.name name = self._study.name
return f"{name}.BIN" return f"{name}"
def log_file(self): def log_file(self):
name = self._study.name name = self._study.name
return f"{name}.TRA" return f"{name}"
def export(self, study, repertory, qlog=None): def export(self, study, repertory, qlog=None):
self._study = study self._study = study
@ -143,8 +143,12 @@ class RubarBE(CommandLineSolver):
self._export_ts(study, repertory, qlog, name=name) self._export_ts(study, repertory, qlog, name=name)
self._export_geomac_i(study, repertory, qlog, name=name) self._export_geomac_i(study, repertory, qlog, name=name)
self._export_mail(study, repertory, qlog, name=name) self._export_mail(study, repertory, qlog, name=name)
self._export_tps(study, repertory, qlog, name=name) self._export_condin(study, repertory, qlog, name=name)
self._export_stricklers(study, repertory, qlog, name=name) self._export_stricklers(study, repertory, qlog, name=name)
self._export_hydro(study, repertory, qlog, name=name)
self._export_condav(study, repertory, qlog, name=name)
return True
def _export_donnee(self, study, repertory, qlog, name="0"): def _export_donnee(self, study, repertory, qlog, name="0"):
if qlog is not None: if qlog is not None:
@ -168,6 +172,9 @@ class RubarBE(CommandLineSolver):
name = param.name name = param.name
value = param.value value = param.value
if "all_" in name:
continue
if value != "": if value != "":
# Value format # Value format
if value.count(':') == 3: if value.count(':') == 3:
@ -276,7 +283,9 @@ class RubarBE(CommandLineSolver):
if label[0] == "r": if label[0] == "r":
label = label[1].upper() label = label[1].upper()
else: else:
label = lable[0] label = label[1].upper()
else:
label = " "
y = point.y y = point.y
z = point.z z = point.z
@ -361,13 +370,13 @@ class RubarBE(CommandLineSolver):
ind += 1 ind += 1
f.write("\n") f.write("\n")
def _export_tps(self, study, repertory, qlog, name="0"): def _export_condin(self, study, repertory, qlog, name="0"):
if qlog is not None: if qlog is not None:
qlog.put("Export TPS file") qlog.put("Export CONDIN file")
with open( with open(
os.path.join( os.path.join(
repertory, f"tps.{name}" repertory, f"condin.{name}"
), "w+" ), "w+"
) as f: ) as f:
for edge in study.river.enable_edges(): for edge in study.river.enable_edges():
@ -376,7 +385,7 @@ class RubarBE(CommandLineSolver):
f.write(f"0.0\n") f.write(f"0.0\n")
ics = study.river.initial_conditions.get(edge) ics = study.river.initial_conditions.get(edge)
data = self._export_tps_init_data(ics) data = self._export_condin_init_data(ics)
profiles = reach.profiles profiles = reach.profiles
first = profiles[0] first = profiles[0]
@ -388,11 +397,11 @@ class RubarBE(CommandLineSolver):
) )
return return
f_h_s = self._export_tps_profile_height_speed(first, data) f_h_s = self._export_condin_profile_height_speed(first, data)
l_h_s = self._export_tps_profile_height_speed(last, data) l_h_s = self._export_condin_profile_height_speed(last, data)
# First mail # First mail
f.write(f"{1:>5} {f_h_s[0]} {f_h_s[1]}") f.write(f"{1:>5} {f_h_s[0]} {f_h_s[1]}\n")
ind = 2 ind = 2
it = iter(profiles) it = iter(profiles)
@ -404,7 +413,7 @@ class RubarBE(CommandLineSolver):
ind += 1 ind += 1
continue continue
cur_h, cur_s = self._export_tps_profile_height_speed( cur_h, cur_s = self._export_condin_profile_height_speed(
profile, data profile, data
) )
@ -418,9 +427,9 @@ class RubarBE(CommandLineSolver):
ind += 1 ind += 1
# Last mail # Last mail
f.write(f"{ind:>5} {f_h_s[0]} {f_h_s[1]}") f.write(f"{ind:>5} {f_h_s[0]} {f_h_s[1]}\n")
def _export_tps_init_data(self, ics): def _export_condin_init_data(self, ics):
data = {} data = {}
for d in ics.data: for d in ics.data:
@ -431,11 +440,70 @@ class RubarBE(CommandLineSolver):
return data return data
def _export_tps_profile_height_speed(self, profile, data): def _export_condin_profile_height_speed(self, profile, data):
z = data[profile.rk][0] z = data[profile.rk][0]
q = data[profile.rk][1] q = data[profile.rk][1]
height = z - profile.z_min() # height = z - profile.z_min()
speed = profile.speed(q, z) speed = profile.speed(q, z)
return height, speed return z, speed
def _export_hydro(self, study, repertory, qlog, name="0"):
if qlog is not None:
qlog.put("Export HYDRO file")
with open(
os.path.join(
repertory, f"hydro.{name}"
), "w+"
) as f:
bcs = []
for edge in study.river.enable_edges():
for bound in study.river.boundary_condition.get_tab("liquid"):
# BC is an hydrogramme
if bound.bctype == "TD" or bound.bctype == "PC":
# BC is on input node of this reach
if bound.node == edge.node1:
bcs.append(bound)
for bc in bcs:
f.write(f"{len(bc)}\n")
for d0, d1 in bc.data:
f.write(f"{d0} {d1}\n")
def _export_condav(self, study, repertory, qlog, name="0"):
if qlog is not None:
qlog.put("Export CONDAV file")
with open(
os.path.join(
repertory, f"condav.{name}"
), "w+"
) as f:
bcs = []
for edge in study.river.enable_edges():
for bound in study.river.boundary_condition.get_tab("liquid"):
# BC is an hydrogramme
if bound.bctype == "ZD" or bound.bctype == "TZ":
# BC is on input node of this reach
if bound.node == edge.node2:
bcs.append(bound)
for bc in bcs:
f.write(f"{len(bc)}\n")
for d0, d1 in bc.data:
f.write(f"{d0} {d1}\n")
class RubarBE(Rubar3):
_type = "rubarbe"
def __init__(self, name):
super(RubarBE, self).__init__(name)
self._type = "rubarbe"
self._cmd_input = ""
self._cmd_solver = "@path @input -o @output"
self._cmd_output = ""

View File

@ -22,7 +22,7 @@ from Solver.GenericSolver import GenericSolver
from Solver.Mage import ( from Solver.Mage import (
Mage7, Mage8, MageFake7, Mage7, Mage8, MageFake7,
) )
from Solver.RubarBE import RubarBE from Solver.RubarBE import Rubar3, RubarBE
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
@ -32,6 +32,7 @@ solver_long_name = {
"mage8": "Mage v8", "mage8": "Mage v8",
# "mage_fake7": "Mage fake v7", # "mage_fake7": "Mage fake v7",
# "rubarbe": "RubarBE", # "rubarbe": "RubarBE",
# "rubar3": "Rubar3",
} }
solver_type_list = { solver_type_list = {
@ -40,4 +41,5 @@ solver_type_list = {
"mage8": Mage8, "mage8": Mage8,
# "mage_fake7": MageFake7, # "mage_fake7": MageFake7,
# "rubarbe": RubarBE, # "rubarbe": RubarBE,
# "rubar3": Rubar3,
} }

View File

@ -67,5 +67,5 @@ class AboutWindow(PamhyrDialog):
label = f"\n - {author}" + label label = f"\n - {author}" + label
except StopIteration: except StopIteration:
label = _translate("About", "Contributors: ") + label label = _translate("About", "Contributors: ") + label
label = "Copyright © 2022-2024 INRAE\n" + label # label = "Copyright © 2022-2024 INRAE\n" + label
self.set_label_text("label_copyright", label) self.set_label_text("label_copyright", label)

View File

@ -133,6 +133,7 @@ class EditBoundaryConditionWindow(PamhyrWindow):
self.setup_plot() self.setup_plot()
self.setup_data() self.setup_data()
self.setup_connections() self.setup_connections()
self.setup_dialog()
def setup_data(self): def setup_data(self):
self._is_solid = self._data.bctype == "SL" self._is_solid = self._data.bctype == "SL"
@ -208,13 +209,17 @@ class EditBoundaryConditionWindow(PamhyrWindow):
.triggered.connect(self.generate_uniform) .triggered.connect(self.generate_uniform)
self.find(QAction, "action_generate_critical")\ self.find(QAction, "action_generate_critical")\
.triggered.connect(self.generate_critical) .triggered.connect(self.generate_critical)
self.find(QAction, "action_increasing")\
.triggered.connect(self.make_increasing)
if self._data.bctype != "ZD" or not self._data.has_node: if self._data.bctype != "ZD" or not self._data.has_node:
self.find(QAction, "action_generate_uniform").setVisible(False) self.find(QAction, "action_generate_uniform").setVisible(False)
self.find(QAction, "action_generate_critical").setVisible(False) self.find(QAction, "action_generate_critical").setVisible(False)
self.find(QAction, "action_increasing").setVisible(False)
else: else:
self.find(QAction, "action_generate_uniform").setVisible(True) self.find(QAction, "action_generate_uniform").setVisible(True)
self.find(QAction, "action_generate_critical").setVisible(True) self.find(QAction, "action_generate_critical").setVisible(True)
self.find(QAction, "action_increasing").setVisible(True)
self._table.dataChanged.connect(self.update) self._table.dataChanged.connect(self.update)
self._table.layoutChanged.connect(self.update) self._table.layoutChanged.connect(self.update)
@ -226,6 +231,10 @@ class EditBoundaryConditionWindow(PamhyrWindow):
else: else:
self._d50sigma.setEnabled(False) self._d50sigma.setEnabled(False)
def setup_dialog(self):
reach = self._data.reach(self._study.river)[0]
self.slope_value = abs(reach.get_incline_median_mean())
def d50_changed(self, value): def d50_changed(self, value):
self._undo_stack.push( self._undo_stack.push(
SetMetaDataCommand( SetMetaDataCommand(
@ -340,15 +349,16 @@ class EditBoundaryConditionWindow(PamhyrWindow):
def generate_uniform(self): def generate_uniform(self):
if self._data.has_node: if self._data.has_node:
node = self._data.node node = self._data.node
if node is None:
return
reach = self._data.reach(self._study.river)[0] reach = self._data.reach(self._study.river)[0]
profile = reach.profiles[-1] profile = reach.profiles[-1]
incline = abs(reach.get_incline_median_mean()) dlg = GenerateDialog(self.slope_value,
dlg = GenerateDialog(incline,
reach, reach,
trad=self._trad, trad=self._trad,
parent=self) parent=self)
if dlg.exec(): if dlg.exec():
incline = dlg.value self.slope_value = dlg.value
frictions = reach._parent.frictions.frictions frictions = reach._parent.frictions.frictions
z_min = profile.z_min() z_min = profile.z_min()
z_max = profile.z_max() z_max = profile.z_max()
@ -360,8 +370,10 @@ class EditBoundaryConditionWindow(PamhyrWindow):
strickler = 25.0 strickler = 25.0
height = [(i)*(z_max-z_min)/50 for i in range(51)] height = [(i)*(z_max-z_min)/50 for i in range(51)]
q = [((profile.wet_width(z_min + h) * 0.8) * strickler q = [((profile.wet_width(z_min + h) * 0.8) * strickler
* (h ** (5/3)) * (abs(incline) ** (0.5))) * (h ** (5/3)) * (abs(self.slope_value) ** (0.5)))
for h in height] for h in height]
for i in range(len(height)):
height[i] += z_min
self._table.replace_data(height, q) self._table.replace_data(height, q)
return return
@ -369,6 +381,8 @@ class EditBoundaryConditionWindow(PamhyrWindow):
def generate_critical(self): def generate_critical(self):
if self._data.has_node: if self._data.has_node:
node = self._data.node node = self._data.node
if node is None:
return
reach = self._data.reach(self._study.river)[0] reach = self._data.reach(self._study.river)[0]
profile = reach.profiles[-1] profile = reach.profiles[-1]
z_min = profile.z_min() z_min = profile.z_min()
@ -377,5 +391,25 @@ class EditBoundaryConditionWindow(PamhyrWindow):
q = [sqrt(9.81 * (profile.wet_area(z_min + h) ** 3) q = [sqrt(9.81 * (profile.wet_area(z_min + h) ** 3)
/ profile.wet_width(z_min + h)) / profile.wet_width(z_min + h))
for h in height] for h in height]
for i in range(len(height)):
height[i] += z_min
self._table.replace_data(height, q) self._table.replace_data(height, q)
return return
def make_increasing(self):
if self._data.has_node:
node = self._data.node
if node is None:
return
if len(self._table._data) < 2:
return
h = [self._data.get_i(0)[0]]
q = [self._data.get_i(0)[1]]
for i in range(len(self._table._data)):
if i == 0:
continue
row = self._data.get_i(i)
if row[1] > q[-1]:
h.append(row[0])
q.append(row[1])
self._table.replace_data(h, q)

View File

@ -74,17 +74,17 @@ class ConfigureSolverWindow(PamhyrDialog):
# File button # File button
buttons = { buttons = {
"pushButton_input": (lambda: self.file_dialog( "pushButton_input": (lambda: self.file_dialog(
select_file=True, select_file="ExistingFile",
callback=lambda f: self.set_line_edit_text( callback=lambda f: self.set_line_edit_text(
"lineEdit_input", f[0]) "lineEdit_input", f[0])
)), )),
"pushButton_solver": (lambda: self.file_dialog( "pushButton_solver": (lambda: self.file_dialog(
select_file=True, select_file="ExistingFile",
callback=lambda f: self.set_line_edit_text( callback=lambda f: self.set_line_edit_text(
"lineEdit_solver", f[0]) "lineEdit_solver", f[0])
)), )),
"pushButton_output": (lambda: self.file_dialog( "pushButton_output": (lambda: self.file_dialog(
select_file=True, select_file="ExistingFile",
callback=lambda f: self.set_line_edit_text( callback=lambda f: self.set_line_edit_text(
"lineEdit_output", f[0]) "lineEdit_output", f[0])
)), )),

View File

@ -157,7 +157,7 @@ class ConfigureWindow(PamhyrDialog):
"pushButton_stricklers_sort": self.sort_stricklers, "pushButton_stricklers_sort": self.sort_stricklers,
# Others # Others
# "pushButton_backup_path": lambda: self.file_dialog( # "pushButton_backup_path": lambda: self.file_dialog(
# select_file=False, # select_file="Directory",
# callback=lambda f: self.set_line_edit_text( # callback=lambda f: self.set_line_edit_text(
# "lineEdit_backup_path", f[0] # "lineEdit_backup_path", f[0]
# ) # )

View File

@ -41,7 +41,7 @@ class PlotAC(PamhyrPlot):
self._autoscale_update = True self._autoscale_update = True
self.label_x = self._trad["transverse_abscissa"] self.label_x = self._trad["transverse_abscissa"]
self.label_y = self._trad["unit_height"] self.label_y = self._trad["unit_elevation"]
self.label_previous_plot_selected = self._trad["prev_cs"] self.label_previous_plot_selected = self._trad["prev_cs"]
self.label_plot_selected = self._trad["cs"] self.label_plot_selected = self._trad["cs"]

View File

@ -56,8 +56,8 @@ class Plot(PamhyrPlot):
self.line_xy = [] self.line_xy = []
self.line_gl = [] self.line_gl = []
self.label_x = self._trad["unit_rk"] self.label_x = self._trad["transverse_abscissa"]
self.label_y = self._trad["unit_height"] self.label_y = self._trad["unit_elevation"]
self.before_plot_selected = None self.before_plot_selected = None
self.plot_selected = None self.plot_selected = None

View File

@ -108,7 +108,7 @@ hydraulic structure values?"
self._sub_dict["long_types"] = { self._sub_dict["long_types"] = {
"ND": self._dict["not_defined"], "ND": self._dict["not_defined"],
"S1": _translate( "S1": _translate(
"BasicHydraulicStructures", "Discharge weir" "BasicHydraulicStructures", "Rectangular weir"
), ),
"S2": _translate( "S2": _translate(
"BasicHydraulicStructures", "Trapezoidal weir" "BasicHydraulicStructures", "Trapezoidal weir"

View File

@ -0,0 +1,60 @@
# DialogDepth.py -- Pamhyr
# Copyright (C) 2023-2024 INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
from View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtGui import (
QKeySequence,
)
from PyQt5.QtCore import (
Qt, QVariant, QAbstractTableModel,
)
from PyQt5.QtWidgets import (
QDialogButtonBox, QComboBox, QUndoStack, QShortcut,
QDoubleSpinBox, QCheckBox,
)
class DepthDialog(PamhyrDialog):
_pamhyr_ui = "InitialConditions_Dialog_Generator_Depth"
_pamhyr_name = "Depth"
def __init__(self, value, option, trad=None, parent=None):
super(DepthDialog, self).__init__(
title=trad[self._pamhyr_name],
options=[],
trad=trad,
parent=parent
)
self.value = value
self.option = option
self.sb = self.find(QDoubleSpinBox, "doubleSpinBox")
self.sb.setValue(self.value)
self.cb = self.find(QCheckBox, "checkBox")
self.cb.setChecked(self.option)
def accept(self):
self.value = self.sb.value()
self.option = self.cb.isChecked()
super().accept()
def reject(self):
self.close()

View File

@ -36,7 +36,12 @@ class DischargeDialog(PamhyrDialog):
_pamhyr_ui = "InitialConditions_Dialog_Generator_Discharge" _pamhyr_ui = "InitialConditions_Dialog_Generator_Discharge"
_pamhyr_name = "Discharge" _pamhyr_name = "Discharge"
def __init__(self, title="Discharge", trad=None, parent=None): def __init__(self,
value,
option,
title="Discharge",
trad=None,
parent=None):
super(DischargeDialog, self).__init__( super(DischargeDialog, self).__init__(
title=trad[self._pamhyr_name], title=trad[self._pamhyr_name],
options=[], options=[],
@ -44,12 +49,16 @@ class DischargeDialog(PamhyrDialog):
parent=parent parent=parent
) )
self.value = None self.value = value
self.option = None self.option = option
self.sb = self.find(QDoubleSpinBox, "doubleSpinBox")
self.sb.setValue(self.value)
self.cb = self.find(QCheckBox, "checkBox")
self.cb.setChecked(self.option)
def accept(self): def accept(self):
self.value = self.find(QDoubleSpinBox, "doubleSpinBox").value() self.value = self.sb.value()
self.option = self.find(QCheckBox, "checkBox").isChecked() self.option = self.cb.isChecked()
super().accept() super().accept()
def reject(self): def reject(self):

View File

@ -28,7 +28,7 @@ from PyQt5.QtCore import (
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QDialogButtonBox, QComboBox, QUndoStack, QShortcut, QDialogButtonBox, QComboBox, QUndoStack, QShortcut,
QDoubleSpinBox, QCheckBox, QDoubleSpinBox, QCheckBox, QLabel
) )
@ -36,7 +36,7 @@ class HeightDialog(PamhyrDialog):
_pamhyr_ui = "InitialConditions_Dialog_Generator_Height" _pamhyr_ui = "InitialConditions_Dialog_Generator_Height"
_pamhyr_name = "Height" _pamhyr_name = "Height"
def __init__(self, trad=None, parent=None): def __init__(self, values, option, trad=None, parent=None):
super(HeightDialog, self).__init__( super(HeightDialog, self).__init__(
title=trad[self._pamhyr_name], title=trad[self._pamhyr_name],
options=[], options=[],
@ -44,12 +44,29 @@ class HeightDialog(PamhyrDialog):
parent=parent parent=parent
) )
self.value = None self.values = values
self.option = None self.option = option
self.sb1 = self.find(QDoubleSpinBox, "doubleSpinBox_1")
self.sb1.setValue(self.values[0])
self.sb2 = self.find(QDoubleSpinBox, "doubleSpinBox_2")
self.sb2.setValue(self.values[1])
self.sb3 = self.find(QDoubleSpinBox, "doubleSpinBox_3")
self.sb3.setValue(self.values[2])
self.cb = self.find(QCheckBox, "checkBox")
self.cb.setChecked(self.option)
self.enable_discharge()
self.cb.clicked.connect(self.enable_discharge)
def enable_discharge(self):
label = self.find(QLabel, "label_3")
self.sb3.setEnabled(self.cb.isChecked())
label.setEnabled(self.cb.isChecked())
def accept(self): def accept(self):
self.value = self.find(QDoubleSpinBox, "doubleSpinBox").value() self.values[0] = self.sb1.value()
self.option = self.find(QCheckBox, "checkBox").isChecked() self.values[1] = self.sb2.value()
self.values[2] = self.sb3.value()
self.option = self.cb.isChecked()
super().accept() super().accept()
def reject(self): def reject(self):

View File

@ -195,8 +195,13 @@ class GenerateCommand(QUndoCommand):
def redo(self): def redo(self):
if self._generator == "growing": if self._generator == "growing":
self._ics.generate_growing_constante_height(self._param, self._ics.generate_growing_constant_depth(self._param,
self._option) self._option)
elif self._generator == "discharge": elif self._generator == "discharge":
self._ics.generate_discharge(self._param, self._ics.generate_discharge(self._param,
self._option) self._option)
elif self._generator == "height":
self._ics.generate_height(self._param[0],
self._param[1],
self._option,
self._param[2])

View File

@ -58,6 +58,7 @@ from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.InitialConditions.PlotDRK import PlotDRK from View.InitialConditions.PlotDRK import PlotDRK
from View.InitialConditions.PlotDischarge import PlotDischarge from View.InitialConditions.PlotDischarge import PlotDischarge
from View.InitialConditions.translate import ICTranslate from View.InitialConditions.translate import ICTranslate
from View.InitialConditions.DialogDepth import DepthDialog
from View.InitialConditions.DialogHeight import HeightDialog from View.InitialConditions.DialogHeight import HeightDialog
from View.InitialConditions.DialogDischarge import DischargeDialog from View.InitialConditions.DialogDischarge import DischargeDialog
from View.WaitingDialog import WaitingDialog from View.WaitingDialog import WaitingDialog
@ -103,6 +104,7 @@ class InitialConditionsWindow(PamhyrWindow):
self.setup_table() self.setup_table()
self.setup_plot() self.setup_plot()
self.setup_connections() self.setup_connections()
self.setub_dialogs()
self.ui.setWindowTitle(self._title) self.ui.setWindowTitle(self._title)
@ -179,16 +181,27 @@ class InitialConditionsWindow(PamhyrWindow):
self.find(QAction, "action_import").triggered\ self.find(QAction, "action_import").triggered\
.connect(self.import_from_file) .connect(self.import_from_file)
self.find(QPushButton, "pushButton_generate_1").clicked.connect(
self.generate_growing_constante_height
)
self.find(QPushButton, "pushButton_generate_1").clicked.connect(
self.generate_growing_constant_depth
)
self.find(QPushButton, "pushButton_generate_2").clicked.connect( self.find(QPushButton, "pushButton_generate_2").clicked.connect(
self.generate_discharge self.generate_discharge
) )
self.find(QPushButton, "pushButton_generate_3").clicked.connect(
self.generate_height
)
self._table.dataChanged.connect(self._update_plot) self._table.dataChanged.connect(self._update_plot)
def setub_dialogs(self):
self.height_values = [0.0, 0.0, 0.0]
self.height_option = True
self.discharge_value = 0.0
self.discharge_option = True
self.depth_value = 0.0
self.depth_option = True
def index_selected_row(self): def index_selected_row(self):
table = self.find(QTableView, f"tableView") table = self.find(QTableView, f"tableView")
rows = table.selectionModel()\ rows = table.selectionModel()\
@ -255,6 +268,7 @@ class InitialConditionsWindow(PamhyrWindow):
workdir = os.path.dirname(self._study.filename) workdir = os.path.dirname(self._study.filename)
return self.file_dialog( return self.file_dialog(
select_file="ExistingFile",
callback=lambda d: self._import_from_file(d[0]), callback=lambda d: self._import_from_file(d[0]),
directory=workdir, directory=workdir,
default_suffix=".BIN", default_suffix=".BIN",
@ -352,18 +366,41 @@ class InitialConditionsWindow(PamhyrWindow):
self._table.redo() self._table.redo()
self._update() self._update()
def generate_growing_constante_height(self): def generate_growing_constant_depth(self):
dlg = HeightDialog(trad=self._trad, parent=self) dlg = DepthDialog(self.depth_value,
self.depth_option,
trad=self._trad,
parent=self)
if dlg.exec(): if dlg.exec():
value = dlg.value self.depth_value = dlg.value
compute_discharge = dlg.option self.depth_option = dlg.option
self._table.generate("growing", value, compute_discharge) self._table.generate("growing",
self.depth_value,
self.depth_option)
self._update() self._update()
def generate_discharge(self): def generate_discharge(self):
dlg = DischargeDialog(trad=self._trad, parent=self) dlg = DischargeDialog(self.discharge_value,
self.discharge_option,
trad=self._trad,
parent=self)
if dlg.exec(): if dlg.exec():
value = dlg.value self.discharge_value = dlg.value
compute_height = dlg.option self.discharge_option = dlg.option
self._table.generate("discharge", value, compute_height) self._table.generate("discharge",
self.discharge_value,
self.discharge_option)
self._update()
def generate_height(self):
dlg = HeightDialog(self.height_values,
self.height_option,
trad=self._trad,
parent=self)
if dlg.exec():
self.height_values = dlg.values
self.height_option = dlg.option
self._table.generate("height",
self.height_values,
self.height_option)
self._update() self._update()

View File

@ -28,11 +28,7 @@ class ICTranslate(MainTranslate):
super(ICTranslate, self).__init__() super(ICTranslate, self).__init__()
self._dict["Initial condition"] = _translate( self._dict["Initial condition"] = _translate(
"InitialCondition", "Initial condition") "InitialCondition", "Initial conditions")
self._dict["Discharge"] = _translate(
"InitialCondition", "Discharge")
self._dict["Height"] = _translate(
"InitialCondition", "Height")
self._dict["elevation"] = self._dict["unit_elevation"] self._dict["elevation"] = self._dict["unit_elevation"]
self._dict["discharge"] = self._dict["unit_discharge"] self._dict["discharge"] = self._dict["unit_discharge"]

View File

@ -499,6 +499,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
self.update() self.update()
def close_model(self): def close_model(self):
if not self.dialog_close(cancel=True):
return
self._study = None self._study = None
self.update_enable_action() self.update_enable_action()
self.conf.set_close_correctly() self.conf.set_close_correctly()
@ -748,15 +751,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
################## ##################
def msg_select_reach(self): def msg_select_reach(self):
self.message_box("Please select a reach", self.message_box(
"Geometry edition need a reach selected " self._trad["mb_select_reach_title"],
"into river network window to work on it") self._trad["mb_select_reach_msg"]
)
def dialog_reopen_study(self): def dialog_reopen_study(self):
dlg = QMessageBox(self) dlg = QMessageBox(self)
dlg.setWindowTitle("Last open study") dlg.setWindowTitle(self._trad["mb_last_open_title"])
dlg.setText("Do you want to open again the last open study?") dlg.setText(self._trad["mb_last_open_msg"])
opt = QMessageBox.Cancel | QMessageBox.Ok # | QMessageBox.Open opt = QMessageBox.Cancel | QMessageBox.Ok # | QMessageBox.Open
dlg.setStandardButtons(opt) dlg.setStandardButtons(opt)
@ -796,9 +800,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def dialog_close(self, cancel=True): def dialog_close(self, cancel=True):
dlg = QMessageBox(self) dlg = QMessageBox(self)
dlg.setWindowTitle("Close PAMHYR without saving study") dlg.setWindowTitle(self._trad["mb_close_title"])
dlg.setText("Do you want to save current study before PAMHYR close ?") dlg.setText(self._trad["mb_close_msg"])
opt = QMessageBox.Save | QMessageBox.Ignore opt = QMessageBox.Save | QMessageBox.Close
if cancel: if cancel:
opt |= QMessageBox.Cancel opt |= QMessageBox.Cancel
@ -810,7 +814,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if res == QMessageBox.Save: if res == QMessageBox.Save:
self.save_study() self.save_study()
return True return True
elif res == QMessageBox.Ignore: elif res == QMessageBox.Close:
return True return True
elif res == QMessageBox.Cancel: elif res == QMessageBox.Cancel:
return False return False
@ -1446,15 +1450,3 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
f"sqlitebrowser {file}", f"sqlitebrowser {file}",
shell=True shell=True
) )
# TODO: Delete me !
###############
# DUMMY STUFF #
###############
def open_dummy(self, title="Dummy"):
self.dummy = DummyWindow(
title=title if type(title) is str else "Dummy",
parent=self
)
self.dummy.show()

View File

@ -368,11 +368,18 @@ class EdgeItem(QGraphicsItem):
class NodeText(QGraphicsTextItem): class NodeText(QGraphicsTextItem):
def __init__(self, node_item): def __init__(self, node_item, graph):
super(NodeText, self).__init__() super(NodeText, self).__init__()
self.item = node_item self.item = node_item
self.setPlainText(self.item.node.name) self.graph = graph
name = self.item.node.name
if name == "":
name = self.graph._trad.node_name(self.item.node)
self.setPlainText(name)
self.setDefaultTextColor(Qt.black) self.setDefaultTextColor(Qt.black)
self.set_custom_pos(self.item.pos()) self.set_custom_pos(self.item.pos())
self.setZValue(2) self.setZValue(2)
@ -502,7 +509,7 @@ class GraphWidget(QGraphicsView):
for node in self.graph.nodes(): for node in self.graph.nodes():
inode = NodeItem(node, self) inode = NodeItem(node, self)
self.texts[inode] = NodeText(inode) self.texts[inode] = NodeText(inode, self)
self.scene().addItem(self.texts[inode]) self.scene().addItem(self.texts[inode])
self.scene().addItem(inode) self.scene().addItem(inode)
self.node_items.append(inode) self.node_items.append(inode)
@ -578,7 +585,7 @@ class GraphWidget(QGraphicsView):
inode = NodeItem(node, self) inode = NodeItem(node, self)
self.scene().addItem(inode) self.scene().addItem(inode)
self.node_items.append(inode) self.node_items.append(inode)
self.texts[inode] = NodeText(inode) self.texts[inode] = NodeText(inode, self)
self.scene().addItem(self.texts[inode]) self.scene().addItem(self.texts[inode])
self.changeNode.emit(self.sender()) self.changeNode.emit(self.sender())

View File

@ -94,6 +94,9 @@ class NodeTableModel(PamhyrTableModel):
return ret return ret
if self._headers[index.column()] == "name":
return self._trad.node_name(self._lst[index.row()])
return self._lst[index.row()][self._headers[index.column()]] return self._lst[index.row()][self._headers[index.column()]]
@pyqtSlot() @pyqtSlot()
@ -133,6 +136,15 @@ class EdgeTableModel(PamhyrTableModel):
if role != Qt.ItemDataRole.DisplayRole: if role != Qt.ItemDataRole.DisplayRole:
return QVariant() return QVariant()
if (self._headers[index.column()] == "node1" or
self._headers[index.column()] == "node2"):
return self._trad.node_name(
self._lst[index.row()][self._headers[index.column()]]
)
if self._headers[index.column()] == "name":
return self._trad.edge_name(self._lst[index.row()])
return self._lst[index.row()][self._headers[index.column()]] return self._lst[index.row()][self._headers[index.column()]]
@pyqtSlot() @pyqtSlot()

View File

@ -97,6 +97,7 @@ class NetworkWindow(PamhyrWindow):
table_view=table, table_view=table,
table_headers=self._table_headers_node, table_headers=self._table_headers_node,
editable_headers=node_editable_headers, editable_headers=node_editable_headers,
trad=self._trad,
data=self._graph, data=self._graph,
undo=self._undo_stack, undo=self._undo_stack,
) )
@ -116,6 +117,7 @@ class NetworkWindow(PamhyrWindow):
table_view=table, table_view=table,
table_headers=self._table_headers_edge, table_headers=self._table_headers_edge,
editable_headers=edge_editable_headers, editable_headers=edge_editable_headers,
trad=self._trad,
delegates={ delegates={
"node1": self.delegate_combobox, "node1": self.delegate_combobox,
"node2": self.delegate_combobox, "node2": self.delegate_combobox,

View File

@ -31,6 +31,9 @@ class NetworkTranslate(MainTranslate):
"Network", "River network" "Network", "River network"
) )
self._dict["node"] = _translate("Network", "Node")
self._dict["edge"] = _translate("Network", "Reach")
self._dict["menu_add_node"] = _translate("Network", "Add node") self._dict["menu_add_node"] = _translate("Network", "Add node")
self._dict["menu_del_node"] = _translate("Network", "Delete the node") self._dict["menu_del_node"] = _translate("Network", "Delete the node")
self._dict["menu_edit_res_node"] = _translate( self._dict["menu_edit_res_node"] = _translate(
@ -63,3 +66,15 @@ class NetworkTranslate(MainTranslate):
"node2": _translate("Network", "Destination node"), "node2": _translate("Network", "Destination node"),
"id": _translate("Network", "Index"), "id": _translate("Network", "Index"),
} }
def node_name(self, node):
if node.name == "":
return f"{self['node']} #{node.id}"
return node.name
def edge_name(self, edge):
if edge.name == "":
return f"{self['edge']} #{edge.id}"
return edge.name

View File

@ -95,4 +95,5 @@ class CustomPlotValuesSelectionDialog(PamhyrDialog):
) )
self.value = x, y self.value = x, y
super().accept() super().accept()

View File

@ -34,7 +34,7 @@ unit = {
"water_elevation": "0-meter", "water_elevation": "0-meter",
"discharge": "1-m3s", "discharge": "1-m3s",
"velocity": "2-ms", "velocity": "2-ms",
"depth": "3-meter", "max_depth": "3-meter",
"mean_depth": "3-meter", "mean_depth": "3-meter",
"froude": "4-dimensionless", "froude": "4-dimensionless",
"wet_area": "5-m2", "wet_area": "5-m2",
@ -157,9 +157,9 @@ class CustomPlot(PamhyrPlot):
) )
lines["velocity"] = line lines["velocity"] = line
if "depth" in self._y: if "max_depth" in self._y:
ax = self._axes[unit["depth"]] ax = self._axes[unit["max_depth"]]
d = list( d = list(
map( map(
lambda p: p.geometry.max_water_depth( lambda p: p.geometry.max_water_depth(
@ -171,7 +171,7 @@ class CustomPlot(PamhyrPlot):
rk, d, rk, d,
color='brown', lw=1., color='brown', lw=1.,
) )
lines["depth"] = line lines["max_depth"] = line
if "mean_depth" in self._y: if "mean_depth" in self._y:
@ -361,9 +361,9 @@ class CustomPlot(PamhyrPlot):
) )
lines["velocity"] = line lines["velocity"] = line
if "depth" in self._y: if "max_depth" in self._y:
ax = self._axes[unit["depth"]] ax = self._axes[unit["max_depth"]]
d = list( d = list(
map(lambda z: profile.geometry.max_water_depth(z), z) map(lambda z: profile.geometry.max_water_depth(z), z)
) )
@ -372,7 +372,7 @@ class CustomPlot(PamhyrPlot):
ts, d, ts, d,
color='brown', lw=1., color='brown', lw=1.,
) )
lines["depth"] = line lines["max_depth"] = line
if "mean_depth" in self._y: if "mean_depth" in self._y:
@ -385,7 +385,7 @@ class CustomPlot(PamhyrPlot):
ts, d, ts, d,
color='orange', lw=1., color='orange', lw=1.,
) )
lines["depth"] = line lines["mean_depth"] = line
if "froude" in self._y: if "froude" in self._y:

View File

@ -59,20 +59,3 @@ class CustomPlotTranslate(ResultsTranslate):
self._dict['3-meter'] = self._dict["unit_height"] self._dict['3-meter'] = self._dict["unit_height"]
self._dict['4-dimensionless'] = self._dict["unit_froude"] self._dict['4-dimensionless'] = self._dict["unit_froude"]
self._dict['5-m2'] = self._dict["wet_area"] self._dict['5-m2'] = self._dict["wet_area"]
# SubDict
self._sub_dict["values_x"] = {
"rk": self._dict["rk"],
"time": self._dict["time"],
}
self._sub_dict["values_y"] = {
"elevation": self._dict["elevation"],
"water_elevation": self._dict["water_elevation"],
"discharge": self._dict["discharge"],
"velocity": self._dict["velocity"],
"depth": self._dict["max_depth"],
"mean_depth": self._dict["mean_depth"],
"froude": self._dict["froude"],
"wet_area": self._dict["wet_area"],
}

View File

@ -51,8 +51,8 @@ class PlotH(PamhyrPlot):
self._current_reach_id = reach_id self._current_reach_id = reach_id
self._current_profile_id = profile_id self._current_profile_id = profile_id
self.label_x = _translate("Results", "Time (s)") self.label_x = self._trad["unit_time_s"]
self.label_y = _translate("Results", "Discharge (m³/s)") self.label_y = self._trad["unit_discharge"]
self.label_discharge = _translate("Results", "Cross-section discharge") self.label_discharge = _translate("Results", "Cross-section discharge")
self.label_discharge_max = _translate("Results", "Max discharge") self.label_discharge_max = _translate("Results", "Max discharge")
@ -174,12 +174,12 @@ class PlotH(PamhyrPlot):
self._line.set_data(x, y) self._line.set_data(x, y)
self._current.set_data( self._current.set_data(
self._current_timestamp, [self._current_timestamp, self._current_timestamp],
self.canvas.axes.get_ylim() self.canvas.axes.get_ylim()
) )
def update_current(self): def update_current(self):
self._current.set_data( self._current.set_data(
self._current_timestamp, [self._current_timestamp, self._current_timestamp],
self.canvas.axes.get_ylim() self.canvas.axes.get_ylim()
) )

View File

@ -20,6 +20,8 @@ import os
import csv import csv
import logging import logging
from numpy import sqrt
from datetime import datetime from datetime import datetime
from tools import trace, timer, logger_exception from tools import trace, timer, logger_exception
@ -290,9 +292,9 @@ class ResultsWindow(PamhyrWindow):
pname = profile.name if profile.name != "" else profile.rk pname = profile.name if profile.name != "" else profile.rk
return (f"Reach: {reach.name} | " + return (f"{self._trad['reach']}: {reach.name} | " +
f"Profile: {pname} | " + f"{self._trad['cross_section']}: {pname} | " +
f"Timestamp : {fts} ({ts} sec)") f"{self._trad['unit_time_s']} : {fts} ({ts} sec)")
def setup_statusbar(self): def setup_statusbar(self):
txt = self._compute_status_label() txt = self._compute_status_label()
@ -308,8 +310,8 @@ class ResultsWindow(PamhyrWindow):
actions = { actions = {
"action_reload": self._reload, "action_reload": self._reload,
"action_add": self._add_custom_plot, "action_add": self._add_custom_plot,
# "action_export": self.export, "action_export": self._export,
"action_export": self.export_current, # "action_export": self.export_current,
} }
for action in actions: for action in actions:
@ -534,6 +536,7 @@ class ResultsWindow(PamhyrWindow):
grid.addWidget(canvas, 1, 0) grid.addWidget(canvas, 1, 0)
widget.setLayout(grid) widget.setLayout(grid)
tab_widget.addTab(widget, name) tab_widget.addTab(widget, name)
tab_widget.setCurrentWidget(widget)
def _copy(self): def _copy(self):
logger.info("TODO: copy") logger.info("TODO: copy")
@ -582,18 +585,50 @@ class ResultsWindow(PamhyrWindow):
self._button_last.setEnabled(True) self._button_last.setEnabled(True)
self._button_play.setIcon(self._icon_start) self._button_play.setIcon(self._icon_start)
def export(self): def _export(self):
dlg = CustomPlotValuesSelectionDialog(parent=self)
if dlg.exec():
x, y = dlg.value
else:
return
logger.debug(
"Export custom plot for: " +
f"{x} -> {','.join(y)}"
)
self.file_dialog( self.file_dialog(
select_file=False, select_file="AnyFile",
callback=lambda d: self.export_to(d[0]) callback=lambda f: self.export_to(f[0], x, y),
default_suffix=".csv",
file_filter=["CSV (*.csv)"],
) )
def export_to(self, directory): def export_to(self, filename, x, y):
timestamps = sorted(self._results.get("timestamps")) timestamps = sorted(self._results.get("timestamps"))
for reach in self._results.river.reachs: if x == "rk":
self.export_reach(reach, directory, timestamps) timestamp = self._get_current_timestamp()
val_dict = self._export_rk(timestamp, y, filename)
elif x == "time":
profile = self._get_current_profile()
val_dict = self._export_time(profile, y, filename)
def export_reach(self, reach, directory, timestamps): with open(filename, 'w', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=',',
quotechar='|', quoting=csv.QUOTE_MINIMAL)
dict_x = self._trad.get_dict("values_x")
dict_y = self._trad.get_dict("values_y")
header = [dict_x[x]]
for text in y:
header.append(dict_y[text])
writer.writerow(header)
for row in range(len(val_dict[x])):
line = [val_dict[x][row]]
for var in y:
line.append(val_dict[var][row])
writer.writerow(line)
def export_all(self, reach, directory, timestamps):
name = reach.name name = reach.name
name = name.replace(" ", "-") name = name.replace(" ", "-")
if len(timestamps) == 1: if len(timestamps) == 1:
@ -607,59 +642,144 @@ class ResultsWindow(PamhyrWindow):
with open(file_name, 'w', newline='') as csvfile: with open(file_name, 'w', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=',', writer = csv.writer(csvfile, delimiter=',',
quotechar='|', quoting=csv.QUOTE_MINIMAL) quotechar='|', quoting=csv.QUOTE_MINIMAL)
if len(timestamps) > 1: ts = timestamps[0]
writer.writerow(["name", "rk", "data-file"]) writer.writerow(self._table["raw_data"]._headers)
for profile in reach.profiles: for row in range(self._table["raw_data"].rowCount()):
p_file_name = os.path.join( line = []
directory, for column in range(self._table["raw_data"].columnCount()):
f"cs_{profile.geometry.id}.csv" index = self._table["raw_data"].index(row, column)
) line.append(self._table["raw_data"].data(index))
writer.writerow(line)
writer.writerow([
profile.name,
profile.rk,
p_file_name
])
self.export_profile(reach,
profile,
p_file_name,
timestamps)
else:
ts = timestamps[0]
writer.writerow(self._table["raw_data"]._headers)
for row in range(self._table["raw_data"].rowCount()):
line = []
for column in range(self._table["raw_data"].columnCount()):
index = self._table["raw_data"].index(row, column)
line.append(self._table["raw_data"].data(index))
writer.writerow(line)
def export_profile(self, reach, profile, file_name, timestamps):
with open(file_name, 'w', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=',',
quotechar='|', quoting=csv.QUOTE_MINIMAL)
writer.writerow(["timestamp", "z", "q"])
for ts in timestamps:
writer.writerow([
ts,
profile.get_ts_key(ts, "Z"),
profile.get_ts_key(ts, "Q"),
])
def export_current(self): def export_current(self):
self.file_dialog( self.file_dialog(
select_file=False, select_file="Directory",
callback=lambda d: self.export_current_to(d[0]) callback=lambda d: self.export_current_to(d[0])
) )
def export_current_to(self, directory): def export_current_to(self, directory):
reach = self._results.river.reachs[self._get_current_reach()] reach = self._results.river.reachs[self._get_current_reach()]
self.export_reach(reach, directory, [self._get_current_timestamp()]) self.export_all(reach, directory, [self._get_current_timestamp()])
def delete_tab(self, index): def delete_tab(self, index):
tab_widget = self.find(QTabWidget, f"tabWidget") tab_widget = self.find(QTabWidget, f"tabWidget")
self._additional_plot.pop(tab_widget.tabText(index)) self._additional_plot.pop(tab_widget.tabText(index))
tab_widget.removeTab(index) tab_widget.removeTab(index)
def _export_rk(self, timestamp, y, filename):
reach = self._results.river.reachs[self._get_current_reach()]
my_dict = {}
my_dict["rk"] = reach.geometry.get_rk()
if "elevation" in y:
my_dict["elevation"] = reach.geometry.get_z_min()
if "discharge" in y:
my_dict["discharge"] = list(
map(
lambda p: p.get_ts_key(timestamp, "Q"),
reach.profiles
)
)
if "water_elevation" in y:
my_dict["water_elevation"] = list(
map(
lambda p: p.get_ts_key(timestamp, "Z"),
reach.profiles
)
)
if "velocity" in y:
my_dict["velocity"] = list(
map(
lambda p: p.geometry.speed(
p.get_ts_key(timestamp, "Q"),
p.get_ts_key(timestamp, "Z")),
reach.profiles
)
)
if "max_depth" in y:
my_dict["max_depth"] = list(
map(
lambda p: p.geometry.max_water_depth(
p.get_ts_key(timestamp, "Z")),
reach.profiles
)
)
if "mean_depth" in y:
my_dict["mean_depth"] = list(
map(
lambda p: p.geometry.mean_water_depth(
p.get_ts_key(timestamp, "Z")),
reach.profiles
)
)
if "froude" in y:
my_dict["froude"] = list(
map(
lambda p:
p.geometry.speed(
p.get_ts_key(timestamp, "Q"),
p.get_ts_key(timestamp, "Z")) /
sqrt(9.81 * (
p.geometry.wet_area(
p.get_ts_key(timestamp, "Z")) /
p.geometry.wet_width(
p.get_ts_key(timestamp, "Z"))
)),
reach.profiles
)
)
if "wet_area" in y:
my_dict["wet_area"] = list(
map(
lambda p: p.geometry.wet_area(
p.get_ts_key(timestamp, "Z")),
reach.profiles
)
)
return my_dict
def _export_time(self, profile, y, filename):
reach = self._results.river.reachs[self._get_current_reach()]
profile = reach.profile(profile)
ts = list(self._results.get("timestamps"))
ts.sort()
my_dict = {}
my_dict["time"] = ts
z = profile.get_key("Z")
q = profile.get_key("Q")
if "elevation" in y:
my_dict["elevation"] = [profile.geometry.z_min()] * len(ts)
if "discharge" in y:
my_dict["discharge"] = q
if "water_elevation" in y:
my_dict["water_elevation"] = z
if "velocity" in y:
my_dict["velocity"] = list(
map(
lambda q, z: profile.geometry.speed(q, z),
q, z
)
)
if "max_depth" in y:
my_dict["max_depth"] = list(
map(lambda z: profile.geometry.max_water_depth(z), z)
)
if "mean_depth" in y:
my_dict["mean_depth"] = list(
map(lambda z: profile.geometry.mean_water_depth(z), z)
)
if "froude" in y:
my_dict["froude"] = list(
map(lambda z, q:
profile.geometry.speed(q, z) /
sqrt(9.81 * (
profile.geometry.wet_area(z) /
profile.geometry.wet_width(z))
), z, q)
)
if "wet_area" in y:
my_dict["wet_area"] = list(
map(lambda z: profile.geometry.wet_area(z), z)
)
return my_dict

View File

@ -37,7 +37,7 @@ class ResultsTranslate(MainTranslate):
self._dict['x'] = _translate("Results", "X (m)") self._dict['x'] = _translate("Results", "X (m)")
self._dict['label_bottom'] = _translate("Results", "River bottom") self._dict['label_bottom'] = _translate("Results", "Bottom")
self._dict['label_water'] = _translate("Results", "Water elevation") self._dict['label_water'] = _translate("Results", "Water elevation")
self._dict['label_water_max'] = _translate( self._dict['label_water_max'] = _translate(
"Results", "Results",
@ -66,3 +66,19 @@ class ResultsTranslate(MainTranslate):
"hydraulic_radius": self._dict["unit_hydraulic_radius"], "hydraulic_radius": self._dict["unit_hydraulic_radius"],
"froude": self._dict["unit_froude"], "froude": self._dict["unit_froude"],
} }
self._sub_dict["values_x"] = {
"rk": self._dict["unit_rk"],
"time": self._dict["unit_time_s"],
}
self._sub_dict["values_y"] = {
"elevation": self._dict["unit_elevation"],
"water_elevation": self._dict["unit_water_elevation"],
"discharge": self._dict["unit_discharge"],
"velocity": self._dict["unit_speed"],
"max_depth": self._dict["unit_max_height"],
"mean_depth": self._dict["unit_mean_height"],
"froude": self._dict["unit_froude"],
"wet_area": self._dict["unit_wet_area"],
}

View File

@ -85,7 +85,7 @@ class WindowToolKit(object):
return header, values return header, values
def file_dialog(self, select_file=True, def file_dialog(self, select_file="ExistingFile",
callback=lambda x: None, callback=lambda x: None,
directory=None, directory=None,
default_suffix=None, default_suffix=None,
@ -107,16 +107,18 @@ class WindowToolKit(object):
dialog = QFileDialog(self, options=options) dialog = QFileDialog(self, options=options)
if select_file: if select_file == "Existing_file":
mode = QFileDialog.FileMode.ExistingFile mode = QFileDialog.FileMode.ExistingFile
else: elif select_file == "Directory":
mode = QFileDialog.FileMode.Directory mode = QFileDialog.FileMode.Directory
else:
mode = QFileDialog.FileMode.AnyFile
dialog.setFileMode(mode) dialog.setFileMode(mode)
if directory is not None: if directory is not None:
dialog.setDirectory(directory) dialog.setDirectory(directory)
if select_file: if select_file != "Directory":
if default_suffix is not None: if default_suffix is not None:
dialog.setDefaultSuffix(default_suffix) dialog.setDefaultSuffix(default_suffix)
@ -147,6 +149,9 @@ class WindowToolKit(object):
msg.setInformativeText(informative_text) msg.setInformativeText(informative_text)
msg.setWindowTitle(window_title) msg.setWindowTitle(window_title)
msg.findChild(QLabel, "qt_msgbox_label")\
.setFixedWidth(384)
msg.exec_() msg.exec_()

View File

@ -66,8 +66,9 @@ class UnitTranslate(CommonWordTranslate):
self._dict["unit_water_elevation"] = _translate( self._dict["unit_water_elevation"] = _translate(
"Unit", "Water elevation (m)" "Unit", "Water elevation (m)"
) )
self._dict["unit_speed"] = _translate("Unit", "Velocity (m/s)") self._dict["unit_speed"] = _translate("Unit", "Velocity (m/s)")
self._dict["unit_discharge"] = _translate("Unit", "Discharge (m³/s)") self._dict["unit_discharge"] = _translate("Unit", "Discharge (m^3/s)")
self._dict["unit_area"] = _translate("Unit", "Area (hectare)") self._dict["unit_area"] = _translate("Unit", "Area (hectare)")
self._dict["unit_time_s"] = _translate("Unit", "Time (sec)") self._dict["unit_time_s"] = _translate("Unit", "Time (sec)")
@ -76,7 +77,7 @@ class UnitTranslate(CommonWordTranslate):
self._dict["unit_date_s"] = _translate("Unit", "Date (sec)") self._dict["unit_date_s"] = _translate("Unit", "Date (sec)")
self._dict["unit_date_iso"] = _translate("Unit", "Date (ISO format)") self._dict["unit_date_iso"] = _translate("Unit", "Date (ISO format)")
self._dict["unit_wet_area"] = _translate("Unit", "Wet Area (m²)") self._dict["unit_wet_area"] = _translate("Unit", "Wet Area (m^2)")
self._dict["unit_wet_perimeter"] = _translate( self._dict["unit_wet_perimeter"] = _translate(
"Unit", "Wet Perimeter (m)" "Unit", "Wet Perimeter (m)"
) )
@ -113,3 +114,29 @@ class MainTranslate(UnitTranslate):
self._dict["waiting_result"] = _translate( self._dict["waiting_result"] = _translate(
"MainWindow", "Reading results ..." "MainWindow", "Reading results ..."
) )
# Message box
self._dict["mb_select_reach_title"] = _translate(
"MainWindow", "Please select a reach"
)
self._dict["mb_select_reach_msg"] = _translate(
"MainWindow",
"This edition window need a reach selected "
"into the river network to work on it"
)
self._dict["mb_last_open_title"] = _translate(
"MainWindow", "Last open study"
)
self._dict["mb_last_open_msg"] = _translate(
"MainWindow",
"Do you want to open again the last open study?"
)
self._dict["mb_close_title"] = _translate(
"MainWindow", "Close without saving study"
)
self._dict["mb_close_msg"] = _translate(
"MainWindow",
"Do you want to save current study before closing it?"
)

View File

@ -382,7 +382,7 @@
</widget> </widget>
<widget class="QWidget" name="tab_language"> <widget class="QWidget" name="tab_language">
<attribute name="title"> <attribute name="title">
<string>Langue</string> <string>Language</string>
</attribute> </attribute>
<layout class="QGridLayout" name="gridLayout_6"> <layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0"> <item row="0" column="0">

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>414</width> <width>414</width>
<height>482</height> <height>70</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -57,22 +57,6 @@
</widget> </widget>
<resources/> <resources/>
<connections> <connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
@ -89,5 +73,21 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections> </connections>
</ui> </ui>

View File

@ -75,6 +75,7 @@
<addaction name="action_sort"/> <addaction name="action_sort"/>
<addaction name="action_generate_uniform"/> <addaction name="action_generate_uniform"/>
<addaction name="action_generate_critical"/> <addaction name="action_generate_critical"/>
<addaction name="action_increasing"/>
</widget> </widget>
<action name="action_add"> <action name="action_add">
<property name="checkable"> <property name="checkable">
@ -140,6 +141,14 @@
<string>Generate rating curve as Q(z) = Sqrt(g*S(z)^3/L(z))</string> <string>Generate rating curve as Q(z) = Sqrt(g*S(z)^3/L(z))</string>
</property> </property>
</action> </action>
<action name="action_increasing">
<property name="text">
<string>Make increasing</string>
</property>
<property name="toolTip">
<string>Remove points to make the curve increasing</string>
</property>
</action>
</widget> </widget>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1024</width> <width>849</width>
<height>576</height> <height>576</height>
</rect> </rect>
</property> </property>
@ -27,14 +27,21 @@
<item> <item>
<widget class="QPushButton" name="pushButton_generate_1"> <widget class="QPushButton" name="pushButton_generate_1">
<property name="text"> <property name="text">
<string>Generate height</string> <string>Generate uniform depth</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="pushButton_generate_2"> <widget class="QPushButton" name="pushButton_generate_2">
<property name="text"> <property name="text">
<string>Generate discharge</string> <string>Generate uniform discharge</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_generate_3">
<property name="text">
<string>Generate uniform elevation</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -65,7 +72,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1024</width> <width>849</width>
<height>22</height> <height>22</height>
</rect> </rect>
</property> </property>

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>284</width>
<height>107</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<property name="locale">
<locale language="English" country="Europe"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Depth (m)</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox">
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Generate discharge</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -32,7 +32,7 @@
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>Discharge (m³/s)</string> <string>Discharge (m^3/s)</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>284</width> <width>396</width>
<height>80</height> <height>182</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -17,7 +17,79 @@
<locale language="English" country="Europe"/> <locale language="English" country="Europe"/>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="2" column="0"> <item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Upstream height (m)</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox_1">
<property name="minimum">
<double>-1000000.000000000000000</double>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Discharge</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox_3">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<double>-1000000.000000000000000</double>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Downstream height (m)</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox_2">
<property name="minimum">
<double>-1000000.000000000000000</double>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QDialogButtonBox" name="buttonBox"> <widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
@ -27,34 +99,17 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0"> <item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<item> <item>
<widget class="QLabel" name="label"> <widget class="QCheckBox" name="checkBox">
<property name="text"> <property name="text">
<string>Height (m)</string> <string>Generate constant discharge</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox">
<property name="maximum">
<double>1000000.000000000000000</double>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Generate discharge</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>194</width> <width>251</width>
<height>114</height> <height>114</height>
</rect> </rect>
</property> </property>
@ -27,7 +27,7 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QGroupBox" name="groupBox_3"> <widget class="QGroupBox" name="groupBox_3">
<property name="title"> <property name="title">
<string>Number of points to keep</string> <string>Maximum number of points to keep</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0"> <item row="0" column="0">

View File

@ -132,14 +132,14 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>1</number>
</property> </property>
<property name="tabsClosable"> <property name="tabsClosable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<widget class="QWidget" name="tab_4"> <widget class="QWidget" name="tab_4">
<attribute name="title"> <attribute name="title">
<string>Raw data</string> <string>Data</string>
</attribute> </attribute>
<layout class="QGridLayout" name="gridLayout_5"> <layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="1"> <item row="0" column="1">
@ -262,7 +262,7 @@
<string>Export</string> <string>Export</string>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Export raw data</string> <string>Export data as CSV</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>Ctrl+E</string> <string>Ctrl+E</string>

View File

@ -17,8 +17,35 @@
<locale language="English" country="Europe"/> <locale language="English" country="Europe"/>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="1"> <item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_logo_pamhyr2">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>ressources/Pamhyr2_logo.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_logo_inrae">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>ressources/Logo-INRAE.png</pixmap>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<item> <item>
<widget class="QLabel" name="label_title"> <widget class="QLabel" name="label_title">
<property name="font"> <property name="font">
@ -33,34 +60,213 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<spacer name="horizontalSpacer_7">
<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="QLabel" name="label_2">
<property name="text">
<string>Copyright © 2022-2024 INRAE</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer_3">
<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="QLabel" name="label_version">
<property name="text">
<string>Version: @version</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<spacer name="horizontalSpacer_5">
<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="QLabel" name="label_license">
<property name="text">
<string>License: GPLv3+</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_logo_gpl">
<property name="maximumSize">
<size>
<width>100</width>
<height>50</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>ressources/GPLv3_Logo.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<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="QLabel" name="label">
<property name="text">
<string>&lt;a href=&quot;https://gitlab.irstea.fr/theophile.terraz/pamhyr&quot;&gt;Source code&lt;/a&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<widget class="QLabel" name="label_copyright"> <widget class="QLabel" name="label_copyright">
<property name="text"> <property name="text">
<string>...</string> <string>...</string>
</property> </property>
</widget> <property name="alignment">
</item> <set>Qt::AlignCenter</set>
<item>
<widget class="QLabel" name="label_version">
<property name="text">
<string>Version: @version</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_license">
<property name="text">
<string>License: GPLv3+</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;a href=&quot;https://gitlab.irstea.fr/theophile.terraz/pamhyr&quot;&gt;Source code&lt;/a&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property> </property>
</widget> </widget>
</item> </item>
@ -79,16 +285,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="0" column="0">
<widget class="QLabel" name="label_logo_pamhyr2">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>ressources/Pamhyr2_logo.png</pixmap>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

File diff suppressed because it is too large Load Diff