diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e8920060..0f0ec0d5 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -29,7 +29,7 @@ stages:
#############
variables:
- MAGE_8_VERSION: "v8.3.5"
+ MAGE_8_VERSION: "v8.3.6"
dl-mage8-doc:
stage: downloads
@@ -262,6 +262,11 @@ build-linux:
- cp -v ../mage8-linux/* pamhyr/mage8/
# Copy Pamhyr
- cp -r dist/pamhyr/* pamhyr/
+ # Pamhyr script to force x11
+ - echo '#!/usr/bin/env bash' > pamhyr/pamhyr-x11
+ - echo "" >> pamhyr/pamhyr-x11
+ - echo "GDK_BACKEND=x11 ./pamhyr $@" >> pamhyr/pamhyr-x11
+ - chmod +x pamhyr/pamhyr-x11
# Copy Pamhyr resources
- mkdir -p pamhyr/_internal/View
- mkdir -p pamhyr/_internal/View/ui
@@ -333,7 +338,7 @@ build-windows:
- python -m pip install -U -r ..\requirements.txt
# Run Pyinstaller
# - pyinstaller --noconsole -y ..\src\pamhyr.py
- - pyinstaller --hide-console hide-early -y ..\src\pamhyr.py
+ - pyinstaller -i ../src/View/ui/ressources/icon.ico --hide-console hide-early -y ..\src\pamhyr.py
# Create directory
- mkdir pamhyr
- dir
diff --git a/packages/pamhyr.nsi b/packages/pamhyr.nsi
index 7555a618..dd4a8053 100644
--- a/packages/pamhyr.nsi
+++ b/packages/pamhyr.nsi
@@ -3,6 +3,7 @@
!define LIC_NAME "LICENSE"
!define APP_NAME "PAMHYR"
+Icon "pamhyr\_internal\View\ui\ressources\icon.ico"
Name "Pamhyr2"
OutFile "pamhyr-windows.exe"
LicenseData "pamhyr\_internal\LICENSE"
diff --git a/src/Checker/Mage.py b/src/Checker/Mage.py
index e7f8352b..acb2ddc8 100644
--- a/src/Checker/Mage.py
+++ b/src/Checker/Mage.py
@@ -206,11 +206,11 @@ class MageGeometryGuideLineChecker(StudyGeometryChecker):
def __init__(self, version="mage8"):
super(MageGeometryGuideLineChecker, self).__init__()
- self._name = _translate("Checker", "Mage geometry guide line checker")
+ self._name = _translate("Checker", "Mage geometry guideline checker")
self._description = _translate(
"Checker",
- "Check if exists geometry guide line is correctly defined \
-for each reaches of the study"
+ "Check if exists geometry guidelines are correctly defined \
+for each reach"
)
self._solver = version
self._modules = Modules.GEOMETRY
@@ -241,7 +241,7 @@ for each reaches of the study"
for profile in profiles:
if not profile.has_standard_named_points():
self._status = STATUS.WARNING
- self._summary = "no_standard_guileline_defined"
+ self._summary = "no_standard_guideline_defined"
return False
for gl in gls[1:]:
diff --git a/src/Checker/Study.py b/src/Checker/Study.py
index f0d69262..b893a507 100644
--- a/src/Checker/Study.py
+++ b/src/Checker/Study.py
@@ -34,9 +34,9 @@ class StudyNetworkReachChecker(AbstractModelChecker):
def __init__(self):
super(StudyNetworkReachChecker, self).__init__()
- self._name = _translate("Checker", "Study network reach checker")
+ self._name = _translate("Checker", "Study reach network checker")
self._description = _translate(
- "Checker", "Check if exists at least one reach for study"
+ "Checker", "Check if exists at least one reach exists"
)
self._modules = Modules.NETWORK
@@ -63,7 +63,7 @@ class StudyGeometryChecker(AbstractModelChecker):
self._name = _translate("Checker", "Study geometry checker")
self._description = _translate(
- "Checker", "Check if exists geometry for each reach of study"
+ "Checker", "Check if the geometry of each reach exists"
)
self._modules = Modules.GEOMETRY
diff --git a/src/Meshing/Mage.py b/src/Meshing/Mage.py
index 1e8f4c2d..8eb89f8e 100644
--- a/src/Meshing/Mage.py
+++ b/src/Meshing/Mage.py
@@ -371,7 +371,8 @@ class MeshingWithMageMailleurTT(AMeshingTool):
lplan: bool = False,
lm: int = 3,
linear: bool = False,
- origin_value=0.0):
+ origin_value=0.0,
+ orientation=0):
if reach is None or len(reach.profiles) == 0:
return reach
@@ -400,7 +401,7 @@ class MeshingWithMageMailleurTT(AMeshingTool):
f"{str(step)} " +
f"{limites[0]} {limites[1]} " +
f"{directrices[0]} {directrices[1]} " +
- f"{lplan} {lm} {linear} " +
+ f"{orientation} {lm} {linear} " +
f"{origin} "
)
proc.start(
@@ -413,7 +414,7 @@ class MeshingWithMageMailleurTT(AMeshingTool):
"update_kp", step,
limites[0], limites[1],
directrices[0], directrices[1],
- lplan, lm, linear, origin, origin_value
+ orientation, lm, linear, origin, origin_value
]
)
)
diff --git a/src/Model/BoundaryCondition/BoundaryCondition.py b/src/Model/BoundaryCondition/BoundaryCondition.py
index 918af8b3..eddc52b1 100644
--- a/src/Model/BoundaryCondition/BoundaryCondition.py
+++ b/src/Model/BoundaryCondition/BoundaryCondition.py
@@ -315,6 +315,9 @@ class BoundaryCondition(SQLSubModel):
self._data.sort(reverse=_reverse, key=key)
self._status.modified()
+ def index(self, bc):
+ self._data.index(bc)
+
def get_i(self, index):
return self.data[index]
diff --git a/src/Model/Saved.py b/src/Model/Saved.py
index 90667a92..6b180b40 100644
--- a/src/Model/Saved.py
+++ b/src/Model/Saved.py
@@ -22,10 +22,19 @@ logger = logging.getLogger()
class SavedStatus(object):
- def __init__(self):
+ def __init__(self, version=0):
super(SavedStatus, self).__init__()
+ self._version = version
self._saved = True
+ @property
+ def version(self):
+ return self._version
+
+ @version.setter
+ def version(self, version):
+ self._version = version
+
def is_saved(self):
return self._saved
@@ -34,5 +43,11 @@ class SavedStatus(object):
self._saved = True
def modified(self):
- # logger.debug("model status set as modified")
+ if self._saved:
+ self._version += 1
+
+ logger.debug(
+ "STATUS: Model status set as modified " +
+ f"at version {self._version}"
+ )
self._saved = False
diff --git a/src/Model/Study.py b/src/Model/Study.py
index 1efdce00..736fce42 100644
--- a/src/Model/Study.py
+++ b/src/Model/Study.py
@@ -41,7 +41,7 @@ class Study(SQLModel):
def __init__(self, filename=None, init_new=True):
# Metadata
- self._version = "0.0.9"
+ self._version = "0.0.10"
self.creation_date = datetime.now()
self.last_modification_date = datetime.now()
self.last_save_date = datetime.now()
@@ -117,6 +117,9 @@ class Study(SQLModel):
if ".backup" in self.filename:
is_new = True
+ if not os.path.exists(self.filename):
+ is_new = True
+
self._init_db_file(self.filename, is_new=is_new)
self.commit()
@@ -209,7 +212,12 @@ class Study(SQLModel):
def _create(self):
# Info (metadata)
self.execute(
- "CREATE TABLE info(key TEXT NOT NULL UNIQUE, value TEXT NOT NULL)")
+ "INSERT INTO info VALUES ('study_release', '0')"
+ )
+
+ self.execute(
+ "CREATE TABLE info(key TEXT NOT NULL UNIQUE, value TEXT NOT NULL)"
+ )
self.execute(
"INSERT INTO info VALUES ('version', " +
f"'{self._db_format(self._version)}')",
@@ -218,19 +226,20 @@ class Study(SQLModel):
self.execute("INSERT INTO info VALUES ('name', '')")
self.execute("INSERT INTO info VALUES ('description', '')")
self.execute(
- f"INSERT INTO info VALUES ('time_system', '{self._time_system}')")
+ f"INSERT INTO info VALUES ('time_system', '{self._time_system}')"
+ )
self.execute(
- f"INSERT INTO info VALUES ('date', " +
- "'{self._date.timestamp()}')"
+ "INSERT INTO info VALUES ('date', " +
+ f"'{self._date.timestamp()}')"
)
self.execute(
- f"INSERT INTO info VALUES ('creation_date', " +
- "'{self.creation_time.timestamp()}')"
+ "INSERT INTO info VALUES ('creation_date', " +
+ f"'{self.creation_date.timestamp()}')"
)
self.execute(
- f"INSERT INTO info VALUES ('last_save_date', " +
- "'{self.last_save_time.timestamp()}')"
+ "INSERT INTO info VALUES ('last_save_date', " +
+ f"'{self.last_save_date.timestamp()}')"
)
self._create_submodel()
@@ -245,6 +254,12 @@ class Study(SQLModel):
logger.debug("Update database")
+ major, minor, release = version[0].split('.')
+ if major == "0" and minor == "0" and int(release) < 10:
+ self.execute(
+ "INSERT INTO info VALUES ('study_release', '0')"
+ )
+
if self._update_submodel(version[0]):
self.execute(
f"UPDATE info SET value='{self._version}' WHERE key='version'"
@@ -258,6 +273,11 @@ class Study(SQLModel):
def _load(cls, filename):
new = cls(init_new=False, filename=filename)
+ version = new.execute(
+ "SELECT value FROM info WHERE key='study_release'"
+ )
+ new.status.version = int(version[0])
+
# TODO: Load metadata
new.name = new.execute("SELECT value FROM info WHERE key='name'")[0]
new.description = new.execute(
@@ -292,6 +312,11 @@ class Study(SQLModel):
def _save(self, progress=None):
progress = progress if progress is not None else lambda: None
+ self.execute(
+ "INSERT INTO info VALUES ('study_release', " +
+ f"'{self.status.version}')"
+ )
+
self.execute(
f"UPDATE info SET " +
f"value='{self._db_format(self.name)}' WHERE key='name'"
diff --git a/src/Solver/Solvers.py b/src/Solver/Solvers.py
index 699e2f3b..c8484980 100644
--- a/src/Solver/Solvers.py
+++ b/src/Solver/Solvers.py
@@ -32,8 +32,8 @@ solver_long_name = {
# "mage7": "Mage v7",
"mage8": "Mage v8",
# "mage_fake7": "Mage fake v7",
- "rubarbe": "RubarBE",
"adistslc": "Adis-TS_LC",
+ # "rubarbe": "RubarBE",
}
solver_type_list = {
@@ -41,6 +41,6 @@ solver_type_list = {
# "mage7": Mage7,
"mage8": Mage8,
# "mage_fake7": MageFake7,
- "rubarbe": RubarBE,
"adistslc": AdisTSlc,
+ # "rubarbe": RubarBE,
}
diff --git a/src/View/BoundaryCondition/Edit/Table.py b/src/View/BoundaryCondition/Edit/Table.py
index 287a8fe4..d4a9f8a6 100644
--- a/src/View/BoundaryCondition/Edit/Table.py
+++ b/src/View/BoundaryCondition/Edit/Table.py
@@ -99,7 +99,7 @@ class TableModel(PamhyrTableModel):
logger.info(e)
logger.debug(traceback.format_exc())
- self.dataChanged.emit(index, index)
+ self.update()
return True
def add(self, row, parent=QModelIndex()):
@@ -112,7 +112,7 @@ class TableModel(PamhyrTableModel):
)
self.endInsertRows()
- self.layoutChanged.emit()
+ self.update()
def delete(self, rows, parent=QModelIndex()):
self.beginRemoveRows(parent, rows[0], rows[-1])
@@ -135,7 +135,7 @@ class TableModel(PamhyrTableModel):
)
self.layoutAboutToBeChanged.emit()
- self.layoutChanged.emit()
+ self.update()
def move_up(self, row, parent=QModelIndex()):
if row <= 0:
@@ -152,7 +152,7 @@ class TableModel(PamhyrTableModel):
)
self.endMoveRows()
- self.layoutChanged.emit()
+ self.update()
def move_down(self, index, parent=QModelIndex()):
if row > len(self._data):
@@ -169,7 +169,7 @@ class TableModel(PamhyrTableModel):
)
self.endMoveRows()
- self.layoutChanged.emit()
+ self.update()
def paste(self, row, header, data):
if len(data) == 0:
@@ -190,4 +190,13 @@ class TableModel(PamhyrTableModel):
)
self.layoutAboutToBeChanged.emit()
+ self.update()
+
+ def auto_sort(self):
+ self.layoutAboutToBeChanged.emit()
+ self._data.sort(key=lambda x: x[0])
+ self.layoutAboutToBeChanged.emit()
+
+ def update(self):
+ # self.auto_sort()
self.layoutChanged.emit()
diff --git a/src/View/BoundaryCondition/Edit/Window.py b/src/View/BoundaryCondition/Edit/Window.py
index faf41896..94557ddd 100644
--- a/src/View/BoundaryCondition/Edit/Window.py
+++ b/src/View/BoundaryCondition/Edit/Window.py
@@ -195,6 +195,7 @@ class EditBoundaryConditionWindow(PamhyrWindow):
self.find(QAction, "action_sort").triggered.connect(self.sort)
self._table.dataChanged.connect(self.update)
+ self._table.layoutChanged.connect(self.update)
if self._is_solid:
self._d50sigma.d50Changed.connect(self.d50_changed)
diff --git a/src/View/BoundaryCondition/translate.py b/src/View/BoundaryCondition/translate.py
index 19244076..02903dae 100644
--- a/src/View/BoundaryCondition/translate.py
+++ b/src/View/BoundaryCondition/translate.py
@@ -48,7 +48,7 @@ class BCTranslate(MainTranslate):
self._sub_dict["long_types"] = {
"ND": self._dict["not_defined"],
- "PC": _translate("BoundaryCondition", "Ponctual contribution"),
+ "PC": _translate("BoundaryCondition", "Point sources"),
"TZ": _translate("BoundaryCondition", "Z(t)"),
"TD": _translate("BoundaryCondition", "Q(t)"),
"ZD": _translate("BoundaryCondition", "Q(Z)"),
diff --git a/src/View/CheckList/Worker.py b/src/View/CheckList/Worker.py
index f8246fba..58295bee 100644
--- a/src/View/CheckList/Worker.py
+++ b/src/View/CheckList/Worker.py
@@ -46,7 +46,7 @@ class Worker(QObject):
self.signalStatus.emit(checker.name)
# Run checker
- checker._run(self._study)
+ checker.run(self._study)
self.signalStatus.emit("progress")
diff --git a/src/View/Frictions/PlotKPZ.py b/src/View/Frictions/PlotKPZ.py
new file mode 100644
index 00000000..97a80b5b
--- /dev/null
+++ b/src/View/Frictions/PlotKPZ.py
@@ -0,0 +1,50 @@
+# PlotKPC.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 .
+
+# -*- coding: utf-8 -*-
+
+from PyQt5.QtCore import QCoreApplication
+from View.HydraulicStructures.PlotKPC import PlotKPC
+
+_translate = QCoreApplication.translate
+
+
+class PlotKPZ(PlotKPC):
+ def __init__(self, canvas=None, trad=None, toolbar=None,
+ river=None, reach=None, profile=None,
+ parent=None):
+ super(PlotKPC, self).__init__(
+ canvas=canvas,
+ trad=trad,
+ data=river,
+ toolbar=toolbar,
+ parent=parent
+ )
+
+ self._current_reach = reach
+ self._current_profile = profile
+
+ self.label_x = self._trad["unit_kp"]
+ self.label_y = self._trad["unit_elevation"]
+
+ self._isometric_axis = False
+
+ self._auto_relim_update = True
+ self._autoscale_update = True
+ self.parent = parent
+
+ def onpick(self, event):
+ return
diff --git a/src/View/Frictions/PlotStricklers.py b/src/View/Frictions/PlotStricklers.py
index c7f0abc3..40bd9140 100644
--- a/src/View/Frictions/PlotStricklers.py
+++ b/src/View/Frictions/PlotStricklers.py
@@ -42,7 +42,7 @@ class PlotStricklers(PamhyrPlot):
)
self.label_x = self._trad["kp"]
- self.label_y = self._trad["stricklers"]
+ self.label_y = self._trad["strickler_plot"]
self.line_kp_elevation = [None, None]
diff --git a/src/View/Frictions/Window.py b/src/View/Frictions/Window.py
index a1922ddf..9776ce56 100644
--- a/src/View/Frictions/Window.py
+++ b/src/View/Frictions/Window.py
@@ -50,7 +50,7 @@ from View.Frictions.Table import (
)
from View.Tools.Plot.PamhyrCanvas import MplCanvas
-from View.Geometry.PlotKPZ import PlotKPZ
+from View.Frictions.PlotKPZ import PlotKPZ
from View.Frictions.PlotStricklers import PlotStricklers
from View.Frictions.translate import FrictionsTranslate
@@ -135,9 +135,11 @@ class FrictionsWindow(PamhyrWindow):
self.plot = PlotKPZ(
canvas=self.canvas,
- data=self._reach.reach,
+ reach=self._reach,
+ river=self._study.river,
trad=self._trad,
toolbar=None,
+ parent=self
)
self.plot.draw()
diff --git a/src/View/Frictions/translate.py b/src/View/Frictions/translate.py
index 57b823a7..c493ecf7 100644
--- a/src/View/Frictions/translate.py
+++ b/src/View/Frictions/translate.py
@@ -28,6 +28,9 @@ class FrictionsTranslate(MainTranslate):
super(FrictionsTranslate, self).__init__()
self._dict["kp"] = self._dict["unit_kp"]
+ self._dict["strickler_plot"] = _translate(
+ "Frictions", "Strickler ($m^{1/3}/s$)"
+ )
self._dict["stricklers"] = _translate(
"Frictions", "Stricklers"
)
@@ -39,8 +42,8 @@ class FrictionsTranslate(MainTranslate):
self._sub_dict["table_headers"] = {
# "name": self._dict["name"],
# "edge": self._dict["reach"],
- "begin_kp": _translate("Frictions", "Begin kp (m)"),
- "end_kp": _translate("Frictions", "End kp (m)"),
- "begin_strickler": _translate("Frictions", "Begin strickler"),
- "end_strickler": _translate("Frictions", "End strickler"),
+ "begin_kp": _translate("Frictions", "Start (m)"),
+ "end_kp": _translate("Frictions", "End (m)"),
+ "begin_strickler": _translate("Frictions", "Start coefficient"),
+ "end_strickler": _translate("Frictions", "End coefficient"),
}
diff --git a/src/View/Geometry/MeshingDialog.py b/src/View/Geometry/MeshingDialog.py
index 974aa187..852c272a 100644
--- a/src/View/Geometry/MeshingDialog.py
+++ b/src/View/Geometry/MeshingDialog.py
@@ -125,14 +125,6 @@ class MeshingDialog(PamhyrDialog):
def lplan(self):
return self._lplan
- @property
- def origin(self):
- return self._origin
-
- @property
- def lm(self):
- return int(self._lm)
-
@property
def linear(self):
return self._linear
@@ -165,15 +157,9 @@ class MeshingDialog(PamhyrDialog):
self._begin_cs = self.profiles.index(p1)
self._end_cs = self.profiles.index(p2)
- origin = self.get_combobox_text("comboBox_origin")
- self._origin = self.profiles.index(origin)
-
self._begin_dir = self.get_combobox_text("comboBox_begin_gl")
self._end_dir = self.get_combobox_text("comboBox_end_gl")
- r_lm_dict = self._trad.get_dict("r_lm_dict")
- self._lm = r_lm_dict[self.get_combobox_text("comboBox_lm")]
-
super().accept()
def reject(self):
diff --git a/src/View/Geometry/PlotAC.py b/src/View/Geometry/PlotAC.py
index cccffe24..ad43fdf3 100644
--- a/src/View/Geometry/PlotAC.py
+++ b/src/View/Geometry/PlotAC.py
@@ -98,6 +98,7 @@ class PlotAC(PamhyrPlot):
label=self.label_next_plot_selected,
color=self.color_plot_next, lw=1.6, linestyle='--'
)
+ self.canvas.axes.set_visible(False)
def draw_gl(self):
if self._current_data_update:
@@ -106,12 +107,16 @@ class PlotAC(PamhyrPlot):
profile_id = 0
profile = self.data.profile(profile_id)
+ if profile is None:
+ return
+
station = profile.get_station()
elevation = profile.z()
gl = profile.names()
self.annotation = []
self.complete_gl, self.incomplete_gl = self.data.compute_guidelines()
+
lcomplete = list(self.complete_gl)
lincomplete = list(self.incomplete_gl)
@@ -160,6 +165,9 @@ class PlotAC(PamhyrPlot):
self.draw()
return
+ if self.data is None:
+ return
+
self.update_current()
self.update_gl()
@@ -171,6 +179,10 @@ class PlotAC(PamhyrPlot):
previous_id = profile_id - 1
next_id = profile_id + 1
+ self.previous_plot_selected.set_visible(False)
+ self.plot_selected.set_visible(False)
+ self.next_plot_selected.set_visible(False)
+
self.previous_plot_selected.set_data([], [])
self.plot_selected.set_data([], [])
self.next_plot_selected.set_data([], [])
@@ -180,18 +192,23 @@ class PlotAC(PamhyrPlot):
self.data.profile(previous_id).get_station(),
self.data.profile(previous_id).z()
)
+ self.previous_plot_selected.set_visible(True)
if 0 <= profile_id < self.data.number_profiles:
self.plot_selected.set_data(
self.data.profile(profile_id).get_station(),
self.data.profile(profile_id).z()
)
+ self.plot_selected.set_visible(True)
if 0 <= next_id < self.data.number_profiles:
self.next_plot_selected.set_data(
self.data.profile(next_id).get_station(),
self.data.profile(next_id).z()
)
+ self.next_plot_selected.set_visible(True)
+
+ self.canvas.axes.set_visible(True)
def update_full(self):
self.draw()
diff --git a/src/View/Geometry/PlotKPZ.py b/src/View/Geometry/PlotKPZ.py
index 1c80af12..eed3542b 100644
--- a/src/View/Geometry/PlotKPZ.py
+++ b/src/View/Geometry/PlotKPZ.py
@@ -20,6 +20,11 @@ import logging
from tools import timer
from View.Tools.PamhyrPlot import PamhyrPlot
+from PyQt5.QtWidgets import QApplication
+from PyQt5.QtCore import (
+ Qt, QItemSelectionModel,
+ QItemSelection, QItemSelectionRange,
+)
logger = logging.getLogger()
@@ -27,7 +32,7 @@ logger = logging.getLogger()
class PlotKPZ(PamhyrPlot):
def __init__(self, canvas=None, trad=None,
study=None, data=None, toolbar=None,
- parent=None):
+ table=None, parent=None):
self._study = study
super(PlotKPZ, self).__init__(
@@ -35,6 +40,7 @@ class PlotKPZ(PamhyrPlot):
trad=trad,
data=data,
toolbar=toolbar,
+ table=table,
parent=parent
)
@@ -51,6 +57,111 @@ class PlotKPZ(PamhyrPlot):
self.before_plot_selected = None
self.plot_selected = None
self.after_plot_selected = None
+ self.parent = parent
+ self._table = table
+ self._colors = []
+
+ def onpick(self, event):
+ if event.mouseevent.inaxes != self.canvas.axes:
+ return
+ if event.mouseevent.button.value != 1:
+ return
+
+ modifiers = QApplication.keyboardModifiers()
+ if modifiers not in [Qt.ControlModifier,
+ Qt.NoModifier,
+ Qt.ShiftModifier]:
+ return
+
+ ind, point = self._closest_kp(event)
+ if self.parent._table is None:
+ return
+ self.parent._table.blockSignals(True)
+ if modifiers == Qt.ControlModifier:
+ rows = list(
+ set(
+ (i.row() for i in self.parent.tableView.selectedIndexes())
+ )
+ )
+ if ind in rows:
+ rows.remove(ind)
+ else:
+ rows.append(ind)
+ self._select_in_table(rows)
+ elif modifiers == Qt.ShiftModifier:
+ rows = sorted(list(
+ set(
+ (i.row() for i in self.parent.tableView.selectedIndexes())
+ )
+ ))
+ if len(rows) > 0:
+ i1 = min(rows[0], rows[-1], ind)
+ i2 = max(rows[0], rows[-1], ind)
+ else:
+ i1 = ind
+ i2 = ind
+ self._select_range_in_table(i1, i2)
+ else:
+ self._select_in_table([ind])
+ self.parent._table.blockSignals(False)
+
+ return
+
+ def _closest_kp(self, event):
+
+ s = event.artist.get_segments()
+ x = [i[0, 0] for i in s]
+ mx = event.mouseevent.xdata
+ points = enumerate(x)
+
+ def dist_mouse(point):
+ x = point[1]
+ d = abs(mx - x)
+ return d
+
+ closest = min(
+ points, key=dist_mouse
+ )
+
+ return closest
+
+ def _select_in_table(self, ind):
+ if self._table is None:
+ return
+
+ self._table.setFocus()
+ selection = self._table.selectionModel()
+ index = QItemSelection()
+
+ if len(ind) == 0:
+ return
+
+ for i in ind:
+ index.append(QItemSelectionRange(self._table.model().index(i, 0)))
+
+ selection.select(
+ index,
+ QItemSelectionModel.Rows |
+ QItemSelectionModel.ClearAndSelect |
+ QItemSelectionModel.Select
+ )
+
+ if len(ind) > 0:
+ self._table.scrollTo(self._table.model().index(ind[-1], 0))
+
+ def _select_range_in_table(self, ind1, ind2):
+ if self._table is not None:
+ self._table.setFocus()
+ selection = self._table.selectionModel()
+ index = QItemSelection(self._table.model().index(ind1, 0),
+ self._table.model().index(ind2, 0))
+ selection.select(
+ index,
+ QItemSelectionModel.Rows |
+ QItemSelectionModel.ClearAndSelect |
+ QItemSelectionModel.Select
+ )
+ self._table.scrollTo(self._table.model().index(ind2, 0))
@timer
def draw(self):
@@ -74,8 +185,7 @@ class PlotKPZ(PamhyrPlot):
return
self.draw_z_line()
- self.draw_z_line_highlight()
- self.draw_current()
+ self.draw_lr()
self.draw_gl()
self.draw_bottom()
self.draw_profiles_hs(self._data)
@@ -88,76 +198,60 @@ class PlotKPZ(PamhyrPlot):
z_min = self.data.get_z_min()
z_max = self.data.get_z_max()
+ self._colors, self._style = self.color_hightlight()
+
self.line_kp_zmin_zmax = self.canvas.axes.vlines(
x=kp, ymin=z_min, ymax=z_max,
- color=self.color_plot,
- lw=1.
+ color=self._colors,
+ linestyle=self._style,
+ lw=1.,
+ picker=10,
)
- def draw_z_line_highlight(self):
- if self._highlight_data is not None:
- kp = self.data.get_kp_complete_profiles()
- z_min = self.data.get_z_min()
- z_max = self.data.get_z_max()
-
- kp_min, kp_max = self._highlight_data
-
- indexes = list(
- map(
- lambda x: x[0],
- filter(
- lambda x: kp_min <= x[1] <= kp_max,
- enumerate(kp)
- )
- )
+ def color_hightlight(self):
+ rows = sorted(list(
+ set(
+ (i.row() for i in self.parent.tableView.selectedIndexes())
)
+ ))
+ colors = [self.color_plot for row in range(len(self._data))]
+ style = ["-" for row in range(len(self._data))]
+ if len(rows) > 0:
+ for row in rows:
+ colors[row] = self.color_plot_current
+ if rows[0] > 0:
+ colors[rows[0]-1] = self.color_plot_previous
+ style[rows[0]-1] = "--"
+ if rows[-1] < len(self._data)-1:
+ colors[rows[-1]+1] = self.color_plot_next
+ style[rows[-1]+1] = "--"
+ return colors, style
- def indexes_filter(data): return list(
- map(
- lambda x: x[1],
- filter(
- lambda x: x[0] in indexes,
- enumerate(data)
- )
- )
- )
-
- ikp = indexes_filter(kp)
- imin = indexes_filter(z_min)
- imax = indexes_filter(z_max)
-
- self.line_kp_zmin_zmax_highlight = self.canvas.axes.vlines(
- x=ikp,
- ymin=imin, ymax=imax,
- color=self.color_plot_highlight,
- lw=1.
- )
-
- def draw_current(self):
+ def draw_lr(self):
kp = self.data.get_kp_complete_profiles()
- z_min = self.data.get_z_min()
- z_max = self.data.get_z_max()
+ lz = []
+ rz = []
- self.plot_selected, = self.canvas.axes.plot(
- (kp[0], kp[0]),
- (z_min[0], z_max[0]),
- color=self.color_plot_current, lw=1.5
- )
- self.plot_selected.set_visible(False)
+ self.line_lr = []
+ for z in self.data.get_z():
+ lz.append(z[0])
+ rz.append(z[-1])
- self.before_plot_selected, = self.canvas.axes.plot(
- (kp[0], kp[0]),
- (z_min[0], z_max[0]),
- color=self.color_plot_previous, lw=1.5, linestyle='--'
+ line = self.canvas.axes.plot(
+ kp, lz,
+ color=self.color_plot_river_bottom,
+ linestyle="dotted",
+ lw=1.,
)
- self.before_plot_selected.set_visible(False)
+ self.line_lr.append(line)
- self.after_plot_selected, = self.canvas.axes.plot(
- (kp[0], kp[0]),
- (z_min[0], z_max[0]),
- color=self.color_plot_next, lw=1.5, linestyle='--'
+ line = self.canvas.axes.plot(
+ kp, rz,
+ color=self.color_plot_river_bottom,
+ linestyle="dotted",
+ lw=1.,
)
- self.after_plot_selected.set_visible(False)
+ self.line_lr.append(line)
def draw_gl(self):
kp = self.data.get_kp_complete_profiles()
@@ -191,30 +285,34 @@ class PlotKPZ(PamhyrPlot):
def draw_profiles_hs(self, reach):
lhs = filter(
lambda hs: hs._input_reach.reach is reach,
- self._study.river.hydraulic_structures.lst
+ filter(
+ lambda hs: hs._input_reach is not None,
+ self._study.river.hydraulic_structures.lst
+ )
)
for hs in lhs:
x = hs.input_kp
- z_min = reach.get_z_min()
- z_max = reach.get_z_max()
+ if x is not None:
+ z_min = reach.get_z_min()
+ z_max = reach.get_z_max()
- self.canvas.axes.plot(
- [x, x],
- [min(z_min), max(z_max)],
- linestyle="--",
- lw=1.,
- color=self.color_plot_previous,
- )
+ self.canvas.axes.plot(
+ [x, x],
+ [min(z_min), max(z_max)],
+ linestyle="--",
+ lw=1.,
+ color=self.color_plot_previous,
+ )
- self.canvas.axes.annotate(
- " > " + hs.name,
- (x, max(z_max)),
- horizontalalignment='left',
- verticalalignment='top',
- annotation_clip=True,
- fontsize=9, color=self.color_plot_previous,
- )
+ self.canvas.axes.annotate(
+ " > " + hs.name,
+ (x, max(z_max)),
+ horizontalalignment='left',
+ verticalalignment='top',
+ annotation_clip=True,
+ fontsize=9, color=self.color_plot_previous,
+ )
@timer
def update(self):
@@ -222,6 +320,7 @@ class PlotKPZ(PamhyrPlot):
self.draw()
return
+ self.update_lr()
self.update_gl()
self.update_current()
@@ -229,52 +328,9 @@ class PlotKPZ(PamhyrPlot):
def update_current(self):
if self._current_data_update:
- ind = self._current_data
- before = ind - 1
- after = ind + 1
-
- self.before_plot_selected.set_visible(False)
- self.plot_selected.set_visible(False)
- self.after_plot_selected.set_visible(False)
-
- if 0 <= before < self.data.number_profiles:
- profile = self.data.profile(before)
- if len(profile) > 0:
- kp_i = profile.kp
- z_min_i = profile.z_min()
- z_max_i = profile.z_max()
-
- self.before_plot_selected.set_data(
- (kp_i, kp_i),
- (z_min_i, z_max_i)
- )
- self.before_plot_selected.set_visible(True)
-
- if 0 <= ind < self.data.number_profiles:
- profile = self.data.profile(ind)
- if len(profile) > 0:
- kp_i = profile.kp
- z_min_i = profile.z_min()
- z_max_i = profile.z_max()
-
- self.plot_selected.set_data(
- (kp_i, kp_i),
- (z_min_i, z_max_i)
- )
- self.plot_selected.set_visible(True)
-
- if 0 <= after < self.data.number_profiles:
- profile = self.data.profile(after)
- if len(profile) > 0:
- kp_i = profile.kp
- z_min_i = profile.z_min()
- z_max_i = profile.z_max()
-
- self.after_plot_selected.set_data(
- (kp_i, kp_i),
- (z_min_i, z_max_i)
- )
- self.after_plot_selected.set_visible(True)
+ self._colors, self._style = self.color_hightlight()
+ self.line_kp_zmin_zmax.set_colors(self._colors)
+ self.line_kp_zmin_zmax.set_linestyle(self._style)
def update_gl(self):
if self._current_data_update:
@@ -286,12 +342,19 @@ class PlotKPZ(PamhyrPlot):
self.line_kp_zmin.set_data(kp, z_min)
- self.line_kp_zmin_zmax.remove()
- self.line_kp_zmin_zmax = self.canvas.axes.vlines(
- x=kp,
- ymin=z_min, ymax=z_max,
- color='r', lw=1.
- )
+# TODO comprendre à quoi sert ce bout de code
+# ========>
+# self.line_kp_zmin_zmax.remove()
+# self._colors, self._style = self.color_hightlight()
+# self.line_kp_zmin_zmax = self.canvas.axes.vlines(
+# x=kp,
+# ymin=z_min,
+# ymax=z_max,
+# color=self._colors,
+# linestyle = self._style,
+# lw=1.
+# )
+# <========
z_complete = self.data.get_guidelines_z()
try:
@@ -301,3 +364,9 @@ class PlotKPZ(PamhyrPlot):
)
except Exception as e:
logger.warning(f"Failed to update graphic KPZ: {e}")
+
+ def update_lr(self):
+ for line in self.line_lr:
+ line[0].remove()
+
+ self.draw_lr()
diff --git a/src/View/Geometry/PlotXY.py b/src/View/Geometry/PlotXY.py
index baa46d26..548b7ee0 100644
--- a/src/View/Geometry/PlotXY.py
+++ b/src/View/Geometry/PlotXY.py
@@ -18,22 +18,27 @@
from tools import timer, trace
from View.Tools.PamhyrPlot import PamhyrPlot
+from matplotlib import collections
+import numpy as np
from PyQt5.QtCore import (
- QCoreApplication
+ QCoreApplication, Qt, QItemSelectionModel,
+ QItemSelection, QItemSelectionRange,
)
+from PyQt5.QtWidgets import QApplication
_translate = QCoreApplication.translate
class PlotXY(PamhyrPlot):
def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
- parent=None):
+ table=None, parent=None):
super(PlotXY, self).__init__(
canvas=canvas,
trad=trad,
data=data,
toolbar=toolbar,
+ table=table,
parent=parent
)
@@ -46,6 +51,116 @@ class PlotXY(PamhyrPlot):
self.before_plot_selected = None
self.plot_selected = None
self.after_plot_selected = None
+ self.parent = parent
+ self.line_xy_collection = None
+ self._table = table
+ self._colors = []
+ self._style = []
+
+ def onpick(self, event):
+ if event.mouseevent.inaxes != self.canvas.axes:
+ return
+ if event.mouseevent.button.value != 1:
+ return
+
+ modifiers = QApplication.keyboardModifiers()
+ if modifiers not in [Qt.ControlModifier,
+ Qt.NoModifier,
+ Qt.ShiftModifier]:
+ return
+
+ ind, point = self._closest_section(event)
+ if self._table is None:
+ return
+ self._table.blockSignals(True)
+ if modifiers == Qt.ControlModifier:
+ rows = list(
+ set(
+ (i.row() for i in self.parent.tableView.selectedIndexes())
+ )
+ )
+ if ind in rows:
+ rows.remove(ind)
+ self._select_in_table(rows)
+ else:
+ self._select_in_table(rows + [ind])
+ elif modifiers == Qt.ShiftModifier:
+ rows = list(
+ set(
+ (i.row() for i in self.parent.tableView.selectedIndexes())
+ )
+ )
+ if len(rows) > 0:
+ i1 = min(rows[0], rows[-1], ind)
+ i2 = max(rows[0], rows[-1], ind)
+ else:
+ i1 = ind
+ i2 = ind
+ self._select_range_in_table(i1, i2)
+ else:
+ self._select_in_table([ind])
+ self._table.blockSignals(False)
+
+ return
+
+ def _closest_section(self, event):
+ axes = self.canvas.axes
+ mx = event.mouseevent.xdata
+ my = event.mouseevent.ydata
+ bx, by = axes.get_xlim(), axes.get_ylim()
+ ratio = (bx[0] - bx[1]) / (by[0] - by[1])
+
+ segments = event.artist.get_segments()
+ ind = event.ind
+
+ points = []
+ for i in ind:
+ points = points + [[i, j] for j in segments[i]]
+
+ def dist_mouse(point):
+ x, y = point[1]
+ d2 = (((mx - x) / ratio) ** 2) + ((my - y) ** 2)
+ return d2
+
+ closest = min(
+ points, key=dist_mouse
+ )
+
+ return closest
+
+ def _select_in_table(self, ind):
+ if self._table is None:
+ return
+ self._table.setFocus()
+ selection = self._table.selectionModel()
+ index = QItemSelection()
+ if len(ind) == 0:
+ return
+ for i in ind:
+ index.append(QItemSelectionRange(self._table.model().index(i, 0)))
+ selection.select(
+ index,
+ QItemSelectionModel.Rows |
+ QItemSelectionModel.ClearAndSelect |
+ QItemSelectionModel.Select
+ )
+
+ if len(ind) > 0:
+ self._table.scrollTo(self._table.model().index(ind[-1], 0))
+
+ def _select_range_in_table(self, ind1, ind2):
+ if self._table is not None:
+ self._table.setFocus()
+ selection = self._table.selectionModel()
+ index = QItemSelection(self._table.model().index(ind1, 0),
+ self._table.model().index(ind2, 0))
+ selection.select(
+ index,
+ QItemSelectionModel.Rows |
+ QItemSelectionModel.ClearAndSelect |
+ QItemSelectionModel.Select
+ )
+ self._table.scrollTo(self._table.model().index(ind2, 0))
@timer
def draw(self):
@@ -63,33 +178,42 @@ class PlotXY(PamhyrPlot):
self.draw_xy()
self.draw_lr()
self.draw_gl()
- self.draw_current()
self.idle()
self._init = True
def draw_xy(self):
- kp = self.data.get_kp_complete_profiles()
-
- kp_min, kp_max = (-1, -1)
- if self._highlight_data is not None:
- kp_min, kp_max = self._highlight_data
-
- def color_hightlight(kp):
- if kp_min <= kp <= kp_max:
- return self.color_plot_highlight
- return self.color_plot
-
self.line_xy = []
- for x, y, kp in zip(self.data.get_x(),
- self.data.get_y(),
- kp):
- line = self.canvas.axes.plot(
- x, y,
- color=color_hightlight(kp),
- **self.plot_default_kargs
+ for xy in zip(self.data.get_x(), self.data.get_y()):
+ self.line_xy.append(np.column_stack(xy))
+
+ self._colors, self._style = self.color_hightlight()
+ self.line_xy_collection = collections.LineCollection(
+ self.line_xy,
+ colors=self._colors,
+ linestyle=self._style,
+ picker=10
+ )
+ self.canvas.axes.add_collection(self.line_xy_collection)
+
+ def color_hightlight(self):
+ rows = sorted(list(
+ set(
+ (i.row() for i in self.parent.tableView.selectedIndexes())
)
- self.line_xy.append(line)
+ ))
+ colors = [self.color_plot for row in range(len(self._data))]
+ style = ["-" for row in range(len(self._data))]
+ if len(rows) > 0:
+ for row in rows:
+ colors[row] = self.color_plot_current
+ if rows[0] > 0:
+ colors[rows[0]-1] = self.color_plot_previous
+ style[rows[0]-1] = "--"
+ if rows[-1] < len(self._data)-1:
+ colors[rows[-1]+1] = self.color_plot_next
+ style[rows[-1]+1] = "--"
+ return colors, style
def draw_lr(self):
lx = []
@@ -136,33 +260,6 @@ class PlotXY(PamhyrPlot):
self.line_gl.append(line)
ind += 1
- def draw_current(self):
- # Previous profile
- self.before_plot_selected, = self.canvas.axes.plot(
- self.data.profile(0).x(),
- self.data.profile(0).y(),
- color=self.color_plot_previous, linestyle="--",
- **self.plot_default_kargs
- )
- self.before_plot_selected.set_visible(False)
-
- # Current profile
- self.plot_selected, = self.canvas.axes.plot(
- self.data.profile(0).x(),
- self.data.profile(0).y(),
- color=self.color_plot_current, **self.plot_default_kargs
- )
- self.plot_selected.set_visible(False)
-
- # Next profile
- self.after_plot_selected, = self.canvas.axes.plot(
- self.data.profile(0).x(),
- self.data.profile(0).y(),
- color=self.color_plot_next, linestyle='--',
- **self.plot_default_kargs
- )
- self.after_plot_selected.set_visible(False)
-
@timer
def update(self):
if not self._init:
@@ -183,21 +280,24 @@ class PlotXY(PamhyrPlot):
x_complete = list(self.data.get_guidelines_x())
y_complete = list(self.data.get_guidelines_y())
- for i in range(self.data.number_profiles):
- if i < len(self.line_xy):
- self.line_xy[i][0].set_data(
- self.data.profile(i).x(),
- self.data.profile(i).y()
- )
- else:
- self.line_xy.append(
- self.canvas.axes.plot(
- self.data.profile(i).x(),
- self.data.profile(i).y(),
- color='r',
- **self.plot_default_kargs
- )
- )
+# TODO comprendre à quoi sert ce bout de code
+# ========>
+# for i in range(self.data.number_profiles):
+# if i < len(self.line_xy):
+# self.line_xy[i][0].set_data(
+# self.data.profile(i).x(),
+# self.data.profile(i).y()
+# )
+# else:
+# self.line_xy.append(
+# self.canvas.axes.plot(
+# self.data.profile(i).x(),
+# self.data.profile(i).y(),
+# color='r',
+# **self.plot_default_kargs
+# )
+# )
+# <========
for i in range(len(x_complete)):
if i < len(self.line_gl):
@@ -215,32 +315,9 @@ class PlotXY(PamhyrPlot):
def update_current(self):
if self._current_data_update:
- ind = self._current_data
- before = ind - 1
- after = ind + 1
-
- self.before_plot_selected.set_visible(False)
- self.plot_selected.set_visible(False)
- self.after_plot_selected.set_visible(False)
-
- if 0 <= before < self.data.number_profiles:
- self.before_plot_selected.set_data(
- self.data.profile(before).x(),
- self.data.profile(before).y()
- )
- self.before_plot_selected.set_visible(True)
-
- if 0 <= ind < self.data.number_profiles:
- self.plot_selected.set_data(self.data.profile(ind).x(),
- self.data.profile(ind).y())
- self.plot_selected.set_visible(True)
-
- if 0 <= after < self.data.number_profiles:
- self.after_plot_selected.set_data(
- self.data.profile(after).x(),
- self.data.profile(after).y()
- )
- self.after_plot_selected.set_visible(True)
+ self._colors, self._style = self.color_hightlight()
+ self.line_xy_collection.set_colors(self._colors)
+ self.line_xy_collection.set_linestyle(self._style)
def update_lr(self):
for line in self.line_lr:
diff --git a/src/View/Geometry/Profile/Plot.py b/src/View/Geometry/Profile/Plot.py
index 5f488592..ee91ca17 100644
--- a/src/View/Geometry/Profile/Plot.py
+++ b/src/View/Geometry/Profile/Plot.py
@@ -24,10 +24,12 @@ from tools import timer, trace
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
- Qt, QCoreApplication, QItemSelectionModel
+ Qt, QCoreApplication, QItemSelectionModel,
+ QItemSelection, QItemSelectionRange,
)
from PyQt5.QtWidgets import QApplication
+from matplotlib.widgets import RectangleSelector
_translate = QCoreApplication.translate
@@ -46,6 +48,7 @@ class Plot(PamhyrPlot):
)
self._table = table
+ self._parent = parent
self._z_note = None
self._z_line = None
self._z_fill_between = None
@@ -68,40 +71,86 @@ class Plot(PamhyrPlot):
None # Hydrolic values (z, wet_area,
# wet_preimeter, water_width)
)
+ self._onpickevent = None
+ self._rect_select = RectangleSelector(
+ ax=self.canvas.axes,
+ onselect=self.rect_select_callback,
+ useblit=True,
+ button=[1], # don't use middle nor right button
+ minspanx=2.0,
+ minspany=2.0,
+ spancoords='pixels',
+ interactive=False
+ )
+
+ def onrelease(self, event):
+ # we need to do that to prevent conflicst
+ # between onpick and rect_select_callback
+ modifiers = QApplication.keyboardModifiers()
+ points, hyd = self.highlight
+ if self._onpickevent is not None:
+ ind, point = self._closest_point(self._onpickevent)
+ if modifiers == Qt.ControlModifier:
+ rows = self._parent.index_selected_rows()
+ if ind in rows:
+ rows.remove(ind)
+ del (points[ind])
+ self.highlight = (points, hyd)
+ self._select_in_table(rows)
+ else:
+ self.highlight = (points+[point], hyd)
+ self._select_in_table(rows+[ind])
+ elif modifiers == Qt.ShiftModifier:
+ rows = self._parent.index_selected_rows()
+ if len(rows) > 0:
+ i1 = min(rows[0], rows[-1], ind)
+ i2 = max(rows[0], rows[-1], ind)
+ p = [
+ [self.data.points[i].x, self.data.points[i].y]
+ for i in range(i1, i2)
+ ]
+ else:
+ i1 = ind
+ i2 = ind
+ p = [point]
+ self.highlight = (p, hyd)
+ self._select_range_in_table(i1, i2)
+ else:
+ self.highlight = ([point], hyd)
+ self._select_in_table([ind])
+
+ self._onpickevent = None
def onpick(self, event):
if event.mouseevent.inaxes != self.canvas.axes:
return
-
- modifiers = QApplication.keyboardModifiers()
- if modifiers != Qt.ControlModifier:
+ if event.mouseevent.button.value != 1:
return
- _, hyd = self.highlight
+ modifiers = QApplication.keyboardModifiers()
+ if modifiers not in [Qt.ControlModifier,
+ Qt.NoModifier,
+ Qt.ShiftModifier]:
+ return
- ind, point = self._closer_point(event)
-
- self.highlight = ([point], hyd)
- self._select_in_table(ind)
-
- self.update()
+ self._onpickevent = event
return
def onclick(self, event):
if event.inaxes != self.canvas.axes:
return
-
- modifiers = QApplication.keyboardModifiers()
- if modifiers != Qt.ShiftModifier:
+ if event.button.value == 1:
return
points, _ = self.highlight
z = self._get_z_from_click(event)
- if z < self.data.z_min():
+ if z < self.data.z_min() or event.button.value == 2:
+ self.highlight = (points, None)
+ self.update()
return
- a, p, w = self._compute_hydrolics(z)
+ a, p, w = self._compute_hydraulics(z)
logger.debug(f"{z, a, p, w}")
@@ -110,7 +159,7 @@ class Plot(PamhyrPlot):
self.update()
return
- def select_points_from_indexes(self, indexes):
+ def select_points_from_indices(self, indices):
data = self.data
_, hyd = self.highlight
@@ -118,7 +167,7 @@ class Plot(PamhyrPlot):
map(
lambda e: e[1],
filter(
- lambda e: e[0] in indexes,
+ lambda e: e[0] in indices,
enumerate(
zip(data.get_station(), data.z())
)
@@ -133,9 +182,13 @@ class Plot(PamhyrPlot):
if self._table is not None:
self._table.blockSignals(True)
self._table.setFocus()
-
selection = self._table.selectionModel()
- index = self._table.model().index(ind, 0)
+ index = QItemSelection()
+ if len(ind) > 0:
+ for i in ind:
+ index.append(QItemSelectionRange(
+ self._table.model().index(i, 0))
+ )
selection.select(
index,
QItemSelectionModel.Rows |
@@ -143,10 +196,27 @@ class Plot(PamhyrPlot):
QItemSelectionModel.Select
)
- self._table.scrollTo(index)
+ if len(ind) > 0:
+ self._table.scrollTo(self._table.model().index(ind[-1], 0))
self._table.blockSignals(False)
- def _closer_point(self, event):
+ def _select_range_in_table(self, ind1, ind2):
+ if self._table is not None:
+ self._table.blockSignals(True)
+ self._table.setFocus()
+ selection = self._table.selectionModel()
+ index = QItemSelection(self._table.model().index(ind1, 0),
+ self._table.model().index(ind2, 0))
+ selection.select(
+ index,
+ QItemSelectionModel.Rows |
+ QItemSelectionModel.ClearAndSelect |
+ QItemSelectionModel.Select
+ )
+ self._table.scrollTo(self._table.model().index(ind2, 0))
+ self._table.blockSignals(False)
+
+ def _closest_point(self, event):
points_ind = event.ind
axes = self.canvas.axes
bx, by = axes.get_xlim(), axes.get_ylim()
@@ -166,22 +236,62 @@ class Plot(PamhyrPlot):
def dist_mouse(point):
x, y = point[1]
- d = sqrt(
- (((mx - x) / ratio) ** 2) +
- ((my - y) ** 2)
- )
- return d
+ d2 = ((mx - x) / ratio) ** 2 + ((my - y) ** 2)
+ return d2
- closer = min(
+ closest = min(
points, key=dist_mouse
)
- return closer
+ return closest
def _get_z_from_click(self, event):
return event.ydata
- def _compute_hydrolics(self, z):
+ def rect_select_callback(self, eclick, erelease):
+
+ points, hyd = self.highlight
+ x1, y1 = eclick.xdata, eclick.ydata
+ x2, y2 = erelease.xdata, erelease.ydata
+
+ if (max(abs(x1-x2), abs(y1-y2)) < 0.001):
+ return
+ modifiers = QApplication.keyboardModifiers()
+
+ x1, y1 = eclick.xdata, eclick.ydata
+ x2, y2 = erelease.xdata, erelease.ydata
+
+ inds, points2 = self._points_in_rectangle(x1, y1, x2, y2)
+ self._onclickevent = None
+ if modifiers == Qt.ControlModifier:
+ rows = self._parent.index_selected_rows()
+ if all(i in rows for i in inds):
+ for ind in sorted(inds, reverse=True):
+ rows.remove(ind)
+ del (points[ind])
+ self.highlight = (points, hyd)
+ self._select_in_table(rows)
+ else:
+ self.highlight = (points+points2, hyd)
+ self._select_in_table(rows+inds)
+ else:
+ self.highlight = (points2, hyd)
+ self._select_in_table(inds)
+ return
+
+ def _points_in_rectangle(self, x1, y1, x2, y2):
+ # TODO: use lambdas
+ listi = []
+ listp = []
+ station = self.data._get_station(self.data.points)
+ for i, p in enumerate(self.data.points):
+ if (min(x1, x2) < station[i] < max(x1, x2)
+ and min(y1, y2) < p.z < max(y1, y2)):
+ listi.append(i)
+ listp.append((station[i], p.z))
+ return listi, listp
+
+ def _compute_hydraulics(self, z):
profile = self.data
points = profile.wet_points(z)
@@ -210,7 +320,7 @@ class Plot(PamhyrPlot):
self.profile_line2D, = self.canvas.axes.plot(
x, y, color=self.color_plot,
lw=1.5, markersize=7, marker='+',
- picker=30
+ picker=10
)
self.draw_annotation(x, y)
@@ -269,12 +379,16 @@ class Plot(PamhyrPlot):
x, y,
color=self.color_plot_highlight,
lw=1.5, markersize=7, marker='+',
- picker=30
)
)
if hyd is not None:
self.draw_highligth_z_line(*hyd)
+ else:
+ if self._z_note is not None:
+ self._z_note.set_visible(False)
+ self._z_line[0].set_visible(False)
+ self._z_fill_between.set_visible(False)
def draw_highligth_z_line(self, z, a, p, w):
text = (
@@ -299,6 +413,7 @@ class Plot(PamhyrPlot):
xlim, [z, z],
color=self.color_plot_river_water
)
+ self._z_line[0].set_visible(True)
self._z_note = self.canvas.axes.annotate(
text, pos,
@@ -310,12 +425,15 @@ class Plot(PamhyrPlot):
fontweight='bold',
alpha=0.7
)
+ self._z_note.set_visible(True)
else:
self.draw_highligth_z_line_fill(x, y, z)
self._z_line[0].set_data(xlim, [z, z])
self._z_note.set_position(pos)
self._z_note.set_text(text)
+ self._z_line[0].set_visible(True)
+ self._z_note.set_visible(True)
def draw_highligth_z_line_fill(self, x, y, z):
if self._z_fill_between is not None:
diff --git a/src/View/Geometry/Profile/Table.py b/src/View/Geometry/Profile/Table.py
index 21e202f8..141545fa 100644
--- a/src/View/Geometry/Profile/Table.py
+++ b/src/View/Geometry/Profile/Table.py
@@ -82,16 +82,6 @@ class GeometryProfileTableModel(PamhyrTableModel):
elif value == self._data.z_max():
return QColor("blue")
- if role == Qt.ToolTipRole:
- if value == self._data.z_min():
- return _translate("MainWindowProfile",
- "La cote du fond",
- "Z minimale")
- elif value == self._data.z_max():
- return _translate("MainWindowProfile",
- "La cote maximale",
- "Z maximale")
-
if index.column() == 3:
value = self._data.point(index.row()).name
@@ -104,16 +94,6 @@ class GeometryProfileTableModel(PamhyrTableModel):
if role == Qt.ForegroundRole:
return QColor("darkRed")
- if role == Qt.ToolTipRole:
- if value.strip().upper() == "RG":
- return _translate(
- "MainWindowProfile", "Rive gauche"
- )
- else:
- return _translate(
- "MainWindowProfile", "Rive droite"
- )
-
return QVariant()
def setData(self, index, value, role=Qt.EditRole):
@@ -250,11 +230,11 @@ class GeometryProfileTableModel(PamhyrTableModel):
self.endMoveRows()
self.layoutChanged.emit()
- def purge(self):
+ def purge(self, np_purge):
self._undo.push(
PurgeCommand(
- self._data, 24
+ self._data, np_purge
)
)
diff --git a/src/View/Geometry/Profile/Window.py b/src/View/Geometry/Profile/Window.py
index 655096d7..6e0e5c15 100644
--- a/src/View/Geometry/Profile/Window.py
+++ b/src/View/Geometry/Profile/Window.py
@@ -20,8 +20,9 @@ import copy
import sys
import csv
from time import time
+import logging
-from tools import trace, timer
+from tools import trace, timer, logger_exception
from Modules import Modules
from PyQt5.QtGui import (
@@ -46,9 +47,12 @@ from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Geometry.Profile.Plot import Plot
from View.Geometry.Profile.Table import GeometryProfileTableModel
from View.Geometry.Profile.Translate import GeometryProfileTranslate
+from View.Geometry.PurgeDialog import PurgeDialog
_translate = QCoreApplication.translate
+logger = logging.getLogger()
+
class ProfileWindow(PamhyrWindow):
_pamhyr_ui = "GeometryCrossSection"
@@ -111,7 +115,8 @@ class ProfileWindow(PamhyrWindow):
data=self._profile,
trad=self._trad,
toolbar=self._toolbar,
- table=self.find(QTableView, "tableView")
+ table=self.find(QTableView, "tableView"),
+ parent=self
)
self._plot.draw()
@@ -142,7 +147,7 @@ class ProfileWindow(PamhyrWindow):
def update_points_selection(self):
rows = self.index_selected_rows()
- self._plot.select_points_from_indexes(rows)
+ self._plot.select_points_from_indices(rows)
def update(self):
self.update_plot()
@@ -165,7 +170,6 @@ class ProfileWindow(PamhyrWindow):
if Modules.GEOMETRY not in key:
return
- logger.debug("TOTO")
self._tablemodel.layoutChanged.emit()
self._update(redraw=True, propagate=False)
@@ -258,6 +262,19 @@ class ProfileWindow(PamhyrWindow):
self._tablemodel.purge()
self.update()
+ def purge(self):
+ try:
+ dlg = PurgeDialog(
+ trad=self._trad,
+ parent=self
+ )
+ if dlg.exec():
+ self._tablemodel.purge(dlg.np_purge)
+ self._plot.draw()
+ except Exception as e:
+ logger_exception(e)
+ return
+
def reverse(self):
self._tablemodel.reverse()
self.update()
diff --git a/src/View/Geometry/PurgeDialog.py b/src/View/Geometry/PurgeDialog.py
new file mode 100644
index 00000000..af4fcc34
--- /dev/null
+++ b/src/View/Geometry/PurgeDialog.py
@@ -0,0 +1,60 @@
+# PurgeDialog.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 .
+
+# -*- 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 (
+ QUndoStack, QShortcut, QSpinBox,
+)
+
+
+class PurgeDialog(PamhyrDialog):
+ _pamhyr_ui = "PurgeOptions"
+ _pamhyr_name = "Purge"
+
+ def __init__(self, trad=None, parent=None):
+ super(PurgeDialog, self).__init__(
+ title=trad[self._pamhyr_name],
+ trad=trad,
+ options=[],
+ parent=parent
+ )
+
+ self._init_default_values()
+
+ def _init_default_values(self):
+ self._np_purge = 24
+
+ @property
+ def np_purge(self):
+ return self._np_purge
+
+ def accept(self):
+ self._np_purge = self.get_spin_box("spinBox_np_purge")
+ super().accept()
+
+ def reject(self):
+ self.close()
diff --git a/src/View/Geometry/Table.py b/src/View/Geometry/Table.py
index 3c5db448..4009af87 100644
--- a/src/View/Geometry/Table.py
+++ b/src/View/Geometry/Table.py
@@ -259,11 +259,11 @@ class GeometryReachTableModel(PamhyrTableModel):
self.layoutAboutToBeChanged.emit()
self.layoutChanged.emit()
- def purge(self):
+ def purge(self, np_purge):
self._undo.push(
PurgeCommand(
- self._data, 24
+ self._data, np_purge
)
)
self.layoutChanged.emit()
diff --git a/src/View/Geometry/Translate.py b/src/View/Geometry/Translate.py
index ec8c451a..85348ded 100644
--- a/src/View/Geometry/Translate.py
+++ b/src/View/Geometry/Translate.py
@@ -33,12 +33,12 @@ class GeometryTranslate(MainTranslate):
self._dict["open_file"] = _translate("Geometry", "Open a file")
self._dict["file_st"] = _translate(
- "Geometry", "File mage geometry (*.ST *.st)")
+ "Geometry", "Mage geometry file (*.ST *.st)")
self._dict["file_m"] = _translate(
- "Geometry", "File mage meshed geometry (*.M *.m)")
+ "Geometry", "Mage meshed geometry file (*.M *.m)")
self._dict["file_shp"] = _translate(
"Geometry", "Shapefile (*.SHP *.shp)")
- self._dict["file_all"] = _translate("Geometry", "All file (*)")
+ self._dict["file_all"] = _translate("Geometry", "All files (*)")
self._dict["cross_section"] = _translate("Geometry", "cross-section")
self._dict["cross_sections"] = _translate("Geometry", "cross-sections")
@@ -70,7 +70,7 @@ class GeometryTranslate(MainTranslate):
"2": _translate("Geometry", "the second guide-line"),
"3": _translate(
"Geometry",
- "the means between the two guide-lines"
+ "the mean over the two guide-lines"
),
}
diff --git a/src/View/Geometry/UpdateKPDialog.py b/src/View/Geometry/UpdateKPDialog.py
index 87afc977..1042e37a 100644
--- a/src/View/Geometry/UpdateKPDialog.py
+++ b/src/View/Geometry/UpdateKPDialog.py
@@ -1,4 +1,4 @@
-# MeshingDialog.py -- Pamhyr
+# UpdateKPDialog.py -- Pamhyr
# Copyright (C) 2023-2024 INRAE
#
# This program is free software: you can redistribute it and/or modify
@@ -28,7 +28,7 @@ from PyQt5.QtCore import (
from PyQt5.QtWidgets import (
QDialogButtonBox, QComboBox, QUndoStack, QShortcut,
- QDoubleSpinBox,
+ QDoubleSpinBox, QButtonGroup,
)
@@ -50,14 +50,20 @@ class UpdateKPDialog(PamhyrDialog):
self._init_default_values()
def _init_default_values(self):
- self._space_step = 50.0
- self._lplan = False
- self._lm = "3"
- self._linear = False
- self._begin_cs = -1
- self._end_cs = -1
+ gl, _ = self._reach.compute_guidelines()
+ self._gl = list(gl)
+
self._begin_dir = "un"
self._end_dir = "np"
+
+ lower_gl = list(map(str.lower, self._gl))
+ for i, gl in enumerate(lower_gl):
+ if gl == "rd":
+ self._begin_dir = self._gl[i]
+ elif gl == "rg":
+ self._end_dir = self._gl[i]
+
+ self._orientation = 0
self._origin = self._reach.profile(0)
self._origin_value = self._reach.profile(0).kp
@@ -69,8 +75,19 @@ class UpdateKPDialog(PamhyrDialog):
self.combobox_add_items("comboBox_origin", profiles)
- self.find(QComboBox, "comboBox_origin").currentIndexChanged.connect(
- self.changed_profile)
+ self.find(QComboBox, "comboBox_origin")\
+ .currentIndexChanged\
+ .connect(
+ self.changed_profile
+ )
+
+ buttonbox = self.find(QButtonGroup, "buttonGroup_orientation")
+
+ for button in buttonbox.buttons():
+ name = button.objectName()
+ i = int(name.split('_')[-1])
+
+ buttonbox.setId(button, i)
def changed_profile(self):
origin = self.get_combobox_text("comboBox_origin")
@@ -102,11 +119,8 @@ class UpdateKPDialog(PamhyrDialog):
return name
def _init_default_values_guidelines(self):
- gl, _ = self._reach.compute_guidelines()
- gl = list(gl)
-
- bgl = ['un'] + gl + ['np']
- egl = ['un'] + gl + ['np']
+ bgl = ['un'] + self._gl + ['np']
+ egl = ['un'] + self._gl + ['np']
self.combobox_add_items("comboBox_begin_gl", bgl)
self.combobox_add_items("comboBox_end_gl", egl)
@@ -114,6 +128,10 @@ class UpdateKPDialog(PamhyrDialog):
self.set_combobox_text("comboBox_begin_gl", self._begin_dir)
self.set_combobox_text("comboBox_end_gl", self._end_dir)
+ @property
+ def orientation(self):
+ return self._orientation
+
@property
def origin(self):
return self._origin
@@ -133,11 +151,12 @@ class UpdateKPDialog(PamhyrDialog):
def accept(self):
origin = self.get_combobox_text("comboBox_origin")
self._origin = self.profiles.index(origin)
-
self._origin_value = self.get_double_spin_box("doubleSpinBox_origin")
-
self._begin_dir = self.get_combobox_text("comboBox_begin_gl")
self._end_dir = self.get_combobox_text("comboBox_end_gl")
+ self._orientation = self.get_checked_id_button_group(
+ "buttonGroup_orientation"
+ )
super().accept()
diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py
index 65ffb8f5..bbc4ba12 100644
--- a/src/View/Geometry/Window.py
+++ b/src/View/Geometry/Window.py
@@ -36,7 +36,7 @@ from PyQt5.QtCore import (
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QFileDialog, QCheckBox,
QUndoStack, QShortcut, QTableView, QHeaderView,
- QAction, QSlider, QPushButton, QVBoxLayout,
+ QAction, QPushButton, QVBoxLayout,
QLabel, QAbstractItemView,
)
@@ -57,6 +57,7 @@ from View.Geometry.PlotAC import PlotAC
from View.Geometry.PlotKPZ import PlotKPZ
from View.Geometry.MeshingDialog import MeshingDialog
from View.Geometry.UpdateKPDialog import UpdateKPDialog
+from View.Geometry.PurgeDialog import PurgeDialog
from View.Geometry.Translate import GeometryTranslate
from View.Geometry.Profile.Window import ProfileWindow
@@ -96,7 +97,6 @@ class GeometryWindow(PamhyrWindow):
self.setup_plots()
self.setup_statusbar()
self.setup_connections()
- self.changed_slider_value()
def setup_table(self):
table_headers = self._trad.get_dict("table_headers")
@@ -157,6 +157,9 @@ class GeometryWindow(PamhyrWindow):
def _compute_status_label(self):
row = self.index_selected_row()
+ if row is None:
+ return
+
profile = self._reach.profile(row)
name = profile.name + " " + str(profile.kp)
@@ -197,13 +200,6 @@ class GeometryWindow(PamhyrWindow):
self.find(QAction, action)\
.triggered.connect(actions[action])
- self.find(QSlider, "verticalSlider").valueChanged.connect(
- self.changed_slider_value)
- self.find(QPushButton, "pushButton_up").clicked.connect(
- self.decrement_value_slider)
- self.find(QPushButton, "pushButton_down").clicked.connect(
- self.increment_value_slider)
-
# Profile selection when line change in table
self.find(QTableView, "tableView").selectionModel()\
.selectionChanged\
@@ -224,7 +220,6 @@ class GeometryWindow(PamhyrWindow):
self._plot_ac.draw()
self.select_current_profile()
- self.changed_slider_value()
if propagate:
self._propagate_update(key=Modules.GEOMETRY)
@@ -298,10 +293,8 @@ class GeometryWindow(PamhyrWindow):
data = {
"step": dlg.space_step,
"limites": [dlg.begin_cs, dlg.end_cs],
- "origin": dlg.origin,
"directrices": [dlg.begin_dir, dlg.end_dir],
"lplan": dlg.lplan,
- "lm": dlg.lm,
"linear": dlg.linear,
}
self._edit_meshing(data)
@@ -334,6 +327,7 @@ class GeometryWindow(PamhyrWindow):
"origin": dlg.origin,
"directrices": [dlg.begin_dir, dlg.end_dir],
"origin_value": dlg.origin_value,
+ "orientation": dlg.orientation,
}
self._update_kp(data)
except Exception as e:
@@ -360,7 +354,9 @@ class GeometryWindow(PamhyrWindow):
canvas=self._canvas_xy,
data=self._reach,
trad=self._trad,
- toolbar=self._toolbar_xy
+ toolbar=self._toolbar_xy,
+ table=self.find(QTableView, "tableView"),
+ parent=self
)
self._plot_xy.draw()
@@ -379,7 +375,9 @@ class GeometryWindow(PamhyrWindow):
study=self._study,
data=self._reach,
trad=self._trad,
- toolbar=self._toolbar_kpc
+ toolbar=self._toolbar_kpc,
+ table=self.find(QTableView, "tableView"),
+ parent=self
)
self._plot_kpc.draw()
@@ -405,7 +403,6 @@ class GeometryWindow(PamhyrWindow):
def update_plot_ac(self, ind: int):
self.tableView.model().blockSignals(True)
- self._plot_ac.current = ind
self._plot_ac.update()
self.tableView.model().blockSignals(False)
@@ -433,27 +430,11 @@ class GeometryWindow(PamhyrWindow):
self._plot_ac.update()
self.tableView.model().blockSignals(False)
- def select_row_profile_slider(self, ind: int = 0):
- if self.tableView is not None:
- selectionModel = self.tableView.selectionModel()
- index = self.tableView.model().index(ind, 0)
-
- selectionModel.select(
- index,
- QItemSelectionModel.Rows |
- QItemSelectionModel.ClearAndSelect |
- QItemSelectionModel.Select
- )
-
- self.tableView.scrollTo(index)
-
def select_current_profile(self):
self.tableView.model().blockSignals(True)
+ row = self.index_selected_row()
- if len(self.tableView.selectedIndexes()) > 0:
- row = self.index_selected_row()
-
- self.find(QSlider, "verticalSlider").setValue(row)
+ if row is not None:
self.select_plot_xy(row)
self.select_plot_kpc(row)
self.select_plot_ac(row)
@@ -464,33 +445,6 @@ class GeometryWindow(PamhyrWindow):
self.tableView.model().blockSignals(False)
- def changed_slider_value(self):
- self.tableView.model().blockSignals(True)
-
- if self._table.rowCount() != 0:
- slider = self.find(QSlider, "verticalSlider")
- slider.setMaximum(self._table.rowCount() - 1)
-
- slider_value = slider.value()
- kp = self._reach.profile(slider_value).kp
-
- self.select_plot_xy(slider_value)
- self.select_plot_kpc(slider_value)
- self.select_row_profile_slider(slider_value)
- self.update_statusbar()
-
- self.tableView.model().blockSignals(False)
-
- def increment_value_slider(self):
- slider = self.find(QSlider, "verticalSlider")
- if 0 <= slider.value() < self._table.rowCount() - 1:
- slider.setValue(slider.value() + 1)
-
- def decrement_value_slider(self):
- slider = self.find(QSlider, "verticalSlider")
- if 0 < slider.value() < self._table.rowCount():
- slider.setValue(slider.value() - 1)
-
def add(self):
if len(self.tableView.selectedIndexes()) == 0:
self._table.add(self._table.rowCount())
@@ -511,29 +465,37 @@ class GeometryWindow(PamhyrWindow):
self._table.delete(rows)
def index_selected_row(self):
- return self.tableView\
- .selectionModel()\
- .selectedRows()[0]\
- .row()
+ r = self.tableView\
+ .selectionModel()\
+ .selectedRows()
+
+ if len(r) == 1:
+ return r[0].row()
+ else:
+ return None
def sort_ascending(self):
self._table.sort_profiles(False)
self.select_current_profile()
- self.changed_slider_value()
def sort_descending(self):
self._table.sort_profiles(True)
self.select_current_profile()
- self.changed_slider_value()
def move_up(self):
row = self.index_selected_row()
+ if row is None:
+ return
+
self._table.move_up(row)
self.select_current_profile()
def move_down(self):
row = self.index_selected_row()
+ if row is None:
+ return
+
self._table.move_down(row)
self.select_current_profile()
@@ -541,6 +503,18 @@ class GeometryWindow(PamhyrWindow):
self._table.purge()
self.update_redraw()
+ def purge(self):
+ try:
+ dlg = PurgeDialog(
+ trad=self._trad,
+ parent=self
+ )
+ if dlg.exec():
+ self._table.purge(dlg.np_purge)
+ except Exception as e:
+ logger_exception(e)
+ return
+
def duplicate(self):
rows = [
row.row() for row in
diff --git a/src/View/HydraulicStructures/BasicHydraulicStructures/Translate.py b/src/View/HydraulicStructures/BasicHydraulicStructures/Translate.py
index f55fb2d7..29a12f35 100644
--- a/src/View/HydraulicStructures/BasicHydraulicStructures/Translate.py
+++ b/src/View/HydraulicStructures/BasicHydraulicStructures/Translate.py
@@ -28,7 +28,7 @@ class BasicHydraulicStructuresTranslate(MainTranslate):
super(BasicHydraulicStructuresTranslate, self).__init__()
self._dict["Basic Hydraulic Structures"] = _translate(
- "BasicHydraulicStructures", "Basic Hydraulic Structures"
+ "BasicHydraulicStructures", "Basic Hydraulic Structure"
)
self._dict['msg_type_change_title'] = _translate(
@@ -138,7 +138,7 @@ hydraulic structure values?"
"BasicHydraulicStructures", "Check valve"
),
"UD": _translate(
- "BasicHydraulicStructures", "User defined"
+ "BasicHydraulicStructures", "User-defined"
),
}
diff --git a/src/View/HydraulicStructures/PlotKPC.py b/src/View/HydraulicStructures/PlotKPC.py
index 3327f6e6..08ee34e2 100644
--- a/src/View/HydraulicStructures/PlotKPC.py
+++ b/src/View/HydraulicStructures/PlotKPC.py
@@ -20,8 +20,9 @@ from tools import timer
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
- QCoreApplication
+ QCoreApplication, Qt,
)
+from PyQt5.QtWidgets import QApplication
from matplotlib.collections import LineCollection
@@ -50,6 +51,7 @@ class PlotKPC(PamhyrPlot):
self._auto_relim_update = True
self._autoscale_update = True
+ self.parent = parent
@property
def river(self):
@@ -91,7 +93,14 @@ class PlotKPC(PamhyrPlot):
self.line_kp_zmin, = self.canvas.axes.plot(
kp, z_min,
color=self.color_plot_river_bottom,
- lw=1.
+ lw=1.,
+ )
+
+ self.line_kp_zmax, = self.canvas.axes.plot(
+ kp, z_max,
+ color=self.color_plot_river_bottom,
+ lw=1.,
+ alpha=0.0
)
if len(kp) != 0:
@@ -99,7 +108,8 @@ class PlotKPC(PamhyrPlot):
x=kp,
ymin=z_min, ymax=z_max,
color=self.color_plot,
- lw=1.
+ lw=1.,
+ picker=10
)
def draw_current(self):
@@ -163,3 +173,40 @@ class PlotKPC(PamhyrPlot):
self.profile.set_data([], [])
self.canvas.figure.canvas.draw_idle()
+
+ def onpick(self, event):
+ if event.mouseevent.inaxes != self.canvas.axes:
+ return
+ if event.mouseevent.button.value != 1:
+ return
+
+ modifiers = QApplication.keyboardModifiers()
+ if modifiers not in [Qt.ControlModifier,
+ Qt.NoModifier,
+ Qt.ShiftModifier]:
+ return
+
+ closest = self._closest_profile(event)
+ index = self.parent.tableView.selectedIndexes()
+ if self.parent._table is not None:
+ self.parent._table.setData(index[2], closest)
+
+ return
+
+ def _closest_profile(self, event):
+
+ s = event.artist.get_segments()
+ x = [i[0, 0] for i in s]
+ mx = event.mouseevent.xdata
+ points = enumerate(x)
+
+ def dist_mouse(point):
+ x = point[1]
+ d = abs(mx - x)
+ return d
+
+ closest = min(
+ points, key=dist_mouse
+ )
+
+ return closest[1]
diff --git a/src/View/HydraulicStructures/Window.py b/src/View/HydraulicStructures/Window.py
index 1c6af72c..7dee787d 100644
--- a/src/View/HydraulicStructures/Window.py
+++ b/src/View/HydraulicStructures/Window.py
@@ -141,7 +141,8 @@ class HydraulicStructuresWindow(PamhyrWindow):
reach=None,
profile=None,
trad=self._trad,
- toolbar=self.toolbar
+ toolbar=self.toolbar,
+ parent=self
)
self.plot_kpc.draw()
diff --git a/src/View/InitialConditions/PlotDischarge.py b/src/View/InitialConditions/PlotDischarge.py
index 7c43c1e5..5ab0b501 100644
--- a/src/View/InitialConditions/PlotDischarge.py
+++ b/src/View/InitialConditions/PlotDischarge.py
@@ -52,18 +52,41 @@ class PlotDischarge(PamhyrPlot):
self._init = True
def draw_data(self):
- kp = self.data.reach.reach.get_kp()
+ self.line_discharge = []
if len(self.data) != 0:
kp = self.data.get_kp()
discharge = self.data.get_discharge()
- self.line_kp_zmin = self.canvas.axes.plot(
+ line, = self.canvas.axes.plot(
kp, discharge,
color=self.color_plot,
**self.plot_default_kargs
)
+ self.line_discharge.append(line)
@timer
def update(self, ind=None):
- self.draw()
+ if not self._init:
+ self.draw()
+
+ self.update_data()
+
+ self.update_idle()
+
+ def update_data(self):
+ if len(self.data) == len(self.line_discharge):
+ kp = self.data.get_kp()
+ discharge = self.data.get_discharge()
+
+ line, = self.canvas.axes.plot(
+ kp, discharge,
+ color=self.color_plot,
+ **self.plot_default_kargs
+ )
+ self.line_discharge.append(line)
+ else:
+ for line in self.line_discharge:
+ line.remove()
+
+ self._draw_data()
diff --git a/src/View/InitialConditions/Window.py b/src/View/InitialConditions/Window.py
index 82946e84..a9f4c6ad 100644
--- a/src/View/InitialConditions/Window.py
+++ b/src/View/InitialConditions/Window.py
@@ -194,8 +194,13 @@ class InitialConditionsWindow(PamhyrWindow):
return rows[0].row()
def update(self):
+ self.update(propagate=False)
+
+ def _update(self, propagate=True):
self._update_plot()
- self._propagate_update(key=Modules.INITIAL_CONDITION)
+
+ if propagate:
+ self._propagate_update(key=Modules.INITIAL_CONDITION)
def _update_plot(self):
self.plot_1.draw()
diff --git a/src/View/LateralContribution/Edit/Table.py b/src/View/LateralContribution/Edit/Table.py
index c0ab3b44..accf7142 100644
--- a/src/View/LateralContribution/Edit/Table.py
+++ b/src/View/LateralContribution/Edit/Table.py
@@ -99,7 +99,7 @@ class TableModel(PamhyrTableModel):
logger.info(e)
logger.debug(traceback.format_exc())
- self.dataChanged.emit(index, index)
+ self.update()
return True
def add(self, row, parent=QModelIndex()):
@@ -112,7 +112,7 @@ class TableModel(PamhyrTableModel):
)
self.endInsertRows()
- self.layoutChanged.emit()
+ self.update()
def delete(self, rows, parent=QModelIndex()):
self.beginRemoveRows(parent, rows[0], rows[-1])
@@ -135,7 +135,7 @@ class TableModel(PamhyrTableModel):
)
self.layoutAboutToBeChanged.emit()
- self.layoutChanged.emit()
+ self.update()
def move_up(self, row, parent=QModelIndex()):
if row <= 0:
@@ -152,7 +152,7 @@ class TableModel(PamhyrTableModel):
)
self.endMoveRows()
- self.layoutChanged.emit()
+ self.update()
def move_down(self, index, parent=QModelIndex()):
if row > len(self._data):
@@ -169,7 +169,7 @@ class TableModel(PamhyrTableModel):
)
self.endMoveRows()
- self.layoutChanged.emit()
+ self.update()
def paste(self, row, header, data):
if len(data) == 0:
@@ -190,4 +190,13 @@ class TableModel(PamhyrTableModel):
)
self.layoutAboutToBeChanged.emit()
+ self.update()
+
+ def auto_sort(self):
+ self.layoutAboutToBeChanged.emit()
+ self._data.sort(key=lambda x: x[0])
+ self.layoutAboutToBeChanged.emit()
+
+ def update(self):
+ # self.auto_sort()
self.layoutChanged.emit()
diff --git a/src/View/LateralContribution/Edit/Window.py b/src/View/LateralContribution/Edit/Window.py
index 53c774cb..1b5beec7 100644
--- a/src/View/LateralContribution/Edit/Window.py
+++ b/src/View/LateralContribution/Edit/Window.py
@@ -137,6 +137,7 @@ class EditLateralContributionWindow(PamhyrWindow):
self.find(QAction, "action_sort").triggered.connect(self.sort)
self._table.dataChanged.connect(self.update)
+ self._table.layoutChanged.connect(self.update)
def update(self):
self.plot.update()
diff --git a/src/View/LateralContribution/Edit/translate.py b/src/View/LateralContribution/Edit/translate.py
index eeb88930..14b23772 100644
--- a/src/View/LateralContribution/Edit/translate.py
+++ b/src/View/LateralContribution/Edit/translate.py
@@ -28,7 +28,7 @@ class LCETranslate(LCTranslate):
def __init__(self):
super(LCETranslate, self).__init__()
self._dict["Edit lateral contribution"] = _translate(
- "LateralContribution", "Edit lateral contribution"
+ "LateralContribution", "Edit lateral sources"
)
self._sub_dict["table_headers"] = {
diff --git a/src/View/LateralContribution/PlotXY.py b/src/View/LateralContribution/PlotXY.py
new file mode 100644
index 00000000..c5826286
--- /dev/null
+++ b/src/View/LateralContribution/PlotXY.py
@@ -0,0 +1,260 @@
+# PlotXY.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 .
+
+# -*- coding: utf-8 -*-
+
+from tools import timer, trace
+from View.Tools.PamhyrPlot import PamhyrPlot
+from matplotlib import collections
+import numpy as np
+
+from PyQt5.QtCore import (
+ QCoreApplication, Qt, QItemSelectionModel,
+ QItemSelection, QItemSelectionRange,
+)
+from PyQt5.QtWidgets import QApplication, QTableView
+
+_translate = QCoreApplication.translate
+
+
+class PlotXY(PamhyrPlot):
+ def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
+ table=None, parent=None):
+ super(PlotXY, self).__init__(
+ canvas=canvas,
+ trad=trad,
+ data=data,
+ toolbar=toolbar,
+ table=table,
+ parent=parent
+ )
+
+ self.line_xy = []
+ self.line_gl = []
+
+ self.label_x = self._trad["x"]
+ self.label_y = self._trad["y"]
+
+ self.before_plot_selected = None
+ self.plot_selected = None
+ self.after_plot_selected = None
+ self.parent = parent
+ self.line_xy_collection = None
+ self._table = table
+ self._colors = []
+ self._style = []
+
+ def onpick(self, event):
+ if event.mouseevent.inaxes != self.canvas.axes:
+ return
+ if event.mouseevent.button.value not in [1, 3]:
+ return
+
+ closest = self._closest_section(event)
+ t = self.parent.current_tab()
+ tableView = self.parent.find(QTableView, f"tableView_{t}")
+ table = self.parent._table[t]
+ index = tableView.selectedIndexes()
+ kp = self.data.get_kp()
+ if self.parent._table is not None:
+ if event.mouseevent.button.value == 1:
+ table.setData(index[3], kp[closest[0]])
+ if event.mouseevent.button.value == 3:
+ table.setData(index[4], kp[closest[0]])
+
+ return
+
+ def _closest_section(self, event):
+ axes = self.canvas.axes
+ mx = event.mouseevent.xdata
+ my = event.mouseevent.ydata
+ bx, by = axes.get_xlim(), axes.get_ylim()
+ ratio = (bx[0] - bx[1]) / (by[0] - by[1])
+
+ segments = event.artist.get_segments()
+ ind = event.ind
+
+ points = []
+ for i in ind:
+ points = points + [[i, j] for j in segments[i]]
+
+ def dist_mouse(point):
+ x, y = point[1]
+ d2 = (((mx - x) / ratio) ** 2) + ((my - y) ** 2)
+ return d2
+
+ closest = min(
+ points, key=dist_mouse
+ )
+
+ return closest
+
+ @timer
+ def draw(self):
+ self.init_axes()
+
+ if self.data is None:
+ self.idle()
+ return
+
+ if self.data.number_profiles == 0:
+ self._init = False
+ self.idle()
+ return
+
+ self.draw_xy()
+ self.draw_lr()
+ self.draw_gl()
+
+ self.idle()
+ self._init = True
+
+ def draw_xy(self):
+ self.line_xy = []
+ for xy in zip(self.data.get_x(), self.data.get_y()):
+ self.line_xy.append(np.column_stack(xy))
+
+ self._colors, self._style = self.color_hightlight()
+ self.line_xy_collection = collections.LineCollection(
+ self.line_xy,
+ colors=self._colors,
+ linestyle=self._style,
+ picker=10
+ )
+ self.canvas.axes.add_collection(self.line_xy_collection)
+
+ def color_hightlight(self):
+ kp_min, kp_max = (-1, -1)
+ if self._highlight_data is not None:
+ kp_min, kp_max = self._highlight_data
+
+ colors = [self.color_plot for row in range(len(self._data))]
+ for i, kp in enumerate(self.data.get_kp_complete_profiles()):
+ if kp_min <= kp <= kp_max:
+ colors[i] = self.color_plot_current
+ style = ["-" for row in range(len(self._data))]
+
+ return colors, style
+
+ def draw_lr(self):
+ lx = []
+ ly = []
+ rx = []
+ ry = []
+
+ self.line_lr = []
+ for x, y in zip(self.data.get_x(),
+ self.data.get_y()):
+ lx.append(x[0])
+ ly.append(y[0])
+
+ rx.append(x[-1])
+ ry.append(y[-1])
+
+ line = self.canvas.axes.plot(
+ lx, ly,
+ color=self.color_plot_river_bottom,
+ linestyle="dotted",
+ lw=1.,
+ )
+ self.line_lr.append(line)
+
+ line = self.canvas.axes.plot(
+ rx, ry,
+ color=self.color_plot_river_bottom,
+ linestyle="dotted",
+ lw=1.,
+ )
+ self.line_lr.append(line)
+
+ def draw_gl(self):
+ x_complete = self.data.get_guidelines_x()
+ y_complete = self.data.get_guidelines_y()
+
+ ind = 0
+ self.line_gl = []
+ for x, y in zip(x_complete, y_complete):
+ line = self.canvas.axes.plot(
+ x, y, color=self.colors[ind % len(self.colors)],
+ linestyle=self.linestyle[ind // len(self.colors)]
+ )
+ self.line_gl.append(line)
+ ind += 1
+
+ @timer
+ def update(self):
+ if not self._init:
+ self.draw()
+ return
+
+ if self.data is None:
+ return
+
+ self.update_lr()
+ self.update_gl()
+ self.update_current()
+
+ self.update_idle()
+
+ def update_gl(self):
+ self.data.compute_guidelines()
+ x_complete = list(self.data.get_guidelines_x())
+ y_complete = list(self.data.get_guidelines_y())
+
+# TODO comprendre à quoi sert ce bout de code
+# ========>
+# for i in range(self.data.number_profiles):
+# if i < len(self.line_xy):
+# self.line_xy[i][0].set_data(
+# self.data.profile(i).x(),
+# self.data.profile(i).y()
+# )
+# else:
+# self.line_xy.append(
+# self.canvas.axes.plot(
+# self.data.profile(i).x(),
+# self.data.profile(i).y(),
+# color='r',
+# **self.plot_default_kargs
+# )
+# )
+# <========
+
+ for i in range(len(x_complete)):
+ if i < len(self.line_gl):
+ self.line_gl[i][0].set_data(
+ x_complete[i],
+ y_complete[i]
+ )
+ else:
+ self.line_gl.append(
+ self.canvas.axes.plot(
+ x_complete[i],
+ y_complete[i]
+ )
+ )
+
+ def update_current(self):
+ if self._current_data_update:
+ self._colors, self._style = self.color_hightlight()
+ self.line_xy_collection.set_colors(self._colors)
+ self.line_xy_collection.set_linestyle(self._style)
+
+ def update_lr(self):
+ for line in self.line_lr:
+ line[0].remove()
+
+ self.draw_lr()
diff --git a/src/View/LateralContribution/Window.py b/src/View/LateralContribution/Window.py
index 879955bb..fab8e289 100644
--- a/src/View/LateralContribution/Window.py
+++ b/src/View/LateralContribution/Window.py
@@ -54,7 +54,7 @@ from View.LateralContribution.Table import (
)
from View.Tools.Plot.PamhyrCanvas import MplCanvas
-from View.Geometry.PlotXY import PlotXY
+from View.LateralContribution.PlotXY import PlotXY
from View.LateralContribution.translate import (
LC_types, LCTranslate,
)
@@ -83,6 +83,7 @@ class LateralContributionWindow(PamhyrWindow):
self.setup_table()
self.setup_graph()
+ self.tabs = self.find(QTabWidget, "tabWidget")
self.setup_connections()
def setup_table(self):
@@ -148,6 +149,7 @@ class LateralContributionWindow(PamhyrWindow):
data=None,
trad=self._trad,
toolbar=None,
+ parent=self
)
def setup_connections(self):
@@ -156,6 +158,8 @@ class LateralContributionWindow(PamhyrWindow):
self.find(QAction, "action_edit").triggered.connect(self.edit)
self.find(QAction, "action_sort").triggered.connect(self.sort)
+ self.tabs.currentChanged.connect(self._set_current_reach)
+
for t in ["liquid", "solid", "suspenssion"]:
table = self.find(QTableView, f"tableView_{t}")
table.selectionModel()\
@@ -216,6 +220,7 @@ class LateralContributionWindow(PamhyrWindow):
data=data,
trad=self._trad,
toolbar=None,
+ parent=self
)
self.plot.highlight = highlight
self.plot.update()
diff --git a/src/View/LateralContribution/translate.py b/src/View/LateralContribution/translate.py
index 145e137f..e6d4225c 100644
--- a/src/View/LateralContribution/translate.py
+++ b/src/View/LateralContribution/translate.py
@@ -39,12 +39,12 @@ class LCTranslate(MainTranslate):
super(LCTranslate, self).__init__()
self._dict["Lateral contribution"] = _translate(
- "LateralContribution", "Lateral contribution"
+ "LateralContribution", "Lateral sources"
)
self._sub_dict["long_types"] = {
"ND": self._dict["not_defined"],
- "LC": _translate("LateralContribution", "Lateral contribution"),
+ "LC": _translate("LateralContribution", "Lateral sources"),
"RA": _translate("LateralContribution", "Rain"),
"EV": _translate("LateralContribution", "Evaporation"),
}
@@ -57,6 +57,6 @@ class LCTranslate(MainTranslate):
"name": self._dict["name"],
"type": self._dict["type"],
"edge": self._dict["reach"],
- "begin_kp": _translate("LateralContribution", "Begin kp (m)"),
- "end_kp": _translate("LateralContribution", "End kp (m)")
+ "begin_kp": _translate("LateralContribution", "Start (m)"),
+ "end_kp": _translate("LateralContribution", "End (m)")
}
diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py
index 558131cb..2bdda242 100644
--- a/src/View/MainWindow.py
+++ b/src/View/MainWindow.py
@@ -459,8 +459,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if Modules.CONFIG in keys:
self._do_update_config()
- if Modules.STUDY in keys:
- self._tab_widget_info.update()
+ self._do_propagate_update_info_tab(keys)
logger.debug(f"Propagation of {keys}")
for _, window in self.sub_win_list:
@@ -469,6 +468,18 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
self._tab_widget_checker.update(modules=keys)
+ def _do_propagate_update_info_tab(self, keys):
+ modules = Modules.modelling_list()
+ modules.append(Modules.STUDY)
+
+ has_info_mod = reduce(
+ lambda acc, m: acc or (m in keys),
+ modules, False
+ )
+
+ if has_info_mod:
+ self._tab_widget_info.update()
+
def _do_propagate_update_rec(self, window, keys):
for _, win in window.sub_win_list:
win._propagated_update(key=keys)
@@ -579,9 +590,13 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Nothing
"""
if self._study.filename is None or self._study.filename == "":
+ options = QFileDialog.Options()
+ options |= QFileDialog.DontUseNativeDialog
+
file_name, _ = QFileDialog.getSaveFileName(
self, "Save File",
- "", "Pamhyr(*.pamhyr)"
+ "", "Pamhyr(*.pamhyr)",
+ options=options,
)
if file_name.rsplit(".", 1)[-1] == "pamhyr":
@@ -630,9 +645,13 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns:
Nothing
"""
+ options = QFileDialog.Options()
+ options |= QFileDialog.DontUseNativeDialog
+
file_name, _ = QFileDialog.getSaveFileName(
self, "Save File",
- "", "Pamhyr(*.pamhyr)"
+ "", "Pamhyr(*.pamhyr)",
+ options=options,
)
logger.debug(f"Save study as : {repr(file_name)}")
@@ -976,7 +995,10 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Nothing
"""
if self._study is None:
- dialog = QFileDialog(self)
+ options = QFileDialog.Options()
+ options |= QFileDialog.DontUseNativeDialog
+
+ dialog = QFileDialog(self, options=options)
dialog.setFileMode(QFileDialog.FileMode.ExistingFile)
dialog.setDefaultSuffix(".pamhyr")
# dialog.setFilter(dialog.filter() | QtCore.QDir.Hidden)
@@ -1376,7 +1398,11 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if self._study.filename == "":
return
- dialog = QFileDialog(self)
+ options = QFileDialog.Options()
+ options |= QFileDialog.DontUseNativeDialog
+
+ dialog = QFileDialog(self, options=options)
+
dialog.setFileMode(QFileDialog.FileMode.ExistingFile)
dialog.setDefaultSuffix(".BIN")
# dialog.setFilter(dialog.filter() | QtCore.QDir.Hidden)
diff --git a/src/View/Network/translate.py b/src/View/Network/translate.py
index 1b2b8c0c..d6024681 100644
--- a/src/View/Network/translate.py
+++ b/src/View/Network/translate.py
@@ -54,10 +54,12 @@ class NetworkTranslate(MainTranslate):
self._sub_dict["table_headers_node"] = {
"name": self._dict['name'],
"type": self._dict['type'],
+ # "id": _translate("Network", "Index"),
}
self._sub_dict["table_headers_edge"] = {
"name": self._dict['name'],
"node1": _translate("Network", "Source node"),
"node2": _translate("Network", "Destination node"),
+ # "id": _translate("Network", "Index"),
}
diff --git a/src/View/Results/CustomPlot/Translate.py b/src/View/Results/CustomPlot/Translate.py
index 6c4236b8..4c4f3815 100644
--- a/src/View/Results/CustomPlot/Translate.py
+++ b/src/View/Results/CustomPlot/Translate.py
@@ -28,7 +28,7 @@ class CustomPlotTranslate(ResultsTranslate):
super(CustomPlotTranslate, self).__init__()
self._dict["Custom Plot Selection"] = _translate(
- "CustomPlot", "Custom Plot Selection"
+ "CustomPlot", "Custom plot selection"
)
# Value type
@@ -38,13 +38,13 @@ class CustomPlotTranslate(ResultsTranslate):
self._dict['water_elevation'] = self._dict["unit_water_elevation"]
self._dict['discharge'] = self._dict["unit_discharge"]
self._dict['elevation'] = _translate(
- "CustomPlot", "Bed load elevation (m)"
+ "CustomPlot", "Bed elevation (m)"
)
# Unit corresponding long name (plot axes display)
self._dict['0-meter'] = _translate(
- "CustomPlot", "Bed load elevation (m)"
+ "CustomPlot", "Bed elevation (m)"
)
self._dict['1-m3s'] = self._dict["unit_discharge"]
diff --git a/src/View/Results/PlotKPC.py b/src/View/Results/PlotKPC.py
index 77e101dc..74c08059 100644
--- a/src/View/Results/PlotKPC.py
+++ b/src/View/Results/PlotKPC.py
@@ -109,7 +109,10 @@ class PlotKPC(PamhyrPlot):
def draw_profiles_hs(self, reach):
lhs = filter(
lambda hs: hs._input_reach.reach is reach.geometry,
- self.results.study.river.hydraulic_structures.lst
+ filter(
+ lambda hs: hs._input_reach is not None,
+ self.results.study.river.hydraulic_structures.lst
+ )
)
for hs in lhs:
diff --git a/src/View/Results/PlotSedReach.py b/src/View/Results/PlotSedReach.py
index d77339a1..f62c5123 100644
--- a/src/View/Results/PlotSedReach.py
+++ b/src/View/Results/PlotSedReach.py
@@ -231,7 +231,7 @@ class PlotSedReach(PamhyrPlot):
return
self.canvas.axes.set_xlabel(
- _translate("MainWindow_reach", "Kp (m)"),
+ _translate("MainWindow_reach", "Position (m)"),
color='black', fontsize=10
)
self.canvas.axes.set_ylabel(
diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py
index 22a7149f..1621e282 100644
--- a/src/View/Results/PlotXY.py
+++ b/src/View/Results/PlotXY.py
@@ -22,10 +22,14 @@ from functools import reduce
from tools import timer, trace
from View.Tools.PamhyrPlot import PamhyrPlot
+import numpy as np
+from matplotlib import collections
from PyQt5.QtCore import (
- QCoreApplication
+ QCoreApplication, Qt, QItemSelectionModel,
+ QItemSelection, QItemSelectionRange
)
+from PyQt5.QtWidgets import QApplication, QTableView
_translate = QCoreApplication.translate
@@ -57,6 +61,73 @@ class PlotXY(PamhyrPlot):
self.label_y = _translate("Results", "Y (m)")
self._isometric_axis = True
+ self._tablemodel = parent._table["profile"]
+ self._table = parent.find(QTableView, f"tableView_profile")
+
+ def onpick(self, event):
+ if event.mouseevent.inaxes != self.canvas.axes:
+ return
+ if event.mouseevent.button.value != 1:
+ return
+
+ modifiers = QApplication.keyboardModifiers()
+ if modifiers not in [Qt.ControlModifier,
+ Qt.NoModifier,
+ Qt.ShiftModifier]:
+ return
+
+ ind, point = self._closest_section(event)
+ if self._table is None:
+ return
+ self._select_in_table([ind])
+ self._table.blockSignals(False)
+
+ return
+
+ def _closest_section(self, event):
+ axes = self.canvas.axes
+ mx = event.mouseevent.xdata
+ my = event.mouseevent.ydata
+ bx, by = axes.get_xlim(), axes.get_ylim()
+ ratio = (bx[0] - bx[1]) / (by[0] - by[1])
+
+ segments = event.artist.get_segments()
+ ind = event.ind
+
+ points = []
+ for i in ind:
+ points = points + [[i, j] for j in segments[i]]
+
+ def dist_mouse(point):
+ x, y = point[1]
+ d2 = (((mx - x) / ratio) ** 2) + ((my - y) ** 2)
+ return d2
+
+ closest = min(
+ points, key=dist_mouse
+ )
+
+ return closest
+
+ def _select_in_table(self, ind):
+ if self._table is None:
+ return
+ self._table.setFocus()
+ selection = self._table.selectionModel()
+ index = QItemSelection()
+ if len(ind) == 0:
+ return
+ for i in ind:
+ index.append(QItemSelectionRange(self._table.model().index(i, 0)))
+ selection.select(
+ index,
+ QItemSelectionModel.Rows |
+ QItemSelectionModel.ClearAndSelect |
+ QItemSelectionModel.Select
+ )
+
+ if len(ind) > 0:
+ self._table.scrollTo(self._table.model().index(ind[-1], 0))
@property
def results(self):
@@ -90,18 +161,36 @@ class PlotXY(PamhyrPlot):
self._init = False
return
- self.line_xy = [
- self.canvas.axes.plot(
- x, y,
- color=self.color_plot_river_bottom,
- **self.plot_default_kargs
- )
- for x, y, kp in zip(
- reach.geometry.get_x(),
- reach.geometry.get_y(),
- reach.geometry.get_kp()
- )
- ]
+ self.line_xy = []
+ for xy in zip(reach.geometry.get_x(),
+ reach.geometry.get_y()):
+ self.line_xy.append(np.column_stack(xy))
+
+ self._colors, self._style = self.color_hightlight()
+ self.line_xy_collection = collections.LineCollection(
+ self.line_xy,
+ colors=self._colors,
+ linestyle=self._style,
+ picker=10
+ )
+ self.canvas.axes.add_collection(self.line_xy_collection)
+
+ def color_hightlight(self):
+ reach = self.results.river.reach(self._current_reach_id)
+ rows = [self._current_profile_id]
+ colors = [self.color_plot
+ for row in range(reach.geometry.number_profiles)]
+ style = ["-" for row in range(reach.geometry.number_profiles)]
+ if len(rows) > 0:
+ for row in rows:
+ colors[row] = self.color_plot_current
+ if rows[0] > 0:
+ colors[rows[0]-1] = self.color_plot_previous
+ style[rows[0]-1] = "--"
+ if rows[-1] < reach.geometry.number_profiles-1:
+ colors[rows[-1]+1] = self.color_plot_next
+ style[rows[-1]+1] = "--"
+ return colors, style
def draw_guide_lines(self, reach):
x_complete = reach.geometry.get_guidelines_x()
diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py
index 155b971e..d946c088 100644
--- a/src/View/Results/Window.py
+++ b/src/View/Results/Window.py
@@ -176,7 +176,8 @@ class ResultsWindow(PamhyrWindow):
profile_id=0,
trad=self._trad,
toolbar=self.toolbar,
- display_current=True
+ display_current=True,
+ parent=self
)
self.plot_xy.draw()
diff --git a/src/View/SolverParameters/translate.py b/src/View/SolverParameters/translate.py
index c1a45d2b..46bae698 100644
--- a/src/View/SolverParameters/translate.py
+++ b/src/View/SolverParameters/translate.py
@@ -99,7 +99,7 @@ class ParamTranslate(MainTranslate):
"Minimum water height (meter)"),
"mage_max_niter":
_translate("SolverParameters",
- "Maximun number of iterations (< 100)"),
+ "Maximum number of iterations (< 100)"),
"mage_timestep_reduction_factor":
_translate("SolverParameters",
"Timestep reduction factor"),
@@ -114,10 +114,10 @@ class ParamTranslate(MainTranslate):
"Reduction precision factor of residue"),
"mage_niter_max_precision":
_translate("SolverParameters",
- "Number of iteration at maximum precision"),
+ "Number of iterations at maximum precision"),
"mage_niter_before_switch":
_translate("SolverParameters",
- "Number of iteration before switch"),
+ "Number of iterations before switch"),
"mage_max_froude":
_translate("SolverParameters",
"Maximum accepted Froude number"),
@@ -152,7 +152,7 @@ class ParamTranslate(MainTranslate):
"mage_methode_modification_geometrie":
_translate("SolverParameters", "Geometry modification method"),
"mage_shields_critique":
- _translate("SolverParameters", "Critic shields"),
+ _translate("SolverParameters", "Critical Shields number"),
"mage_shields_correction":
_translate("SolverParameters", "Shields correction"),
"mage_capacite_solide":
diff --git a/src/View/Stricklers/translate.py b/src/View/Stricklers/translate.py
index 01275bb1..eb8b5361 100644
--- a/src/View/Stricklers/translate.py
+++ b/src/View/Stricklers/translate.py
@@ -28,7 +28,7 @@ class StricklersTranslate(MainTranslate):
super(StricklersTranslate, self).__init__()
self._dict["Stricklers"] = _translate(
- "Stricklers", "Stricklers"
+ "Stricklers", "Strickler coefficients"
)
self._sub_dict["table_headers"] = {
diff --git a/src/View/Tools/ASubWindow.py b/src/View/Tools/ASubWindow.py
index 78655358..e985217f 100644
--- a/src/View/Tools/ASubWindow.py
+++ b/src/View/Tools/ASubWindow.py
@@ -35,7 +35,7 @@ from PyQt5.QtWidgets import (
QRadioButton, QComboBox, QFileDialog,
QMessageBox, QTableView, QAction,
QDateTimeEdit, QWidget, QPlainTextEdit,
- QLabel, QDoubleSpinBox,
+ QLabel, QDoubleSpinBox, QButtonGroup,
)
from PyQt5.QtCore import (
QTime, QDateTime,
@@ -102,7 +102,10 @@ class WindowToolKit(object):
Returns:
The returns of callback
"""
- dialog = QFileDialog(self)
+ options = QFileDialog.Options()
+ options |= QFileDialog.DontUseNativeDialog
+
+ dialog = QFileDialog(self, options=options)
if select_file:
mode = QFileDialog.FileMode.ExistingFile
@@ -498,6 +501,17 @@ class ASubWindowFeatures(object):
qdate = QDateTime.fromString(date.isoformat(), "yyyy-MM-ddThh:mm:ss")
self.find(QDateTimeEdit, name).setDateTime(qdate)
+ def get_checked_id_button_group(self, name: str):
+ """Get current checked button id in a buttonGroup
+
+ Args:
+ name: The buttonGroup component name
+
+ Returns:
+ Current checked id
+ """
+ return self.find(QButtonGroup, name).checkedId()
+
# Top level interface
diff --git a/src/View/Tools/PamhyrPlot.py b/src/View/Tools/PamhyrPlot.py
index 843be242..76159205 100644
--- a/src/View/Tools/PamhyrPlot.py
+++ b/src/View/Tools/PamhyrPlot.py
@@ -16,6 +16,8 @@
# -*- coding: utf-8 -*-
+import logging
+
import matplotlib.colors as mplcolors
from matplotlib import ticker
@@ -25,6 +27,8 @@ from View.Tools.Plot.APlot import APlot
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
+logger = logging.getLogger()
+
class PamhyrPlot(APlot):
color_axes = "black"
@@ -38,7 +42,6 @@ class PamhyrPlot(APlot):
color_plot_river_bottom = "grey"
color_plot_river_water = "blue"
color_plot_river_water_zone = "skyblue"
-
colors = list(mplcolors.TABLEAU_COLORS)
linestyle = ['solid', 'dashed', 'dashdot', 'dotted']
@@ -77,6 +80,7 @@ class PamhyrPlot(APlot):
connector = {
'pick_event': self.onpick,
'button_press_event': self.onclick,
+ 'button_release_event': self.onrelease,
}
for event in connector:
@@ -100,6 +104,7 @@ class PamhyrPlot(APlot):
self._highlight_data_update = False
self._current_data = None #: Current data identifier
self._current_data_update = False
+ self._rect_select = None
@property
def canvas(self):
@@ -231,3 +236,13 @@ class PamhyrPlot(APlot):
def onclick(self, event):
return
+
+ def onrelease(self, event):
+ return
+
+ def rect_select_callback(self, eclick, erelease):
+ 'eclick and erelease are the press and release events'
+ x1, y1 = eclick.xdata, eclick.ydata
+ x2, y2 = erelease.xdata, erelease.ydata
+ logging.debug("(%3.2f, %3.2f) --> (%3.2f, %3.2f)" % (x1, y1, x2, y2))
+ return
diff --git a/src/View/Tools/Plot/PamhyrToolbar.py b/src/View/Tools/Plot/PamhyrToolbar.py
index 2a851c92..5b4e2927 100644
--- a/src/View/Tools/Plot/PamhyrToolbar.py
+++ b/src/View/Tools/Plot/PamhyrToolbar.py
@@ -112,7 +112,7 @@ class PamhyrPlotToolbar(NavigationToolbar2QT):
self.toolitems.append(
(
'Forward',
- _translate("Toolbar", 'Return to next view'),
+ _translate("Toolbar", 'Back to next view'),
'forward', 'forward'
)
)
@@ -121,7 +121,7 @@ class PamhyrPlotToolbar(NavigationToolbar2QT):
self.toolitems.append(
(
'Pan',
- _translate("Toolbar", 'Axes panoramic'),
+ _translate("Toolbar", 'Panoramic axes'),
'move', 'pan'
)
)
@@ -184,7 +184,7 @@ class PamhyrPlotToolbar(NavigationToolbar2QT):
self.toolitems.append(
(
'Save',
- _translate("Toolbar", 'Save the figure'),
+ _translate("Toolbar", 'Save figure'),
'filesave', 'save_figure'
)
)
@@ -253,12 +253,12 @@ class PamhyrPlotToolbar(NavigationToolbar2QT):
self._actions['back'].setToolTip(
_translate("Toolbar", "Back to previous view"))
self._actions['forward'].setToolTip(
- _translate("Toolbar", "Return to next view"))
+ _translate("Toolbar", "Back to next view"))
self._actions['pan'].setToolTip(
- _translate("Toolbar", "Axes panoramic"))
+ _translate("Toolbar", "Panoramic axes"))
self._actions['zoom'].setToolTip(_translate("Toolbar", "Zoom"))
self._actions['save_figure'].setToolTip(
- _translate("Toolbar", "Save the figure"))
+ _translate("Toolbar", "Save figure"))
self.action_isometric_view.setToolTip(
_translate("Toolbar", "Isometric view (Shift+W)"))
self.action_auto_global_view.setToolTip(
diff --git a/src/View/Translate.py b/src/View/Translate.py
index 126043b5..6b5cfef8 100644
--- a/src/View/Translate.py
+++ b/src/View/Translate.py
@@ -55,7 +55,7 @@ class UnitTranslate(CommonWordTranslate):
def __init__(self):
super(UnitTranslate, self).__init__()
- self._dict["unit_kp"] = _translate("Unit", "KP (m)")
+ self._dict["unit_kp"] = _translate("Unit", "Position (m)")
self._dict["unit_width"] = _translate("Unit", "Width (m)")
self._dict["unit_height"] = _translate("Unit", "Height (m)")
self._dict["unit_diameter"] = _translate("Unit", "Diameter (m)")
@@ -103,5 +103,5 @@ class MainTranslate(UnitTranslate):
"MainWindow", "Open SQLite debuging tool ('sqlitebrowser')"
)
self._dict["active_window"] = _translate(
- "MainWindow", "Activate this window"
+ "MainWindow", "Enable this window"
)
diff --git a/src/View/ui/BoundaryConditions.ui b/src/View/ui/BoundaryConditions.ui
index 9f2f1b99..e023eff0 100644
--- a/src/View/ui/BoundaryConditions.ui
+++ b/src/View/ui/BoundaryConditions.ui
@@ -37,7 +37,7 @@
- 0
+ 2
@@ -61,7 +61,7 @@
- Suspenssion
+ Suspension
-
@@ -114,7 +114,7 @@
Add
- Add a new boundary condition or punctual contribution
+ Add a new boundary condition or point source
Ctrl+N
@@ -144,7 +144,7 @@
Edit
- Edit boundary condition or punctual contribution
+ Edit boundary condition or point source
Ctrl+E
@@ -159,7 +159,7 @@
Sort
- Sort boundary condition by name
+ Sort by names
diff --git a/src/View/ui/ConfigureDialog.ui b/src/View/ui/ConfigureDialog.ui
index 590d0ca2..9c23ce2d 100644
--- a/src/View/ui/ConfigureDialog.ui
+++ b/src/View/ui/ConfigureDialog.ui
@@ -164,7 +164,7 @@
-
- Frequence
+ Frequency
@@ -349,7 +349,7 @@
- This value must be used for reading or editing files in speficic case.
+ This value must be used for reading or editing files in speficic cases.
@@ -374,7 +374,7 @@
-
- - The "@file" keyworkd is replace by the path of file to open.
+ - The "@file" keyword is replaced by the path of file to open.
@@ -382,7 +382,7 @@
- Language
+ Langue
-
diff --git a/src/View/ui/DebugRepl.ui b/src/View/ui/DebugRepl.ui
index db4d069e..39f30ac3 100644
--- a/src/View/ui/DebugRepl.ui
+++ b/src/View/ui/DebugRepl.ui
@@ -23,7 +23,7 @@
-
- Eval
+ Evaluate
diff --git a/src/View/ui/EditBoundaryConditions.ui b/src/View/ui/EditBoundaryConditions.ui
index bfcf9505..b27232d2 100644
--- a/src/View/ui/EditBoundaryConditions.ui
+++ b/src/View/ui/EditBoundaryConditions.ui
@@ -86,7 +86,7 @@
Add
- Add a new point in boundary condition or punctual contribution
+ Add a new point
Ctrl+N
@@ -116,7 +116,7 @@
Sort
- Sort boundary condition points
+ Sort points
diff --git a/src/View/ui/EditLateralContribution.ui b/src/View/ui/EditLateralContribution.ui
index 02e14bcb..21736a6b 100644
--- a/src/View/ui/EditLateralContribution.ui
+++ b/src/View/ui/EditLateralContribution.ui
@@ -79,7 +79,7 @@
Add
- Add a new point in boundary condition or lateral contribution
+ Add a new point in boundary condition or lateral source
Ctrl+N
@@ -109,7 +109,7 @@
Sort
- Sort boundary condition point
+ Sort points
diff --git a/src/View/ui/Frictions.ui b/src/View/ui/Frictions.ui
index e219bf73..77c32181 100644
--- a/src/View/ui/Frictions.ui
+++ b/src/View/ui/Frictions.ui
@@ -98,7 +98,10 @@
ressources/edit.pngressources/edit.png
- Edit stricklers
+ Edit Strickler coefficients
+
+
+ Edit Strickler coefficients
Ctrl+E
diff --git a/src/View/ui/GeometryCrossSection.ui b/src/View/ui/GeometryCrossSection.ui
index c9c29e61..dfc47bb6 100644
--- a/src/View/ui/GeometryCrossSection.ui
+++ b/src/View/ui/GeometryCrossSection.ui
@@ -67,10 +67,10 @@
ressources/add.pngressources/add.png
- add
+ Add
- Add a point on cross-section
+ Add a point to cross-section
@@ -91,7 +91,7 @@
ressources/up.pngressources/up.png
- up
+ Up
Move up selected point(s)
@@ -103,10 +103,10 @@
ressources/down.pngressources/down.png
- down
+ Down
- Mode down selected point(s)
+ Move down selected point(s)
diff --git a/src/View/ui/GeometryReach.ui b/src/View/ui/GeometryReach.ui
index 2ba38650..ceda4450 100644
--- a/src/View/ui/GeometryReach.ui
+++ b/src/View/ui/GeometryReach.ui
@@ -28,49 +28,6 @@
-
- -
-
-
-
-
-
-
-
-
-
- ressources/go-up2.pngressources/go-up2.png
-
-
-
- -
-
-
-
-
-
- Qt::Vertical
-
-
- true
-
-
- true
-
-
-
-
-
- -
-
-
-
-
-
-
- ressources/go-down1.pngressources/go-down1.png
-
-
-
-
-
@@ -166,7 +123,7 @@
ressources/add.pngressources/add.png
- add
+ Add
Add a cross-section
@@ -190,7 +147,7 @@
ressources/edit.pngressources/edit.png
- edit
+ Edit
Edit selected cross section(s)
@@ -205,7 +162,7 @@
sort_asc
- Sort cross-sections by ascending KP
+ Sort cross-sections by ascending position
@@ -217,7 +174,7 @@
sort_des
- Sort cross-sections by descending KP
+ Sort cross-sections by descending position
@@ -226,7 +183,7 @@
ressources/up.pngressources/up.png
- up
+ Up
Move up selected cross-section(s)
@@ -238,7 +195,7 @@
ressources/down.pngressources/down.png
- down
+ Down
Move down selected cross-section(s)
diff --git a/src/View/ui/InitialConditions.ui b/src/View/ui/InitialConditions.ui
index 38f96734..403a5fe2 100644
--- a/src/View/ui/InitialConditions.ui
+++ b/src/View/ui/InitialConditions.ui
@@ -119,7 +119,7 @@
sort
- Sort inital condition
+ Sort inital conditions
diff --git a/src/View/ui/LateralContributions.ui b/src/View/ui/LateralContributions.ui
index bf9e5b45..2e720e3d 100644
--- a/src/View/ui/LateralContributions.ui
+++ b/src/View/ui/LateralContributions.ui
@@ -37,7 +37,7 @@
- 0
+ 2
@@ -61,7 +61,7 @@
- Suspenssion
+ Suspension
-
@@ -114,7 +114,7 @@
Add
- Add a new boundary condition or lateral contribution
+ Add a new boundary condition or lateral source
Ctrl+N
@@ -144,7 +144,7 @@
Edit
- Edit boundary condition or lateral contribution
+ Edit boundary condition or lateral source
Ctrl+E
@@ -159,7 +159,7 @@
Sort
- Sort boundary condition by name
+ Sort by names
diff --git a/src/View/ui/MainWindow.ui b/src/View/ui/MainWindow.ui
index c2bda3eb..5d7a4d9b 100644
--- a/src/View/ui/MainWindow.ui
+++ b/src/View/ui/MainWindow.ui
@@ -117,7 +117,7 @@
- &River Network
+ &River network
@@ -422,7 +422,7 @@
- Pamhyr configuration
+ Pamhyr2 configuration
@@ -460,10 +460,10 @@
- Numerical parameter for solvers
+ Numerical parameters of solvers
- Numerical parameter for solvers
+ Numerical parameters of solvers
@@ -472,7 +472,7 @@
ressources/boundary_condition.pngressources/boundary_condition.png
- Boundary conditions and punctual contributions
+ Boundary conditions and point sources
@@ -493,7 +493,7 @@
ressources/friction.pngressources/friction.png
- Edit friction
+ Edit frictions
@@ -502,7 +502,7 @@
ressources/lateral_contribution.pngressources/lateral_contribution.png
- Edit lateral contributions
+ Edit lateral sources
@@ -611,7 +611,7 @@
Boundary conditions
- Edit boundary conditions and punctual contributions
+ Edit boundary conditions and point sources
@@ -623,10 +623,10 @@
ressources/lateral_contribution.pngressources/lateral_contribution.png
- Lateral contribution
+ Lateral sources
- Edit lateral contribution
+ Edit lateral sources
@@ -638,7 +638,7 @@
Friction
- Edit frictions
+ Edit friction
@@ -683,7 +683,7 @@
Mage
- Open mage documentation
+ Open Mage documentation
@@ -731,12 +731,12 @@
ressources/boundary_condition.pngressources/boundary_condition.png
- Boundary conditions and punctual contributions
+ Boundary conditions and point sources
- &Additional file
+ &Additional files
diff --git a/src/View/ui/MeshingOptions.ui b/src/View/ui/MeshingOptions.ui
index 6ff87a52..49596584 100644
--- a/src/View/ui/MeshingOptions.ui
+++ b/src/View/ui/MeshingOptions.ui
@@ -33,7 +33,7 @@
-
- Section space step (m)
+ Space step (m)
@@ -111,7 +111,7 @@
-
- Distance computation
+ Guideline used for distance computation
-
@@ -120,7 +120,7 @@
true
- Second guide-line
+ Second guideline
@@ -130,7 +130,7 @@
true
- First guide-line
+ First guideline
@@ -165,7 +165,7 @@
true
- First cross section
+ First cross-section
@@ -186,7 +186,7 @@
true
- Last cross section
+ Last cross-section
diff --git a/src/View/ui/NewStudy.ui b/src/View/ui/NewStudy.ui
index 47b216c1..e087241c 100644
--- a/src/View/ui/NewStudy.ui
+++ b/src/View/ui/NewStudy.ui
@@ -127,7 +127,7 @@
false
- Staring date
+ Starting date
diff --git a/src/View/ui/PurgeOptions.ui b/src/View/ui/PurgeOptions.ui
new file mode 100644
index 00000000..9b027f97
--- /dev/null
+++ b/src/View/ui/PurgeOptions.ui
@@ -0,0 +1,86 @@
+
+
+ Dialog
+
+
+
+ 0
+ 0
+ 194
+ 114
+
+
+
+ Dialog
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+ -
+
+
+ Number of points to keep
+
+
+
-
+
+
+ 3
+
+
+ 999999999
+
+
+ 24
+
+
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ Dialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ Dialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/src/View/ui/REPLineDialog.ui b/src/View/ui/REPLineDialog.ui
index 9d5722ae..25902f3f 100644
--- a/src/View/ui/REPLineDialog.ui
+++ b/src/View/ui/REPLineDialog.ui
@@ -54,7 +54,7 @@
-
- Comment lines start with '*' char (let see the mage documentation for more details)
+ <html><head/><body><p>Comment lines start with '*' char (let see Mage documentation for more details)</p></body></html>
diff --git a/src/View/ui/REPLineList.ui b/src/View/ui/REPLineList.ui
index ea3fe793..b2c71336 100644
--- a/src/View/ui/REPLineList.ui
+++ b/src/View/ui/REPLineList.ui
@@ -37,13 +37,13 @@
- ressources/add.pngressources/gtk-add.png
+ ressources/add.pngressources/add.png
Add
- Add new additional line
+ Add new line
Ctrl+N
@@ -52,7 +52,7 @@
- ressources/del.pngressources/gtk-remove.png
+ ressources/del.pngressources/del.png
Delete
diff --git a/src/View/ui/ReachSedimentLayers.ui b/src/View/ui/ReachSedimentLayers.ui
index dfe39a82..4aaf140d 100644
--- a/src/View/ui/ReachSedimentLayers.ui
+++ b/src/View/ui/ReachSedimentLayers.ui
@@ -35,7 +35,7 @@
-
- Apply sediment layers on all reach
+ Apply sediment layers to all reaches
@@ -80,7 +80,7 @@
Edit profile
- Edit profile sediment layer
+ Edit sediment layers of the profile
diff --git a/src/View/ui/Reservoir.ui b/src/View/ui/Reservoir.ui
index 97e0d7a1..b5f89ff0 100644
--- a/src/View/ui/Reservoir.ui
+++ b/src/View/ui/Reservoir.ui
@@ -99,7 +99,7 @@
Edit
- Edit elevation/surface law
+ Edit stage-area relation
@@ -111,7 +111,7 @@
Sort
- Sort points by elevation
+ Sort points by elevations
diff --git a/src/View/ui/ReservoirList.ui b/src/View/ui/ReservoirList.ui
index c53a7cd6..aecfc26a 100644
--- a/src/View/ui/ReservoirList.ui
+++ b/src/View/ui/ReservoirList.ui
@@ -75,7 +75,7 @@
- ressources/add.pngressources/gtk-add.png
+ ressources/add.pngressources/add.png
Add
@@ -87,7 +87,7 @@
- ressources/del.pngressources/gtk-remove.png
+ ressources/del.pngressources/del.png
Delete
@@ -105,7 +105,7 @@
Edit
- Edit reservoir law
+ Edit reservoir equations
diff --git a/src/View/ui/Results.ui b/src/View/ui/Results.ui
index c7c319a0..0ff198c6 100644
--- a/src/View/ui/Results.ui
+++ b/src/View/ui/Results.ui
@@ -145,7 +145,7 @@
-
- 1
+ 2
@@ -198,7 +198,7 @@
- Hydrograph
+ Discharge time series
-
@@ -251,7 +251,7 @@
Add
- Add custom visualization
+ Add customized visualization
diff --git a/src/View/ui/Stricklers.ui b/src/View/ui/Stricklers.ui
index a7dbd8e9..437ee782 100644
--- a/src/View/ui/Stricklers.ui
+++ b/src/View/ui/Stricklers.ui
@@ -25,7 +25,7 @@
- Study stricklers
+ Strickler coefficients of the study
-
@@ -35,7 +35,7 @@
- Application stricklers
+ Strickler coefficients of the application
-
@@ -70,7 +70,7 @@
Add
- Add new stricklers
+ Add new Strickler coefficients
@@ -82,7 +82,7 @@
Delete
- Delete selected stricklers
+ Delete selected Strickler coefficients
@@ -94,7 +94,7 @@
Sort
- Sort stricklers
+ Sort Strickler coefficients
diff --git a/src/View/ui/UpdateKPOptions.ui b/src/View/ui/UpdateKPOptions.ui
index 881491ba..0f5f1b88 100644
--- a/src/View/ui/UpdateKPOptions.ui
+++ b/src/View/ui/UpdateKPOptions.ui
@@ -6,37 +6,23 @@
0
0
- 340
- 204
+ 381
+ 302
Dialog
+
+ Qt::LeftToRight
+
- -
-
-
- Qt::Horizontal
-
-
- QDialogButtonBox::Cancel|QDialogButtonBox::Ok
-
-
-
-
Distance computation
-
-
-
-
- true
-
-
-
-
@@ -47,11 +33,17 @@
- -
-
-
- true
+
-
+
+
+ Upstream to downstream
+
+ false
+
+
+ buttonGroup_orientation
+
-
@@ -67,20 +59,6 @@
-
- -
-
-
- Origin
-
-
-
- -
-
-
- Origin value
-
-
-
-
@@ -94,9 +72,80 @@
+ -
+
+
+ Origin
+
+
+
+ -
+
+
+ true
+
+
+
+ -
+
+
+ Origin value
+
+
+
+ -
+
+
+ Downstream to upstream
+
+
+ buttonGroup_orientation
+
+
+
+ -
+
+
+ true
+
+
+
+ -
+
+
+ Orientation
+
+
+
+ -
+
+
+ Qt::LeftToRight
+
+
+ Keep current
+
+
+ true
+
+
+ buttonGroup_orientation
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
@@ -134,4 +183,7 @@
+
+
+
diff --git a/src/View/ui/Widgets/MainWindowTabInfo.ui b/src/View/ui/Widgets/MainWindowTabInfo.ui
index 9c09579d..8de4e323 100644
--- a/src/View/ui/Widgets/MainWindowTabInfo.ui
+++ b/src/View/ui/Widgets/MainWindowTabInfo.ui
@@ -182,7 +182,7 @@
-
- Lateral contributions:
+ Lateral sources:
diff --git a/src/View/ui/Widgets/d50sigma.ui b/src/View/ui/Widgets/d50sigma.ui
index d1af908b..5518cbcd 100644
--- a/src/View/ui/Widgets/d50sigma.ui
+++ b/src/View/ui/Widgets/d50sigma.ui
@@ -22,7 +22,7 @@
Qt::Horizontal
-
+
-
@@ -37,13 +37,13 @@
- 4
+ 8
-
+
-
diff --git a/src/View/ui/ressources/icon.ico b/src/View/ui/ressources/icon.ico
new file mode 100644
index 00000000..8b8894aa
Binary files /dev/null and b/src/View/ui/ressources/icon.ico differ
diff --git a/src/lang/fr.ts b/src/lang/fr.ts
index 4b3a4a4d..5c194d35 100644
--- a/src/lang/fr.ts
+++ b/src/lang/fr.ts
@@ -23,14 +23,14 @@
Edit additional file
- Éditer le fichier supplémentaire
+ Modifier le fichier supplémentaire
BasicHydraulicStructures
- Basic Hydraulic Structures
+ Basic Hydraulic Structure
Ouvrage hydraulique élémentaire
@@ -56,7 +56,7 @@
Half-angle tangent
- Tangeante du demi angle
+ Tangeante du demi-angle
@@ -96,7 +96,7 @@
Weir
- Seuil
+ Déversoir
@@ -128,20 +128,15 @@
Parameter 5
Paramètre 5
-
-
- Discharge weir
- Seuil déversoir
-
Trapezoidal weir
- Seuil trapézoidal
+ Déversoir trapézoidal
Triangular weir
- Seuil triangulaire
+ Déversoir triangulaire
@@ -180,16 +175,21 @@
- User defined
+ User-defined
Défini par l'utilisateur
+
+
+ Discharge weir
+
+
BoundaryCondition
Edit boundary conditions
- Éditer les conditions aux limites
+ Modifier les conditions aux limites
@@ -208,7 +208,7 @@
- Ponctual contribution
+ Point sources
Apports ponctuels
@@ -267,49 +267,79 @@
- Mage geometry guide line checker
+ Mage geometry guideline checker
Vérificateur des lignes directrices pour Mage
- Check if exists geometry guide line is correctly defined for each reaches of the study
- Vérifie si les lignes directrices sont définies pour tous les biefs
+ Check if geometry guidelines are correctly defined for each reach
+ Vérifie si les lignes directrices sont définies pour tous les biefs
-
- Study network reach checker
+
+ Study reach network checker
Vérificateur des biefs de l'étude
- Check if exists at least one reach for study
- Vérifie si il existe au moins un bief dans l'étude
+ Check if at least one reach exists
+ Vérifie s'il existe au moins un bief dans l'étude
-
+
Study geometry checker
Vérificateur de géometrie de l'étude
-
- Check if exists geometry for each reach of study
- Vérifie si la géométrie existe pour chaque bief de l'étude
+
+ Check if the geometry of each reach exists
+ Vérifie si la géométrie de chaque bief de l'étude existe
-
+
Dummy ok
Dummy ok
-
+
Dummy warning
Dummy warning
-
+
Dummy error
Dummy error
+
+
+ Study initial conditions checker
+ Vérificateur des conditions initial de l'étude
+
+
+
+ Check initial conditions for each node of study
+ Vérifie les conditions initial de l'étude pour chaque nœud
+
+
+
+ Study boundary conditions checker
+ Vérificateur des conditions aux limites de l'étude
+
+
+
+ Check boundary conditions for each node of study
+ Vérifie les conditions aux limites de l'étude pour chaque nœud
+
+
+
+ Check if exists geometry guidelines are correctly defined for each reach
+ Vérifie si il existe des lignes directrices correctement définie pour chaque bief
+
+
+
+ Check if exists at least one reach exists
+ Vérificateur si il exists au moins un bief
+
Checklist
@@ -414,12 +444,12 @@
CustomPlot
- Custom Plot Selection
+ Custom plot selection
Sélection des graphiques personnalisés
- Bed load elevation (m)
+ Bed elevation (m)
Cote du fond (m)
@@ -434,9 +464,9 @@
Dialog
-
+
Dialog
- Dialog
+ Dialogue
@@ -449,7 +479,7 @@
Type
-
+
Description
Description
@@ -471,7 +501,7 @@
<html><head/><body><p>Command line format, for input formater (optional), solver execution and output formater (optional). This format can use some replacement values like:</p><p>- <span style=" font-style:italic;">@install_dir</span>: The Pamhyr2 install path</p><p>- <span style=" font-style:italic;">@path</span>: The associate path</p><p>- <span style=" font-style:italic;">@input</span>: Solver input data (depend of solver type)</p><p>-<span style=" font-style:italic;"> @output</span>: Solver output data (depend of solver type)</p><p>- <span style=" font-style:italic;">@dir</span>: The working dir at solver execution</p><p>- <span style=" font-style:italic;">@args</span>: Solver arguments and additional arguments defined on solver parameters</p></body></html>
- <html><head/><body><p>Format des lignes de commandes. Ce format peut contenir des valeurs de remplacement, tel que :</p><p>- <span style=" font-style:italic;">@install_dir</span>: Le dossier d'installation de Pamhyr2</p><p>- <span style=" font-style:italic;">@path</span>: Le chemin associé à cette commande</p><p>- <span style=" font-style:italic;">@input</span>: Les données d'entrées du solveur générées par Pamhyr2 (dépend du solveur)</p><p>-<span style=" font-style:italic;"> @output</span>: Les données d'entrées du solveur générées par Pamhyr2 (dépend du solveur)</p><p>- <span style=" font-style:italic;">@dir</span>: Le chemin vers le dossier d'execution du solveur</p><p>- <span style=" font-style:italic;">@args</span>: Arguments du solveur et arguments complémentaires définis dans les paramètres du solveur</p></body></html>
+ <html><head/><body><p>Format des lignes de commandes. Ce format peut contenir des valeurs de remplacement, telles que :</p><p>- <span style=" font-style:italic;">@install_dir</span>: Le dossier d'installation de Pamhyr2</p><p>- <span style=" font-style:italic;">@path</span>: Le chemin associé à cette commande</p><p>- <span style=" font-style:italic;">@input</span>: Les données d'entrées du solveur générées par Pamhyr2 (dépend du solveur)</p><p>-<span style=" font-style:italic;"> @output</span>: Les données d'entrées du solveur générées par Pamhyr2 (dépend du solveur)</p><p>- <span style=" font-style:italic;">@dir</span>: Le chemin vers le dossier d'execution du solveur</p><p>- <span style=" font-style:italic;">@args</span>: Arguments du solveur et arguments complémentaires définis dans les paramètres du solveur</p></body></html>
@@ -506,7 +536,7 @@
Height
- Hauteur
+ Hauteur
@@ -514,62 +544,62 @@
Solveurs
-
+
Backup
Sauvegarde auto
-
+
Auto save
Sauvegarde auto
-
- Frequence
+
+ Frequency
Fréquence
-
+
Enable
Activée
-
+
HH:mm:ss
HH:mm:ss
- Stricklers
- Stricklers
+ Strickler coefficients
+ Coefficients de Strickler
-
+
Editor
Editeur
-
- This value must be used for reading or editing files in speficic case.
+
+ This value must be used for reading or editing files in speficic cases.
Cette valeur peut être utilisée dans des cas spécifiques pour lire ou écrire dans un fichier.
-
+
Editor command
- Commande d'édition
+ Commande d'modification
-
- - The "@file" keyworkd is replace by the path of file to open.
+
+ - The "@file" keyword is replaced by the path of file to open.
- Le mot clef "@file" sera remplacé par le chemin du fichier à ouvrir.
-
+
Language
- Langage
+ Langue
-
+
Please restart application after language modification
Un redémarrage de l'application est requis après le changement de langue
@@ -590,7 +620,7 @@
- Staring date
+ Starting date
Date de départ
@@ -606,7 +636,7 @@
Last modification :
- Date de modification :
+ Dernière modification :
@@ -621,45 +651,45 @@
Discharge
- Débit
+ Débit
-
- First cross section
+
+ First cross-section
Première section en travers
-
- Last cross section
+
+ Last cross-section
Dernière section en travers
-
- First guide line
+
+ First guideline
Première ligne directrice
- Last guide line
- Dernière ligne directrice
+ Last guideline
+ Dernière ligne directrice
- Section space step
+ Space step
Pas d'espace
-
- Distance computation guild line
- Ligne directrice pour le calcule des distances
+
+ Guideline used for distance computation
+ Ligne directrice pour le calcul des distances
-
+
Spline
Spline
-
+
Linear
Linéaire
@@ -690,29 +720,94 @@
- Comment lines start with '*' char (let see the mage documentation for more details)
- Les lignes de commentaire commence pas un charactère '*' (voir la documentation de mage pour plus de détails)
+ Comment lines start with '*' char (let see Mage documentation for more details)
+ Les lignes de commentaire commencent par un caractère '*' (voir la documentation de Mage pour plus de détails)
-
+
Limits
Limites
Options
- Options
+ Options
-
- Section space step (m)
+
+ Space step (m)
Pas d'espace (m)
-
+
Type of interpolation:
Type d'interpolation :
+
+
+ Height (m)
+ Hauteur (m)
+
+
+
+ Stricklers
+ Stricklers
+
+
+
+ Distance computation
+ Calcule des distances
+
+
+
+ Second guide-line
+ Deuxième ligne directrice
+
+
+
+ First guide-line
+ Première ligne directrice
+
+
+
+ Origin
+ Origine
+
+
+
+ Origin value
+ Valeur de l'origine
+
+
+
+ Discharge (m³/s)
+ Débit (m³/s)
+
+
+
+ Parameters
+ Paramètres
+
+
+
+ Langue
+ Langue
+
+
+
+ <html><head/><body><p>Comment lines start with '*' char (let see Mage documentation for more details)</p></body></html>
+ Les lignes de commentaire commencent par un caractère '*' (voir la documentation de Mage pour plus de détails)
+
+
+
+ Second guideline
+ Seconde ligne directrice
+
+
+
+ Discharge (m³/s)
+
+
Documentation
@@ -725,102 +820,102 @@
Exception
-
+
Generic error message
Message d'erreur générique
-
+
Undefined error message
Message d'erreur non définie
-
+
Method not implemented
Méthode non implémentée
-
+
Method
Méthode
-
+
not implemented
non implémenté
-
+
for class
pour la classe
-
+
Not implemented method
Méthode non implémentée
-
+
FileFormatError
ErreurFormatDeFichier
-
+
Invalid file format:
Format de fichier invalide :
-
+
File format error
Erreur de format de fichier
-
+
Invalid file format
Format de fichier invalide
-
+
Invalid file
Fichier invalide
-
+
format because of
format à cause de
-
+
Clipboard format error
Erreur de format dans le presse-papier
-
+
without header
Sans en-tête
-
+
with header
Avec en-tête
-
+
Invalid clipboard data format:
Format des données du presse-papier invalide :
-
+
Clipboard format unknown
Presse-papier format inconnu
-
+
External file dependence is missing
Fichier externe d'une dépendence manquant
-
+
'@file' is missing for module @module:
'@path'
le fichier '@file' est manquant pour le module @module : '@path'
@@ -829,32 +924,32 @@
Form
-
+
Form
Formulaire
-
+
About Pamhyr2
À propos de Pamhyr2
-
+
...
...
-
+
Version: @version
- Version: @version
+ Version : @version
-
+
License: GPLv3+
- Licence: GPLv3+
+ Licence : GPLv3+
-
+
<a href="https://gitlab.irstea.fr/theophile.terraz/pamhyr">Source code</a>
<a href="https://gitlab.irstea.fr/theophile.terraz/pamhyr">Code source</a>
@@ -906,7 +1001,7 @@
River network
- Réseau de la rivière
+ Réseau hydrographique
@@ -985,8 +1080,8 @@
- Lateral contributions:
- Contributions latérales :
+ Lateral sources:
+ Apports latéraux :
@@ -1016,11 +1111,41 @@
Errors summary
- Résumer des erreurs
+ Résumé des erreurs
Frictions
+
+
+ Strickler coefficients
+ Coefficients de Strickler
+
+
+
+ Edit friction coefficients
+ Modifier les frottements
+
+
+
+ Start (m)
+ PK de départ (m)
+
+
+
+ End (m)
+ PK de fin (m)
+
+
+
+ Start coefficient
+ Coefficient de départ
+
+
+
+ End coefficient
+ Coefficient de fin
+
Stricklers
@@ -1029,43 +1154,23 @@
Edit frictions
- Éditer les frottements
-
-
-
- Begin kp (m)
- Pk de départ (m)
-
-
-
- End kp (m)
- Pk de fin (m)
-
-
-
- Begin strickler
- Strickler de départ
-
-
-
- End strickler
- Strickler de fin
+ Éditer les frotements
Geometry
-
+
X (m)
X (m)
-
+
Y (m)
Y (m)
-
+
Z (m)
Z (m)
@@ -1081,71 +1186,71 @@
- File mage geometry (*.ST *.st)
- Fichier géométrie Mage (*.ST *.st)
+ Mage geometry file (*.ST *.st)
+ Fichier Mage de géométrie (*.ST *.st)
- File mage meshed geometry (*.M *.m)
- Fichier géométrie maillée (*.M *.m)
+ Mage meshed geometry file (*.M *.m)
+ Fichier Mage de géométrie maillée (*.M *.m)
-
- All file (*)
+
+ All files (*)
Tous les fichiers (*)
-
+
cross-section
section en travers
-
+
cross-sections
sections en travers
-
+
Transverse abscissa (m)
Abscisse en travers (m)
-
+
Previous cross-section
Section en travers précédente
-
+
Cross-section
Section en travers
-
+
Next cross-section
Section en travers suivante
-
+
Points
Points
First guideline
- Première ligne directrice
+ Première ligne directrice
Second guideline
- Seconde ligne directrice
+ Seconde ligne directrice
- Means between the two guideline
- Moyenne entre les deux lignes directrices
+ Mean over the two guidelines
+ Moyenne sur les deux lignes directrices
-
+
Meshing
Maillage
@@ -1154,11 +1259,6 @@
Geometry cross-section
Géométrie des sections en travers
-
-
- Traversal abs (m)
- Absice en travers (m)
-
upstream
@@ -1169,13 +1269,53 @@
downstream
aval
+
+
+ Shapefile (*.SHP *.shp)
+ Fichier shape (*.SHP *.shp)
+
+
+
+ the first guide-line
+ la première ligne directrice
+
+
+
+ the second guide-line
+ la seconde ligne directrice
+
+
+
+ Width
+ Largeur
+
+
+
+ Area
+ Aire
+
+
+
+ Perimeter
+ Périmètre
+
+
+
+ Traversal abs (m)
+ Abscisse en travers (m)
+
+
+
+ the mean over the two guide-lines
+ la moyenne entre les deux ligne directrice
+
HydraulicStructures
Hydraulic Structures
- Structures hydrauliques
+ Ouvrages hydrauliques
@@ -1205,8 +1345,8 @@
LateralContribution
- Edit lateral contribution
- Éditer les contributions latérales
+ Edit lateral sources
+ Modifier les contributions latérales
@@ -1220,7 +1360,7 @@
- Lateral contribution
+ Lateral sources
Contributions latérales
@@ -1235,44 +1375,44 @@
- Begin kp (m)
- Pk de départ (m)
+ Start (m)
+ PK de départ (m)
- End kp (m)
- Pk de fin (m)
+ End (m)
+ PK de fin (m)
MainWindow
-
+
Open debug window
- Ouvrir la fenêtre de dégogage
+ Ouvrir la fenêtre de débogage
-
+
Open SQLite debuging tool ('sqlitebrowser')
- Ouvrir l'outis de dégogage SQLite ('sqlitebrowser')
+ Ouvrir l'outil de débogage SQLite ('sqlitebrowser')
-
- Activate this window
+
+ Enable this window
Activer cette fenêtre
-
+
MainWindow
Fenêtre principale
-
- toolBar
- Barre d'outils
+
+ Toolbar
+ Barre d'outils
-
+
Add
Ajouter
@@ -1282,52 +1422,52 @@
Ajouter un casier
-
+
Delete
Supprimer
Delete reservoirs
- Supprimer casier(s)
+ Supprimer les casier(s)
-
+
Edit
- Éditer
+ modifier
- Edit reservoir law
- Éditer la loi du(es) casier(s)
+ Edit reservoir equations
+ Modifier la loi des casiers
-
+
Add node or edge
Ajouter un nœud ou une arête
-
+
Remove node or edge
Supprimer un nœud ou une arête
Add sediment layer
- Ajouter une couche sedimentaire
+ Ajouter une couche sédimentaire
Delete sediment layer
- Supprimer une couche sedimentaire
+ Supprimer une couche sédimentaire
Edit sediment layer
- Éditer la couche sedimentaire
+ Modifier la couche sédimentaire
-
+
Ctrl+E
Ctrl+E
@@ -1337,192 +1477,192 @@
PAMHYR
-
+
&File
&Fichier
-
- &River Network
+
+ &River network
&Réseau
-
+
&Geometry
&Géometrie
-
+
&Execute
&Exécuter
-
+
&Hydraulics
&Hydraulique
-
+
&Results
&Résultats
-
+
&Help
&Aide
-
+
Help
Aide
-
+
Pamhyr2
Pamhyr2
-
+
&Sediment
&Sédiment
-
+
&Windows
&Fenêtres
-
+
New study
Nouvelle étude
-
+
Ctrl+N
Ctrl+N
-
+
Open a study
Ouvrir une étude
-
+
Ctrl+O
Ctrl+O
-
+
Close
Fermer
-
+
Close current study
Fermer l'étude en cours
-
+
Save
Sauvegarder
-
+
Save study
Sauvegarder l'étude
-
+
Ctrl+S
Ctrl+S
-
+
Save as ...
Sauvegarder sous ...
-
+
Save study as ...
Sauvegarder l'étude sous ...
-
+
Ctrl+Shift+S
Ctrl+Shift+S
-
- Pamhyr configuration
+
+ Pamhyr2 configuration
Configuration de Pamhyr2
-
+
Quit
Quitter
-
+
Quit application
Quitter l'application
-
+
Ctrl+F4
Ctrl+F4
-
+
Edit river network
- Éditer le réseau
+ Modifier le réseau
-
+
Edit geometry
- Éditer la géométrie
+ Modifier la géométrie
-
+
Import geometry
Importer une géométrie
-
+
Export geometry
Exporter la géométrie
-
- Numerical parameter for solvers
- Paramètres numeriques des solvers
+
+ Numerical parameters of solvers
+ Paramètres numériques des solveurs
-
- Boundary conditions and punctual contributions
- Condition aux limites et apports ponctuels
+
+ Boundary conditions and point sources
+ Conditions aux limites et apports ponctuels
-
+
Initial conditions
Conditions initiales
-
+
Edit friction
- Éditer les frottements
+ Modifier les frottements
-
- Edit lateral contributions
- Éditer les apports latéraux
+
+ Edit lateral sources
+ Modifier les contributions latérales
-
+
Run solver
- Lancer solveur
+ Lancer le solveur
-
+
F5
F5
@@ -1532,167 +1672,162 @@
Ouvrir
-
+
Visualize last results
Visualisation des derniers résultats
-
+
Visualize the last results
- Visualisation des derniers resultats
+ Visualisation des derniers résultats
-
+
About
À propos
-
+
Save current study
Sauvegarder l'étude
-
+
Save the study (Ctrl+S)
Sauvegarde de l'étude (Ctrl+S)
-
+
Close the study (Ctrl+F)
Fermeture de l'étude (Ctrl+F)
-
+
Ctrl+F
Ctrl+F
-
+
Run a solver
Lancer un solveur
-
+
River network
Réseau
-
+
Geometry
Géometrie
-
+
Edit reach geometry
- Éditer la géométrie du bief actuel
+ Modifier la géométrie du bief actuel
-
+
Boundary conditions
Conditions aux limites
-
- Edit boundary conditions and punctual contributions
- Éditer les conditions aux limites et les apports ponctuels
+
+ Edit boundary conditions and point sources
+ Modifier les conditions aux limites et les apports ponctuels
-
- Lateral contribution
+
+ Lateral sources
Contributions latérales
-
- Edit lateral contribution
- Éditer les contributions latérales
-
-
-
+
Friction
Frottements
- Edit friction frictions
- Éditer les frottements
+ Edit friction coefficients
+ Modifier les frottements
-
+
Edit study
- Éditer l'étude
+ Modifier l'étude
Edit the study metadata
- Éditer les informations de l'étude
+ Modifier les informations de l'étude
-
+
Define initial conditions
Définir les conditions initiales
-
+
Sediment layers
- Couche sédimentaires
+ Couches sédimentaires
-
+
Define sediment layers
Définition des couches sédimentaires
-
+
Edit reach sediment layers
- Éditer les couches sédimentaires
+ Modifier les couches sédimentaires
-
+
Mage
Mage
-
- Open mage documentation
- Ouvrir la domumentation de mage
+
+ Open Mage documentation
+ Ouvrir la documentation de Mage
-
+
Users (wiki)
Utilisateurs (wiki)
-
+
Developers (pdf)
- Développeur (pdf)
+ Développeurs (pdf)
-
+
Developers (html)
- Développeur (html)
+ Développeurs (html)
-
+
Reservoirs
Casiers
-
+
Edit reservoirs
- Éditer les casiers
+ Modifier les casiers
-
+
Hydraulic structures
- Structures hydraulique
+ Ouvrages hydrauliques
-
+
Edit hydraulic structures
- Éditer les structures hydraulique
+ Modifier les ouvrages hydrauliques
-
+
Open results from file
Ouvrir des résultats depuis un fichier
@@ -1708,11 +1843,11 @@
- Eval
+ Evaluate
Évaluer
-
+
Ctrl+Return
Ctrl+Return
@@ -1724,10 +1859,10 @@
Delete selected sediment layer(s)
- Supprimer la(les) couche(s) sédimentaire(s) sélectionnée(s)
+ Supprimer les couches sédimentaires sélectionnées
-
+
Ctrl+D
Ctrl+D
@@ -1753,68 +1888,68 @@
- Suspenssion
+ Suspension
Suspension
- Add a new boundary condition or lateral contribution
- Ajouter une condition aux limites ou un apport ponctuel
+ Add a new boundary condition or lateral source
+ Ajouter une condition aux limites ou un apport latéral
-
+
Delete current selected rows
Supprimer les lignes selectionnées
- Edit boundary condition or lateral contribution
- Éditer une condition aux limites ou un apport ponctuel
+ Edit boundary condition or lateral source
+ Modifier une condition aux limites ou un apport latéral
-
+
Sort
Trier
- Sort boundary condition by name
+ Sort by names
Trier par nom
- Study stricklers
- Stricklers de l'étude
+ Strickler coefficients of the study
+ Coefficients de Strickler de l'étude
- Application stricklers
- Stricklers de l'application
+ Strickler coefficients of the application
+ Coefficients de Strickler de l'application
- Add new stricklers
- Ajouter un Strickler
+ Add new Strickler coefficients
+ Ajouter un coefficient de Strickler
- Delete selected stricklers
- Supprimer les Stricklers selectionnés
+ Delete selected Strickler coefficients
+ Supprimer les coefficients de Strickler selectionnés
- Sort stricklers
- Trier les Stricklers
+ Sort Strickler coefficients
+ Trier les coefficients de Strickler
- Add a new boundary condition or punctual contribution
+ Add a new boundary condition or point source
Ajouter une condition aux limites ou un apport ponctuel
- Edit boundary condition or punctual contribution
- Éditer une condition aux limites ou un apport ponctuel
+ Edit boundary condition or point source
+ Modifier une condition aux limites ou un apport ponctuel
@@ -1828,38 +1963,38 @@
- Hydrograph
+ Discharge time series
Hydrogramme
- Add custom visualization
+ Add customized visualization
Ajouter une visualisation personnalisée
-
+
Reload
Recharger
-
+
Export
Exporter
-
+
Export raw data
Exporter les données brutes
-
+
delete
supprimer
-
- Edit stricklers
- Éditer des stricklers
+
+ Edit Strickler coefficients
+ Modifier les coefficients de Strickler
@@ -1899,32 +2034,32 @@
Basic hydraulic structures
- Ouvrages hydrauliques élémentaire
+ Ouvrages hydrauliques élémentaires
Enable / Disable basic hydraulic structure
- Activer/Déactiver l'ouvrage hydraulique élémentaire
+ Activer/Désactiver l'ouvrage hydraulique élémentaire
-
+
Add a new point
- Add a new point
+ Ajouter un nouveau point
Delete points
- Supprimer points
+ Supprimer les points
-
+
Edit selected hydraulic structure
- Éditer l'ouvrage hydraulique sélectionné
+ Modifier l'ouvrage hydraulique sélectionné
Stop
- Stoper
+ Arrêter
@@ -1944,45 +2079,40 @@
results
- resultats
-
-
-
- add
- Ajouter
+ résultats
- Add a point on cross-section
+ Add a point to cross-section
Ajouter un point à la section en travers
Delete selected point(s)
- Supprimer le(s) point(s) sélectionné(s)
+ Supprimer les points sélectionnés
-
- up
+
+ Up
Monter
Move up selected point(s)
- Déplacer le point sélectionné vers le haut
+ Déplacer les points sélectionnés vers le haut
-
- down
+
+ Down
Descendre
- Mode down selected point(s)
- Déplacer le point sélectionné vers le bas
+ Move down selected point(s)
+ Déplacer les points sélectionnés vers le bas
-
+
sort_asc
sort_asc
@@ -1992,49 +2122,49 @@
Trier les points par leurs plus proches voisins
-
+
sort_des
sort_des
Sort reversed points by nearest neighbor
- Trie inverser les points par leurs plus proche voisins
+ Trier/inverser les points par leurs plus proches voisins
Enable / Disable hydraulic structure
- Activer/Déactiver l'ouvrage hydraulique
+ Activer/Désactiver l'ouvrage hydraulique
- Edit elevation/surface law
- Éditer loi élévation/surface
+ Edit stage-area relation
+ Modifier loi cote/surface
- Sort points by elevation
- Trier les points par leur cote
+ Sort points by elevations
+ Trier les points par cote
-
+
Edit sediment layers list
- Éditer la liste des couches sédimentaires
+ Modifier la liste des couches sédimentaires
- Apply sediment layers on all reach
+ Apply sediment layers to all reaches
Appliquer une liste de couches sédimentaires
Edit profile
- Éditer le profil
+ Modifier le profil
- Edit profile sediment layer
- Éditer les couches sédimentaires du profil
+ Edit sediment layers of the profile
+ Modifier les couches sédimentaires du profil
@@ -2044,57 +2174,52 @@
Generate from discharge
- Générer pour un débit donnée
+ Générer pour un débit donné
-
+
Add new initial condition
Ajouter une nouvelle condition initiale
-
+
Delete inital condition
Supprimer une condition initiale
-
+
sort
sort
-
- Sort inital condition
+
+ Sort inital conditions
Trier les conditions initiales
-
- Add a new point in boundary condition or punctual contribution
- Ajouter un nouveau point
+
+ Add a new point in boundary condition or point source
+ Ajouter un nouveau point
Sort boundary condition points
- Trier les points des conditions aux limites
+ Trier les points des conditions aux limites
- Add a new point in boundary condition or lateral contribution
+ Add a new point in boundary condition or lateral source
Ajouter un nouveau point
-
-
- Sort boundary condition point
- Trier les points des conditions aux limites
-
Add sediment layers
- Ajouter une couche sedimentaire
+ Ajouter une couche sédimentaire
Add specific sediment layers on selected point(s)
- Ajouter des couches spécifiques au(x) point(s) sélectionné(s)
+ Ajouter des couches spécifiques aux points sélectionnés
@@ -2104,97 +2229,92 @@
Delete specific sediment layers of selected point(s)
- Supprimer les couches sédimentaires au(x) point(s) sélectionné(s)
+ Supprimer les couches sédimentaires aux points sélectionnés
Edit sediment layers
- Éditer les couches sédimentaires
+ Modifier les couches sédimentaires
-
+
Import
Importer
-
+
Add a cross-section
Ajouter une section en travers
-
+
Delete selected cross-section(s)
- Supprimer la(es) section(s) en travers sélectionnée(s)
+ Supprimer les sections en travers sélectionnées
-
- edit
- éditer
-
-
-
+
Edit selected cross section(s)
- Éditer la(es) section(s) en travers sélectionnée(s)
+ Modifier les sections en travers sélectionnées
-
- Sort cross-sections by ascending KP
+
+ Sort cross-sections by ascending position
Trier les sections en travers par PK croissant
-
- Sort cross-sections by descending KP
+
+ Sort cross-sections by descending position
Trier les sections en travers par PK décroissant
-
+
Move up selected cross-section(s)
- Déplacer la(s) section(s) en travers vers le haut
+ Déplacer les sections en travers vers le haut
-
+
Move down selected cross-section(s)
- Déplacer la(es) section(s) en travers vers le bas
+ Déplacer les sections en travers vers le bas
-
+
Meshing
Maillage
-
+
Summary
- Résumer
+ Résumé
-
+
Checks
Vérifications
-
- &Advansed
+
+ &Advanced
&Avancé
-
- &Additional file
- Fichiers &supplémentaire
+
+ &Additional files
+ Fichiers &supplémentaires
-
+
REP additional lines
- Lines REP supplémentaire
+ Lignes REP supplémentaires
- Add new additional line
+ Add new line
Ajouter une nouvelle ligne
Delete additional line(s)
- Supprimer la(es) ligne(s) supplementaire
+ Supprimer les lignes supplementaires
@@ -2204,7 +2324,7 @@
Edit selected line(s)
- Éditer la(es) ligne(s) selectionnée(s)
+ Modifier les lignes selectionnées
@@ -2214,7 +2334,7 @@
File text
- Text du fichiers
+ Texte du fichier
@@ -2229,7 +2349,7 @@
The relative file path on executable directory
- Le chemin relatif du fichier dans le répertoire d'execution
+ Le chemin relatif du fichier dans le répertoire d'exécution
@@ -2249,84 +2369,84 @@
Delete selected file(s)
- Supprimer le(s) fichier(s) selectionné(s)
+ Supprimer les fichiers sélectionnés
Edit file
- Éditer fichier
+ Modifier fichier
-
+
Edit the study information
- Éditer les information de l'étude
+ Modifier les informations de l'étude
-
- Update KP
+
+ toolBar
-
- Recompute KP
+
+ toolBar_2
-
+
+ Edit frictions
+ Éditer les frotements
+
+
+
Purge
-
-
-
-
- Purge cross-sections to keep a given number of points
-
+ Purger
Purge the cross-section to keep a given number of points
-
+ Purger les profiles pour garder qu'un nombre donné de points
Reverse
-
+ Retourner
Reverse the points order
-
-
-
-
- MainWindowProfile
-
-
- La cote du fond
- Z minimale
-
+ Retourner l'ordre des points
-
- La cote maximale
- Z maximale
-
+
+ Import from file
+ Importer depuis un fichier
-
- Rive gauche
-
+
+ Update KP
+ Mise à jour des PK
-
- Rive droite
-
+
+ Recompute KP
+ Recalcule des PK
+
+
+
+ Purge cross-sections to keep a given number of points
+ Purger les profiles pour garder un nombre fixer de points
+
+
+
+ Sort points
+ Trier les points
MainWindow_reach
- Kp (m)
+ Position (m)
Pk (m)
@@ -2340,7 +2460,7 @@
X (m)
-
+
Select destination file
Selectionner fichier de destination
@@ -2365,7 +2485,7 @@
Edit node reservoir
- Éditer le casier du nœud
+ Modifier le casier du nœud
@@ -2380,17 +2500,17 @@
Enable the reach
- Activer l'arrête
+ Activer l'arête
Disable the reach
- Déactiver l'arrête
+ Désactiver l'arête
Reverse the reach orientation
- Inverser l'orientation de l'arrête
+ Inverser l'orientation de l'arête
@@ -2426,7 +2546,7 @@
Edit Mage REP lines
- Éditer le lignes REP Mage
+ Modifier les lignes REP Mage
@@ -2444,7 +2564,7 @@
Edit Reservoir
- Éditer le casier
+ Modifier le casier
@@ -2545,7 +2665,7 @@
Edit Sediment Layers
- Éditer les couches sédimentaires
+ Modifier les couches sédimentaires
@@ -2600,12 +2720,12 @@
Apply sediment layers to reach
- Appliquer des couches sédimentaire au bief
+ Appliquer des couches sédimentaires au bief
Sediment Layers List
- Liste des ensembles de couches sedimentaires
+ Liste des ensembles de couches sédimentaires
@@ -2623,7 +2743,7 @@
Solver logs
- Selection des logs
+ Sélection des logs
@@ -2691,7 +2811,7 @@
Implicitation parameter
- Parametre d'implicitation
+ Paramètre d'implicitation
@@ -2730,7 +2850,7 @@
- Maximun number of iterations (< 100)
+ Maximum number of iterations (< 100)
Nombre maximum d'itérations (< 100)
@@ -2755,12 +2875,12 @@
- Number of iteration at maximum precision
+ Number of iterations at maximum precision
Nombre d'itérations à la précision maximum
- Number of iteration before switch
+ Number of iterations before switch
Nombre d'itérations avant changement
@@ -2791,7 +2911,7 @@
Use Mage internal initialization (Y/N)
- Utiliser l'initialisation interne de mage (O/N)
+ Utiliser l'initialisation interne de Mage (O/N)
@@ -2830,8 +2950,8 @@
- Critic shields
- Shields critique
+ Critical Shields number
+ Nombre de Shields critique
@@ -2856,10 +2976,15 @@
Stricklers
+
+
+ Strickler coefficients
+ Coefficient de Strickler
+
Stricklers
- Stricklers
+ Stricklers
@@ -2867,7 +2992,7 @@
Edit study
- Éditer l'étude
+ Modifier l'étude
@@ -2878,43 +3003,43 @@
Toolbar
-
+
Default view
Vue par défaut
-
+
Back to previous view
Retour à la vue précédente
-
- Return to next view
+
+ Back to next view
Retour à la vue suivante
-
- Axes panoramic
+
+ Panoramic axes
Axes panoramiques
-
+
Zoom
Zoom
-
+
Isometric view (Shift+W)
Vue isométrique (Shift+W)
-
+
Auto scale view (Shift+X)
Vue automatique (Shift+X)
-
- Save the figure
+
+ Save figure
Sauvegarder la figure
@@ -2922,7 +3047,7 @@
Unit
- KP (m)
+ Position (m)
PK (m)
@@ -2956,27 +3081,27 @@
Cote de l'eau (m)
-
+
Area (hectare)
Aire (hectare)
-
+
Time (sec)
- Temps (sec)
+ Temps (s)
-
+
Time (JJJ:HH:MM:SS)
Temps (JJJ:HH:MM:SS)
-
+
Date (sec)
- Date (sec)
+ Date (s)
-
+
Date (ISO format)
Date (format ISO)
@@ -2985,8 +3110,13 @@
Discharge (m³/s)
Débit (m³/s)
-
+
+ Speed (m/s)
+ Vitesse (m/s)
+
+
+
Discharge (m³/s)