diff --git a/doc/dev/documentation.org b/doc/dev/documentation.org index 94768e8a97e954f3c0bf5f44962ddd15b8b82dd6..28fad83926138762f693f6c2e408bf75806b86a2 100644 --- a/doc/dev/documentation.org +++ b/doc/dev/documentation.org @@ -456,6 +456,15 @@ of Bar (Listing [[sql-bar]] and [[sql-foo]]). bar._sql_save(execute, data=data) #+end_src +Let see the results database scheme for Pamhyr2 at version v0.0.7 in +Figure [[sql_schema]]. + +#+NAME: sql_schema +#+ATTR_LATEX: :width 16cm +#+CAPTION: SQLite database scheme at Pamhyr2 version v0.0.7 (generate with [[https://gitlab.com/Screwtapello/sqlite-schema-diagram]]) +[[./images/schema_v0.0.7.png]] + + [fn:sqlite] The SQLite web site: https://www.sqlite.org/index.html (last access 2023-09-20) diff --git a/doc/dev/images/schema_v0.0.7.png b/doc/dev/images/schema_v0.0.7.png new file mode 100644 index 0000000000000000000000000000000000000000..a09da69f67cde4569c3bcf10e0db4313594c61ef Binary files /dev/null and b/doc/dev/images/schema_v0.0.7.png differ diff --git a/src/Meshing/Mage.py b/src/Meshing/Mage.py index 393de9c495085c9f6dbc16df016e2a0bb1b8ce1d..9ce8f357e72c4e3124816ee8462e9d20ac8d5850 100644 --- a/src/Meshing/Mage.py +++ b/src/Meshing/Mage.py @@ -306,8 +306,6 @@ class MeshingWithMageMailleurTT(AMeshingTool): st_file = self.export_reach_to_st(reach, tmp) m_file = st_file.rsplit(".ST", 1)[0] + ".M" - os.sync() - proc = QProcess() proc.setWorkingDirectory(tmp) diff --git a/src/Model/Geometry/PointXYZ.py b/src/Model/Geometry/PointXYZ.py index cf678c24f26e6f25e9ff728406971c94e405c2e9..9ba79e66f59e376e36011dccea265e3bb88a40ad 100644 --- a/src/Model/Geometry/PointXYZ.py +++ b/src/Model/Geometry/PointXYZ.py @@ -47,7 +47,7 @@ class PointXYZ(Point, SQLSubModel): z INTEGER NOT NULL, profile INTEGER NOT NULL, sl INTEGER, - FOREIGN KEY(profile) REFERENCES profileXYZ(id), + FOREIGN KEY(profile) REFERENCES geometry_profileXYZ(id), FOREIGN KEY(sl) REFERENCES sedimentary_layer(id) ) """) @@ -220,3 +220,11 @@ class PointXYZ(Point, SQLSubModel): Euclidean 3D distance between the two points """ return dist((p1.x, p1.y, p1.z), (p2.x, p2.y, p2.z)) + + @staticmethod + def areatriangle3d(p1, p2, p3): + a = PointXYZ.distance(p1, p2) + b = PointXYZ.distance(p2, p3) + c = PointXYZ.distance(p3, p1) + s = (a + b + c) / 2 + return (s*(s-a) * (s-b)*(s-c)) ** 0.5 diff --git a/src/Model/Geometry/Profile.py b/src/Model/Geometry/Profile.py index 33741eaa63699730e10247b285223e55f6b6f1da..17bf5c605f0079b5ce4a78c7b9f4ba3227a3401d 100644 --- a/src/Model/Geometry/Profile.py +++ b/src/Model/Geometry/Profile.py @@ -296,6 +296,11 @@ class Profile(object): ) self._status.modified() + @timer + def reverse(self): + self._points.reverse() + self._status.modified() + # Sediment Layers def get_sl(self): diff --git a/src/Model/Geometry/ProfileXYZ.py b/src/Model/Geometry/ProfileXYZ.py index 6b3449946450c2f58b1c18284809c75397f3a47c..0bd8d83db408da1b44f9c78e9063e4099a964f55 100644 --- a/src/Model/Geometry/ProfileXYZ.py +++ b/src/Model/Geometry/ProfileXYZ.py @@ -578,3 +578,32 @@ class ProfileXYZ(Profile, SQLSubModel): break return last_point + + def purge(self, np_purge): + """ + Remove points to keep at most np_purge points. + """ + + if (self.nb_points <= np_purge): return + + nb_named = 2 # we consider the first and last point as named + area = [0.0] + for i in range(1, self.nb_points-1): + if self.point(i).point_is_named(): + area.append(9999999.999) + nb_named += 1 + else: + area.append(PointXYZ.areatriangle3d(self.point(i-1),self.point(i),self.point(i+1))) + area.append(0.0) + + while (self.nb_points > max(np_purge, nb_named)): + to_rm = np.argmin(area[1:self.nb_points-1])+1 + self.delete_i([to_rm]) + area.pop(to_rm) + for i in [to_rm-1, to_rm]: + if (i == 0): continue + if (i == self.nb_points - 1): continue + if self.point(i).point_is_named(): + area[i] = 9999999.999 + else: + area[i] = PointXYZ.areatriangle3d(self.point(i-1),self.point(i),self.point(i+1)) diff --git a/src/Solver/CommandLine.py b/src/Solver/CommandLine.py index 4afcbc9a24a91c49d640e33bdb4a06a2812b1100..5f706d1a2772b25e6f10f82bd512bb7c574aaf78 100644 --- a/src/Solver/CommandLine.py +++ b/src/Solver/CommandLine.py @@ -167,8 +167,10 @@ class CommandLineSolver(AbstractSolver): repertory, "pamhyr-study-description.txt" ) - with open(path, "w+") as f: - txt = study.description + with open(path, "w+", encoding='utf-8') as f: + txt = study.description\ + .encode()\ + .decode('utf-8', 'replace') f.write(txt) ####### diff --git a/src/Solver/Mage.py b/src/Solver/Mage.py index f8b664fd7f586cc6380953ff46437b0382fe6d8a..ea1c763532aeb0aa87aeda12fbb36c3d3fc604fe 100644 --- a/src/Solver/Mage.py +++ b/src/Solver/Mage.py @@ -282,6 +282,9 @@ class Mage(CommandLineSolver): if bound.node is None: continue + if not study.river.is_enable_node(bound.node): + continue + if bound.bctype == "ZD": AVA.append(bound) elif bound.bctype == "TD" or bound.bctype == "PC": @@ -357,13 +360,7 @@ class Mage(CommandLineSolver): with mage_file_open(os.path.join(repertory, f"{name}.RUG"), "w+") as f: files.append(f"{name}.RUG") - edges = study.river.edges() - edges = list( - filter( - lambda e: e.is_enable(), - edges - ) - ) + edges = study.river.enable_edges() id = 1 for edge in edges: @@ -495,6 +492,9 @@ class Mage(CommandLineSolver): if not hs.input_reach.is_enable(): continue + if not hs.enabled: + continue + if hs.input_kp is None: continue @@ -510,25 +510,26 @@ class Mage(CommandLineSolver): def _export_SIN_bhs(self, study, sin_dict, hs, f): for bhs in hs.basic_structures: - reach_id = study.river.get_edge_id(hs.input_reach) + 1 - param_str = ' '.join( - [ - f'{p:>10.3f}' - for p in self._export_SIN_parameters(bhs) - ] - ) + if bhs.enabled: + reach_id = study.river.get_edge_id(hs.input_reach) + 1 + param_str = ' '.join( + [ + f'{p:>10.3f}' + for p in self._export_SIN_parameters(bhs) + ] + ) - name = bhs.name - if name == "": - name = f"HS_{bhs.id:>3}".replace(" ", "0") - else: - name = name.replace(" ", "_") + name = bhs.name + if name == "": + name = f"HS_{bhs.id:>3}".replace(" ", "0") + else: + name = name.replace(" ", "_") - f.write( - f"{sin_dict[bhs._type]} " + - f"{reach_id} {float(hs.input_kp):>12.3f} " + - f"{param_str} {name}\n" - ) + f.write( + f"{sin_dict[bhs._type]} " + + f"{reach_id} {float(hs.input_kp):>12.3f} " + + f"{param_str} {name}\n" + ) def _export_SIN_parameters(self, bhs): res = [9999.999] * 5 @@ -802,7 +803,7 @@ class Mage8(Mage): value = "O" if value.lower() == "y" else "N" if name == "init_internal": - value = ("p" if value.lower() in ["y", "yes", "true"] + value = ("p" if value.lower() in ["y", "yes", "true", "o"] else "") logger.debug( diff --git a/src/View/Geometry/PlotAC.py b/src/View/Geometry/PlotAC.py index 24567bef97f50b131c4dbc6d5c0e7ebdfb0c4bfa..cccffe24b750761066a2e1607bd408c13b5ffb31 100644 --- a/src/View/Geometry/PlotAC.py +++ b/src/View/Geometry/PlotAC.py @@ -129,7 +129,7 @@ class PlotAC(PamhyrPlot): if txt.strip() in self.complete_gl: color = self.color_complete_gl[ - lcomplete.index(txt) + lcomplete.index(txt) % len(self.color_complete_gl) ] else: color = self.color_incomplete_gl[ diff --git a/src/View/Geometry/PlotKPZ.py b/src/View/Geometry/PlotKPZ.py index 35e9ffabe00cd420a18f8443cdeec8312c462b89..f4dbd7907024086339533d376fd9324fd8967f08 100644 --- a/src/View/Geometry/PlotKPZ.py +++ b/src/View/Geometry/PlotKPZ.py @@ -167,7 +167,9 @@ class PlotKPZ(PamhyrPlot): self.line_kp_zgl.append( self.canvas.axes.plot( - kp, z, lw=1., color=self.colors[ind] + kp, z, lw=1., + color=self.colors[ind % len(self.colors)], + linestyle=self.linestyle[ind // len(self.colors)] ) ) ind += 1 diff --git a/src/View/Geometry/PlotXY.py b/src/View/Geometry/PlotXY.py index 6c3a37077eed983c873fddfbc2620e5ab855336d..baa46d26af2e99e8686fa2d8cd292365eb9fa83b 100644 --- a/src/View/Geometry/PlotXY.py +++ b/src/View/Geometry/PlotXY.py @@ -130,7 +130,8 @@ class PlotXY(PamhyrPlot): self.line_gl = [] for x, y in zip(x_complete, y_complete): line = self.canvas.axes.plot( - x, y, color=self.colors[ind] + x, y, color=self.colors[ind % len(self.colors)], + linestyle=self.linestyle[ind // len(self.colors)] ) self.line_gl.append(line) ind += 1 diff --git a/src/View/Geometry/Profile/Table.py b/src/View/Geometry/Profile/Table.py index c23eeb6f803b115b9c95ef8017e3b2316a19a1e4..21e202f8ee9fafffe0d4bec3b275355592118f0c 100644 --- a/src/View/Geometry/Profile/Table.py +++ b/src/View/Geometry/Profile/Table.py @@ -250,6 +250,26 @@ class GeometryProfileTableModel(PamhyrTableModel): self.endMoveRows() self.layoutChanged.emit() + def purge(self): + + self._undo.push( + PurgeCommand( + self._data, 24 + ) + ) + + self.layoutChanged.emit() + + def reverse(self): + + self._undo.push( + ReverseCommand( + self._data + ) + ) + + self.layoutChanged.emit() + def paste(self, row, header, data): if row > self._data.number_points: return diff --git a/src/View/Geometry/Profile/UndoCommand.py b/src/View/Geometry/Profile/UndoCommand.py index 800bd4e0bac1fd346eace58eb0815a2c51c8d3c3..a381feee20bcc1ca8b946c9c1e55d931b83965d5 100644 --- a/src/View/Geometry/Profile/UndoCommand.py +++ b/src/View/Geometry/Profile/UndoCommand.py @@ -169,6 +169,34 @@ class MoveCommand(QUndoCommand): self._profile.move_down_point(self._i) +class ReverseCommand(QUndoCommand): + def __init__(self, profile): + QUndoCommand.__init__(self) + + self._profile = profile + + def undo(self): + self._profile.reverse() + + def redo(self): + self._profile.reverse() + + +class PurgeCommand(QUndoCommand): + def __init__(self, profile, np_purge): + QUndoCommand.__init__(self) + + self._profile = profile + self._old = self._profile.points.copy() + self._np_purge = np_purge + + def undo(self): + self._profile._points = self._old.copy() + + def redo(self): + self._profile.purge(self._np_purge) + + class PasteCommand(QUndoCommand): def __init__(self, profile, row, points): QUndoCommand.__init__(self) diff --git a/src/View/Geometry/Profile/Window.py b/src/View/Geometry/Profile/Window.py index d8f2da07b29c00cec93e1583c35af59e6684d1da..504eb25f3b5575ea7ea3477f2e177df0046c8fcb 100644 --- a/src/View/Geometry/Profile/Window.py +++ b/src/View/Geometry/Profile/Window.py @@ -125,6 +125,8 @@ class ProfileWindow(PamhyrWindow): "action_down": self.move_down, "action_add": self.add, "action_delete": self.delete, + "action_purge": self.purge, + "action_reverse": self.reverse, } for action in actions: @@ -146,6 +148,12 @@ class ProfileWindow(PamhyrWindow): self.update_plot() self._propagate_update(key=Modules.GEOMETRY) + def _update(self, redraw=False, propagate=True): + if redraw: + self.update_plot() + if propagate: + self._propagate_update(key=Modules.GEOMETRY) + def update_plot(self): self._tablemodel.blockSignals(True) @@ -153,6 +161,14 @@ class ProfileWindow(PamhyrWindow): self._tablemodel.blockSignals(False) + def _propagated_update(self, key=Modules(0)): + if Modules.GEOMETRY not in key: + return + + print("=====TOTO=====") + self._tablemodel.layoutChanged.emit() + self._update(redraw=True, propagate=False) + def index_selected_row(self): table = self.find(QTableView, "tableView") rows = table.selectionModel()\ @@ -238,6 +254,14 @@ class ProfileWindow(PamhyrWindow): self.update() + def purge(self): + self._tablemodel.purge() + self.update() + + def reverse(self): + self._tablemodel.reverse() + self.update() + def _copy(self): table = self.find(QTableView, "tableView") rows = table.selectionModel().selectedRows() diff --git a/src/View/Geometry/Table.py b/src/View/Geometry/Table.py index 169771cbd98e6a14148ed1a2bee3f01b58fb0bb2..26baa7fb23d84d33a5b7971e7169f1c19f007ed9 100644 --- a/src/View/Geometry/Table.py +++ b/src/View/Geometry/Table.py @@ -246,3 +246,12 @@ class GeometryReachTableModel(PamhyrTableModel): self.layoutAboutToBeChanged.emit() self.layoutChanged.emit() + + def purge(self): + + self._undo.push( + PurgeCommand( + self._data, 24 + ) + ) + self.layoutChanged.emit() diff --git a/src/View/Geometry/UndoCommand.py b/src/View/Geometry/UndoCommand.py index f1d181f53086f0b526b49a774ba2d24a055ba0e9..e5d488851a0e62f6b010090707dee1e3a669fd49 100644 --- a/src/View/Geometry/UndoCommand.py +++ b/src/View/Geometry/UndoCommand.py @@ -254,3 +254,23 @@ class MeshingCommand(QUndoCommand): for profile in self._new_profiles: self._reach.insert_profile(0, profile) + + +class PurgeCommand(QUndoCommand): + def __init__(self, reach, np_purge): + QUndoCommand.__init__(self) + + self._reach = reach + self._np_purge = np_purge + + self._old = [] + for profile in self._reach.profiles: + self._old.append(profile.points.copy()) + + def undo(self): + for i in range(self._reach.number_profiles): + self._reach.profiles[i]._points = self._old[i].copy() + + def redo(self): + for profile in self._reach._profiles: + profile.purge(self._np_purge) diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index d63bf9297cedae83edc9312b6f735447abb13130..302237a3fbdde83bf5b01fd045d9a9fd2ed5c9e2 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -188,6 +188,8 @@ class GeometryWindow(PamhyrWindow): "action_delete": self.delete, "action_edit": self.edit_profile, "action_meshing": self.edit_meshing, + "action_update_kp": self.update_kp, + "action_purge": self.purge, } for action in actions: @@ -227,7 +229,7 @@ class GeometryWindow(PamhyrWindow): self._propagate_update(key=Modules.GEOMETRY) def _propagated_update(self, key=Modules(0)): - if Modules.NETWORK not in key: + if Modules.NETWORK not in key and Modules.GEOMETRY not in key: return self._update(propagate=False) @@ -507,6 +509,13 @@ class GeometryWindow(PamhyrWindow): self._table.move_down(row) self.select_current_profile() + def update_kp(self): + pass + + def purge(self): + self._table.purge() + self.update_redraw() + def duplicate(self): rows = [ row.row() for row in diff --git a/src/View/HydraulicStructures/BasicHydraulicStructures/Window.py b/src/View/HydraulicStructures/BasicHydraulicStructures/Window.py index 93ef8a37564ac4bcc9aee1eb07e84fa9288f574e..9a39f49c64749b995b3ac3733038ee0e720003b5 100644 --- a/src/View/HydraulicStructures/BasicHydraulicStructures/Window.py +++ b/src/View/HydraulicStructures/BasicHydraulicStructures/Window.py @@ -252,13 +252,14 @@ class BasicHydraulicStructuresWindow(PamhyrWindow): self._checkbox.setChecked(self._hs.basic_structure(row).enabled) def _set_basic_structure_state(self): - row = self.index_selected_row() - - if row is not None: - self._table.enabled( - row, - self._checkbox.isChecked() - ) + rows = self.index_selected_rows() + if len(rows) != 0: + for row in rows: + if row is not None: + self._table.enabled( + row, + self._checkbox.isChecked() + ) def update(self): self._set_checkbox_state() diff --git a/src/View/HydraulicStructures/Window.py b/src/View/HydraulicStructures/Window.py index ff290d7a6e95ae127ad0ea8f2b7f7cbdaa598318..1c6af72c6803393728312dd9632352033a39da40 100644 --- a/src/View/HydraulicStructures/Window.py +++ b/src/View/HydraulicStructures/Window.py @@ -262,12 +262,14 @@ class HydraulicStructuresWindow(PamhyrWindow): self._checkbox.setChecked(self._hs_lst.get(row).enabled) def _set_structure_state(self): - row = self.index_selected_row() - if row is not None: - self._table.enabled( - row, - self._checkbox.isChecked() - ) + rows = self.index_selected_rows() + if len(rows) != 0: + for row in rows: + if row is not None: + self._table.enabled( + row, + self._checkbox.isChecked() + ) def update(self): self._set_checkbox_state() diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index f4d8bad7fbe785ef4b198f2c13f4ab07f60599f0..ca6371a524815bb6a59baae5abb0f7ae02fdc6d1 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -445,9 +445,15 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): logger.debug(f"Propagation of {keys}") for _, window in self.sub_win_list: window._propagated_update(key=keys) + self._do_propagate_update_rec(window, keys) self._tab_widget_checker.update(modules=keys) + def _do_propagate_update_rec(self, window, keys): + for _, win in window.sub_win_list: + win._propagated_update(key=keys) + self._do_propagate_update_rec(win, keys) + def update(self): self.set_title() diff --git a/src/View/Results/CustomPlot/Plot.py b/src/View/Results/CustomPlot/Plot.py index e490339d56c5b9f4ab43906fce2d7831b91d93d8..91770042de361ba0c094d14f74267c11c7397a87 100644 --- a/src/View/Results/CustomPlot/Plot.py +++ b/src/View/Results/CustomPlot/Plot.py @@ -77,9 +77,9 @@ class CustomPlot(PamhyrPlot): kp = reach.geometry.get_kp() z_min = reach.geometry.get_z_min() - self.canvas.axes.set_xlim( - left=min(kp), right=max(kp) - ) + # self.canvas.axes.set_xlim( + # left=min(kp), right=max(kp) + # ) meter_axes = self.canvas.axes m3S_axes = self.canvas.axes @@ -88,10 +88,10 @@ class CustomPlot(PamhyrPlot): lines = {} if "elevation" in self._y: - meter_axes.set_ylim( - bottom=min(0, min(z_min)), - top=max(z_min) + 1 - ) + # meter_axes.set_ylim( + # bottom=min(0, min(z_min)), + # top=max(z_min) + 1 + # ) line = meter_axes.plot( kp, z_min, @@ -108,10 +108,10 @@ class CustomPlot(PamhyrPlot): ) ) - meter_axes.set_ylim( - bottom=min(0, min(z_min)), - top=max(water_z) + 1 - ) + # meter_axes.set_ylim( + # bottom=min(0, min(z_min)), + # top=max(water_z) + 1 + # ) line = meter_axes.plot( kp, water_z, lw=1., @@ -133,10 +133,10 @@ class CustomPlot(PamhyrPlot): ) ) - m3s_axes.set_ylim( - bottom=min(0, min(q)), - top=max(q) + 1 - ) + # m3s_axes.set_ylim( + # bottom=min(0, min(q)), + # top=max(q) + 1 + # ) line = m3s_axes.plot( kp, q, lw=1., @@ -206,9 +206,9 @@ class CustomPlot(PamhyrPlot): ts = list(results.get("timestamps")) ts.sort() - self.canvas.axes.set_xlim( - left=min(ts), right=max(ts) - ) + # self.canvas.axes.set_xlim( + # left=min(ts), right=max(ts) + # ) x = ts lines = {} @@ -232,10 +232,10 @@ class CustomPlot(PamhyrPlot): # Water elevation z = profile.get_key("Z") - meter_axes.set_ylim( - bottom=min(0, min(z)), - top=max(z) + 1 - ) + # meter_axes.set_ylim( + # bottom=min(0, min(z)), + # top=max(z) + 1 + # ) line = meter_axes.plot( ts, z, lw=1., @@ -260,10 +260,10 @@ class CustomPlot(PamhyrPlot): if "discharge" in self._y: q = profile.get_key("Q") - m3s_axes.set_ylim( - bottom=min(0, min(q)), - top=max(q) + 1 - ) + # m3s_axes.set_ylim( + # bottom=min(0, min(q)), + # top=max(q) + 1 + # ) line = m3s_axes.plot( ts, q, lw=1., diff --git a/src/View/Results/PlotKPC.py b/src/View/Results/PlotKPC.py index 1cab022e0caf86727dc8374564f985d125cc53c7..71fa3aab795ba674ae6c5bdf87c3941bd1b28786 100644 --- a/src/View/Results/PlotKPC.py +++ b/src/View/Results/PlotKPC.py @@ -119,11 +119,14 @@ class PlotKPC(PamhyrPlot): self.line_kp_sl.append(None) self.line_kp_sl[i], = self.canvas.axes.plot( kp, z, - linestyle="solid" if i == len(final_z_sl) - 1 else "--", + linestyle=( + "solid" if i == len(final_z_sl) - 1 + else self.linestyle[1:][i // len(self.colors)] + ), lw=1., color=( self.color_plot_river_bottom if i == len(final_z_sl) - 1 - else self.colors[i] + else self.colors[i % len(self.colors)] ) ) diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py index 45aaa0094ced68d59565ed910cbe434e3747721b..155b971e5c4ba7081aadf9ae2820c5777b6dec01 100644 --- a/src/View/Results/Window.py +++ b/src/View/Results/Window.py @@ -160,7 +160,10 @@ class ResultsWindow(PamhyrWindow): self.canvas = MplCanvas(width=5, height=4, dpi=100) self.canvas.setObjectName("canvas") self.toolbar = PamhyrPlotToolbar( - self.canvas, self + self.canvas, self, items=[ + "home", "move", "zoom", "save", + "iso", "back/forward" + ] ) self.plot_layout = self.find(QVBoxLayout, "verticalLayout") self.plot_layout.addWidget(self.toolbar) @@ -180,7 +183,10 @@ class ResultsWindow(PamhyrWindow): self.canvas_2 = MplCanvas(width=5, height=4, dpi=100) self.canvas_2.setObjectName("canvas_2") self.toolbar_2 = PamhyrPlotToolbar( - self.canvas_2, self + self.canvas_2, self, items=[ + "home", "move", "zoom", "save", + "iso", "back/forward" + ] ) self.plot_layout_2 = self.find(QVBoxLayout, "verticalLayout_2") self.plot_layout_2.addWidget(self.toolbar_2) @@ -199,7 +205,10 @@ class ResultsWindow(PamhyrWindow): self.canvas_3 = MplCanvas(width=5, height=4, dpi=100) self.canvas_3.setObjectName("canvas_3") self.toolbar_3 = PamhyrPlotToolbar( - self.canvas_3, self + self.canvas_3, self, items=[ + "home", "move", "zoom", "save", + "iso", "back/forward" + ] ) self.plot_layout_3 = self.find(QVBoxLayout, "verticalLayout_3") self.plot_layout_3.addWidget(self.toolbar_3) @@ -218,7 +227,10 @@ class ResultsWindow(PamhyrWindow): self.canvas_4 = MplCanvas(width=5, height=4, dpi=100) self.canvas_4.setObjectName("canvas_4") self.toolbar_4 = PamhyrPlotToolbar( - self.canvas_4, self + self.canvas_4, self, items=[ + "home", "move", "zoom", "save", + "iso", "back/forward" + ] ) self.plot_layout_4 = self.find( QVBoxLayout, "verticalLayout_hydrograph") diff --git a/src/View/Tools/PamhyrPlot.py b/src/View/Tools/PamhyrPlot.py index 4b0c6f35d25b4c296aebd896ca1b3f673e24e7cd..843be242d169f06aeb9aa25ab80d1a2859698aa8 100644 --- a/src/View/Tools/PamhyrPlot.py +++ b/src/View/Tools/PamhyrPlot.py @@ -40,6 +40,7 @@ class PamhyrPlot(APlot): color_plot_river_water_zone = "skyblue" colors = list(mplcolors.TABLEAU_COLORS) + linestyle = ['solid', 'dashed', 'dashdot', 'dotted'] plot_default_kargs = { "lw": 1., diff --git a/src/View/ui/GeometryCrossSection.ui b/src/View/ui/GeometryCrossSection.ui index 6e6d62a522c2fafdd7918dee64371b54608f890f..f7c9158eb1a2a26836ce9d9361823b0bb163e2b2 100644 --- a/src/View/ui/GeometryCrossSection.ui +++ b/src/View/ui/GeometryCrossSection.ui @@ -58,6 +58,8 @@ <addaction name="action_sort_des"/> <addaction name="action_up"/> <addaction name="action_down"/> + <addaction name="action_purge"/> + <addaction name="action_reverse"/> </widget> <action name="action_add"> <property name="icon"> @@ -131,6 +133,22 @@ <string>Sort reversed points by nearest neighbor</string> </property> </action> + <action name="action_purge"> + <property name="text"> + <string>Purge</string> + </property> + <property name="toolTip"> + <string>Purge the cross-section to keep a given number of points</string> + </property> + </action> + <action name="action_reverse"> + <property name="text"> + <string>Reverse</string> + </property> + <property name="toolTip"> + <string>Reverse the points order</string> + </property> + </action> </widget> <resources/> <connections/> diff --git a/src/View/ui/GeometryReach.ui b/src/View/ui/GeometryReach.ui index 95e25be170ed4be477e0892d432fe5bcde4581ac..22e5404324d2a74789346feeac75b12277c68811 100644 --- a/src/View/ui/GeometryReach.ui +++ b/src/View/ui/GeometryReach.ui @@ -127,6 +127,8 @@ <addaction name="action_down"/> <addaction name="action_export"/> <addaction name="action_meshing"/> + <addaction name="action_update_kp"/> + <addaction name="action_purge"/> </widget> <action name="action_import"> <property name="text"> @@ -233,6 +235,22 @@ <string>Meshing</string> </property> </action> + <action name="action_update_kp"> + <property name="text"> + <string>Update KP</string> + </property> + <property name="toolTip"> + <string>Recompute KP</string> + </property> + </action> + <action name="action_purge"> + <property name="text"> + <string>Purge</string> + </property> + <property name="toolTip"> + <string>Purge cross-sections to keep a given number of points</string> + </property> + </action> </widget> <resources/> <connections/> diff --git a/src/lang/fr.ts b/src/lang/fr.ts index 839a50190f59e64526dece19d08e9b467abb6537..4b3a4a4d4ba613ce312a551c2dd776f42103ee11 100644 --- a/src/lang/fr.ts +++ b/src/lang/fr.ts @@ -31,7 +31,7 @@ <message> <location filename="../View/HydraulicStructures/BasicHydraulicStructures/Translate.py" line="30"/> <source>Basic Hydraulic Structures</source> - <translation>Structure hydraulique élémentaire</translation> + <translation>Ouvrage hydraulique élémentaire</translation> </message> <message> <location filename="../View/HydraulicStructures/BasicHydraulicStructures/Translate.py" line="34"/> @@ -51,7 +51,7 @@ <message> <location filename="../View/HydraulicStructures/BasicHydraulicStructures/Translate.py" line="54"/> <source>Upper elevation (m)</source> - <translation>Côte de mise en charge (m)</translation> + <translation>Cote de mise en charge (m)</translation> </message> <message> <location filename="../View/HydraulicStructures/BasicHydraulicStructures/Translate.py" line="57"/> @@ -61,7 +61,7 @@ <message> <location filename="../View/HydraulicStructures/BasicHydraulicStructures/Translate.py" line="60"/> <source>Maximal loading elevation</source> - <translation>Côte de mise en charge maximale</translation> + <translation>Cote de mise en charge maximale</translation> </message> <message> <location filename="../View/HydraulicStructures/BasicHydraulicStructures/Translate.py" line="63"/> @@ -420,7 +420,7 @@ <message> <location filename="../View/Results/CustomPlot/Translate.py" line="46"/> <source>Bed load elevation (m)</source> - <translation>Côte du fond (m)</translation> + <translation>Cote du fond (m)</translation> </message> </context> <context> @@ -434,7 +434,7 @@ <context> <name>Dialog</name> <message> - <location filename="../View/ui/MeshingOptions.ui" line="14"/> + <location filename="../View/ui/SelectSolver.ui" line="14"/> <source>Dialog</source> <translation>Dialog</translation> </message> @@ -449,7 +449,7 @@ <translation>Type</translation> </message> <message> - <location filename="../View/ui/NewStudy.ui" line="92"/> + <location filename="../View/ui/ConfigureAddSolverDialog.ui" line="48"/> <source>Description</source> <translation>Description</translation> </message> @@ -829,7 +829,7 @@ <context> <name>Form</name> <message> - <location filename="../View/ui/Widgets/MainWindowTabCheckers.ui" line="14"/> + <location filename="../View/ui/dummy.ui" line="14"/> <source>Form</source> <translation>Formulaire</translation> </message> @@ -1055,17 +1055,17 @@ <context> <name>Geometry</name> <message> - <location filename="../View/Geometry/Translate.py" line="56"/> + <location filename="../View/LateralContribution/translate.py" line="52"/> <source>X (m)</source> <translation>X (m)</translation> </message> <message> - <location filename="../View/Geometry/Translate.py" line="57"/> + <location filename="../View/LateralContribution/translate.py" line="53"/> <source>Y (m)</source> <translation>Y (m)</translation> </message> <message> - <location filename="../View/Geometry/Translate.py" line="58"/> + <location filename="../View/LateralContribution/translate.py" line="54"/> <source>Z (m)</source> <translation>Z (m)</translation> </message> @@ -1175,7 +1175,7 @@ <message> <location filename="../View/HydraulicStructures/Translate.py" line="30"/> <source>Hydraulic Structures</source> - <translation>Structures hydraulique</translation> + <translation>Structures hydrauliques</translation> </message> <message> <location filename="../View/HydraulicStructures/Translate.py" line="34"/> @@ -1262,17 +1262,17 @@ <translation>Activer cette fenêtre</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="14"/> + <location filename="../View/ui/Stricklers.ui" line="14"/> <source>MainWindow</source> <translation>Fenêtre principale</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="112"/> + <location filename="../View/ui/Stricklers.ui" line="52"/> <source>toolBar</source> <translation>Barre d'outils</translation> </message> <message> - <location filename="../View/ui/EditLateralContribution.ui" line="79"/> + <location filename="../View/ui/Stricklers.ui" line="70"/> <source>Add</source> <translation>Ajouter</translation> </message> @@ -1282,7 +1282,7 @@ <translation>Ajouter un casier</translation> </message> <message> - <location filename="../View/ui/EditLateralContribution.ui" line="94"/> + <location filename="../View/ui/Stricklers.ui" line="82"/> <source>Delete</source> <translation>Supprimer</translation> </message> @@ -1292,7 +1292,7 @@ <translation>Supprimer casier(s)</translation> </message> <message> - <location filename="../View/ui/AdditionalFileList.ui" line="67"/> + <location filename="../View/ui/ReservoirList.ui" line="105"/> <source>Edit</source> <translation>Éditer</translation> </message> @@ -1327,7 +1327,7 @@ <translation>Éditer la couche sedimentaire</translation> </message> <message> - <location filename="../View/ui/REPLineList.ui" line="79"/> + <location filename="../View/ui/Results.ui" line="270"/> <source>Ctrl+E</source> <translation>Ctrl+E</translation> </message> @@ -1397,7 +1397,7 @@ <translation>Nouvelle étude</translation> </message> <message> - <location filename="../View/ui/EditLateralContribution.ui" line="85"/> + <location filename="../View/ui/BoundaryConditions.ui" line="120"/> <source>Ctrl+N</source> <translation>Ctrl+N</translation> </message> @@ -1482,12 +1482,12 @@ <translation>Éditer la géométrie</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="136"/> + <location filename="../View/ui/GeometryReach.ui" line="138"/> <source>Import geometry</source> <translation>Importer une géométrie</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="144"/> + <location filename="../View/ui/GeometryReach.ui" line="146"/> <source>Export geometry</source> <translation>Exporter la géométrie</translation> </message> @@ -1682,7 +1682,7 @@ <translation>Éditer les casiers</translation> </message> <message> - <location filename="../View/ui/HydraulicStructures.ui" line="14"/> + <location filename="../View/ui/MainWindow.ui" line="625"/> <source>Hydraulic structures</source> <translation>Structures hydraulique</translation> </message> @@ -1727,7 +1727,7 @@ <translation>Supprimer la(les) couche(s) sédimentaire(s) sélectionnée(s)</translation> </message> <message> - <location filename="../View/ui/EditLateralContribution.ui" line="100"/> + <location filename="../View/ui/BoundaryConditions.ui" line="135"/> <source>Ctrl+D</source> <translation>Ctrl+D</translation> </message> @@ -1762,7 +1762,7 @@ <translation>Ajouter une condition aux limites ou un apport ponctuel</translation> </message> <message> - <location filename="../View/ui/EditLateralContribution.ui" line="97"/> + <location filename="../View/ui/BoundaryConditions.ui" line="132"/> <source>Delete current selected rows</source> <translation>Supprimer les lignes selectionnées</translation> </message> @@ -1772,7 +1772,7 @@ <translation>Éditer une condition aux limites ou un apport ponctuel</translation> </message> <message> - <location filename="../View/ui/EditLateralContribution.ui" line="109"/> + <location filename="../View/ui/Stricklers.ui" line="94"/> <source>Sort</source> <translation>Trier</translation> </message> @@ -1824,7 +1824,7 @@ <message> <location filename="../View/ui/Results.ui" line="169"/> <source>Water elevation</source> - <translation>Côte de l'eau</translation> + <translation>Cote de l'eau</translation> </message> <message> <location filename="../View/ui/Results.ui" line="201"/> @@ -1842,7 +1842,7 @@ <translation>Recharger</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="141"/> + <location filename="../View/ui/Results.ui" line="264"/> <source>Export</source> <translation>Exporter</translation> </message> @@ -1852,7 +1852,7 @@ <translation>Exporter les données brutes</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="165"/> + <location filename="../View/ui/GeometryCrossSection.ui" line="82"/> <source>delete</source> <translation>supprimer</translation> </message> @@ -1917,87 +1917,87 @@ <translation>Supprimer points</translation> </message> <message> - <location filename="../View/ui/HydraulicStructures.ui" line="133"/> + <location filename="../View/ui/BasicHydraulicStructures.ui" line="136"/> <source>Edit selected hydraulic structure</source> <translation>Éditer l'ouvrage hydraulique sélectionné</translation> </message> <message> - <location filename="../View/ui/SolverLog.ui" line="77"/> + <location filename="../View/ui/SolverLog.ui" line="78"/> <source>Stop</source> <translation>Stoper</translation> </message> <message> - <location filename="../View/ui/SolverLog.ui" line="86"/> + <location filename="../View/ui/SolverLog.ui" line="87"/> <source>Start</source> <translation>Démarrer</translation> </message> <message> - <location filename="../View/ui/SolverLog.ui" line="95"/> + <location filename="../View/ui/SolverLog.ui" line="96"/> <source>Pause</source> <translation>Pause</translation> </message> <message> - <location filename="../View/ui/SolverLog.ui" line="104"/> + <location filename="../View/ui/SolverLog.ui" line="105"/> <source>LogFile</source> <translation>Fichier de log</translation> </message> <message> - <location filename="../View/ui/SolverLog.ui" line="109"/> + <location filename="../View/ui/SolverLog.ui" line="110"/> <source>results</source> <translation>resultats</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="153"/> + <location filename="../View/ui/GeometryCrossSection.ui" line="70"/> <source>add</source> <translation>Ajouter</translation> </message> <message> - <location filename="../View/ui/GeometryCrossSection.ui" line="71"/> + <location filename="../View/ui/GeometryCrossSection.ui" line="73"/> <source>Add a point on cross-section</source> <translation>Ajouter un point à la section en travers</translation> </message> <message> - <location filename="../View/ui/GeometryCrossSection.ui" line="83"/> + <location filename="../View/ui/GeometryCrossSection.ui" line="85"/> <source>Delete selected point(s)</source> <translation>Supprimer le(s) point(s) sélectionné(s)</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="213"/> + <location filename="../View/ui/GeometryCrossSection.ui" line="94"/> <source>up</source> <translation>Monter</translation> </message> <message> - <location filename="../View/ui/GeometryCrossSection.ui" line="95"/> + <location filename="../View/ui/GeometryCrossSection.ui" line="97"/> <source>Move up selected point(s)</source> <translation>Déplacer le point sélectionné vers le haut</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="225"/> + <location filename="../View/ui/GeometryCrossSection.ui" line="106"/> <source>down</source> <translation>Descendre</translation> </message> <message> - <location filename="../View/ui/GeometryCrossSection.ui" line="107"/> + <location filename="../View/ui/GeometryCrossSection.ui" line="109"/> <source>Mode down selected point(s)</source> <translation>Déplacer le point sélectionné vers le bas</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="189"/> + <location filename="../View/ui/GeometryCrossSection.ui" line="118"/> <source>sort_asc</source> <translation>sort_asc</translation> </message> <message> - <location filename="../View/ui/GeometryCrossSection.ui" line="119"/> + <location filename="../View/ui/GeometryCrossSection.ui" line="121"/> <source>Sort points by nearest neighbor</source> <translation>Trier les points par leurs plus proches voisins</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="201"/> + <location filename="../View/ui/GeometryCrossSection.ui" line="130"/> <source>sort_des</source> <translation>sort_des</translation> </message> <message> - <location filename="../View/ui/GeometryCrossSection.ui" line="131"/> + <location filename="../View/ui/GeometryCrossSection.ui" line="133"/> <source>Sort reversed points by nearest neighbor</source> <translation>Trie inverser les points par leurs plus proche voisins</translation> </message> @@ -2014,10 +2014,10 @@ <message> <location filename="../View/ui/Reservoir.ui" line="114"/> <source>Sort points by elevation</source> - <translation>Trier les points par leur côte</translation> + <translation>Trier les points par leur cote</translation> </message> <message> - <location filename="../View/ui/ProfileSedimentLayers.ui" line="75"/> + <location filename="../View/ui/ReachSedimentLayers.ui" line="31"/> <source>Edit sediment layers list</source> <translation>Éditer la liste des couches sédimentaires</translation> </message> @@ -2112,52 +2112,52 @@ <translation>Éditer les couches sédimentaires</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="133"/> + <location filename="../View/ui/GeometryReach.ui" line="135"/> <source>Import</source> <translation>Importer</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="156"/> + <location filename="../View/ui/GeometryReach.ui" line="158"/> <source>Add a cross-section</source> <translation>Ajouter une section en travers</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="168"/> + <location filename="../View/ui/GeometryReach.ui" line="170"/> <source>Delete selected cross-section(s)</source> <translation>Supprimer la(es) section(s) en travers sélectionnée(s)</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="177"/> + <location filename="../View/ui/GeometryReach.ui" line="179"/> <source>edit</source> <translation>éditer</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="180"/> + <location filename="../View/ui/GeometryReach.ui" line="182"/> <source>Edit selected cross section(s)</source> <translation>Éditer la(es) section(s) en travers sélectionnée(s)</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="192"/> + <location filename="../View/ui/GeometryReach.ui" line="194"/> <source>Sort cross-sections by ascending KP</source> <translation>Trier les sections en travers par PK croissant</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="204"/> + <location filename="../View/ui/GeometryReach.ui" line="206"/> <source>Sort cross-sections by descending KP</source> <translation>Trier les sections en travers par PK décroissant</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="216"/> + <location filename="../View/ui/GeometryReach.ui" line="218"/> <source>Move up selected cross-section(s)</source> <translation>Déplacer la(s) section(s) en travers vers le haut</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="228"/> + <location filename="../View/ui/GeometryReach.ui" line="230"/> <source>Move down selected cross-section(s)</source> <translation>Déplacer la(es) section(s) en travers vers le bas</translation> </message> <message> - <location filename="../View/ui/GeometryReach.ui" line="233"/> + <location filename="../View/ui/GeometryReach.ui" line="235"/> <source>Meshing</source> <translation>Maillage</translation> </message> @@ -2261,6 +2261,41 @@ <source>Edit the study information</source> <translation>Éditer les information de l'étude</translation> </message> + <message> + <location filename="../View/ui/GeometryReach.ui" line="240"/> + <source>Update KP</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../View/ui/GeometryReach.ui" line="243"/> + <source>Recompute KP</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../View/ui/GeometryCrossSection.ui" line="138"/> + <source>Purge</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../View/ui/GeometryReach.ui" line="251"/> + <source>Purge cross-sections to keep a given number of points</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../View/ui/GeometryCrossSection.ui" line="141"/> + <source>Purge the cross-section to keep a given number of points</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../View/ui/GeometryCrossSection.ui" line="146"/> + <source>Reverse</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../View/ui/GeometryCrossSection.ui" line="149"/> + <source>Reverse the points order</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>MainWindowProfile</name> @@ -2472,12 +2507,12 @@ <message> <location filename="../View/Results/translate.py" line="41"/> <source>Water elevation</source> - <translation>Côte de l'eau</translation> + <translation>Cote de l'eau</translation> </message> <message> <location filename="../View/Results/translate.py" line="42"/> <source>Max water elevation</source> - <translation>Côte maximum de l'eau</translation> + <translation>Cote maximum de l'eau</translation> </message> <message> <location filename="../View/Results/translate.py" line="48"/> @@ -2913,12 +2948,12 @@ <message> <location filename="../View/Translate.py" line="60"/> <source>Elevation (m)</source> - <translation>Côte (m)</translation> + <translation>Cote (m)</translation> </message> <message> <location filename="../View/Translate.py" line="61"/> <source>Water elevation (m)</source> - <translation>Côte de l'eau (m)</translation> + <translation>Cote de l'eau (m)</translation> </message> <message> <location filename="../View/Translate.py" line="65"/> diff --git a/tools/license.el b/tools/license.el index afb49975302f0a33d67f216795ea1fe63fc3de24..1d08c959f6cdd909006995e26f92155a4d045ee7 100644 --- a/tools/license.el +++ b/tools/license.el @@ -109,3 +109,59 @@ (mapcar 'pamhyr--insert-license (mapcar (lambda (file) (concat root "/" file)) files-without-copyright)))) + +(defvar pamhyr-mail-template "Bonjour, + +La version @version de Pamhyr2 est disponible. + +<NEWS> + +---Change-logs-------------------@version--- +@description +------------------------------------------ + +---Liens-utiles--------------------------- + Télécharger cette version : + https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/releases/@version + + La documentation (en anglais) : + https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home + + Rapporter un problème : + https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/issues + ou directement par mail à : + <pierre-antoine.rouby@inrae.fr> +------------------------------------------ + +<FUTURE_WORK> + +---/!\--Attention------------------------- + Pour les utilisateurs Windows : Certains antivirus peuvent détecter Pamhyr2 comme un virus, c'est un faux positif, le problème est connu et vient de l'exécutable généré par PyInstaller. + Nous n'avons pas encore de solution pour régler ce problème. + Si c'est votre cas, il faudra ajouter une exception dans votre antivirus si vous voulez utiliser Pamhyr2. + Sinon, il est aussi possible de passer par WSL et utiliser la version Linux sous Windows. + + Rapport d'antivirus : <LINK_VIRUSTOTAL> +------------------------------------------ + +Bon weekend, +") + +(require 'web) +(require 'json) + +(defun pamhyr-release-mail (release) + (interactive "sRelease name: ") + (web-http-get + (lambda (httpc header my-data) + (let* ((data (json-read-from-string my-data)) + (release (cdr (assoc 'tag_name data))) + (description (cdr (assoc 'description data)))) + (let ((buffer (generate-new-buffer (format "* mail-%s *" release)))) + (with-current-buffer buffer + (insert + (string-replace "@description" description + (string-replace "@version" release + pamhyr-mail-template))) + (set-buffer buffer))))) + :url (concat "https://gitlab.irstea.fr/api/v4/projects/2779/releases/" release)))