# Window.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 -*- import logging from tools import trace, timer from View.Tools.PamhyrWindow import PamhyrWindow from PyQt5.QtGui import ( QKeySequence, ) from PyQt5.QtCore import ( Qt, QVariant, QAbstractTableModel, QCoreApplication, QModelIndex, pyqtSlot, QRect, ) from PyQt5.QtWidgets import ( QDialogButtonBox, QPushButton, QLineEdit, QFileDialog, QTableView, QAbstractItemView, QUndoStack, QShortcut, QAction, QItemDelegate, QComboBox, QVBoxLayout, QHeaderView, QTabWidget, ) from Modules import Modules from View.Frictions.UndoCommand import ( PasteCommand, DuplicateCommand, ) from View.Frictions.Table import ( TableModel, ComboBoxDelegate ) from View.Tools.Plot.PamhyrCanvas import MplCanvas from View.Frictions.PlotRKZ import PlotRKZ from View.Frictions.PlotStricklers import PlotStricklers from View.Frictions.translate import FrictionsTranslate from View.Stricklers.Window import StricklersWindow logger = logging.getLogger() class FrictionsWindow(PamhyrWindow): _pamhyr_ui = "Frictions" _pamhyr_name = "Edit frictions" def __init__(self, reach=None, study=None, config=None, parent=None): trad = FrictionsTranslate() if reach is not None: self._reach = reach else: self._reach = study.river.current_reach() self._frictions = self._reach.frictions name = ( trad[self._pamhyr_name] + " - " + study.name + " - " + self._reach.name ) super(FrictionsWindow, self).__init__( title=name, study=study, config=config, trad=trad, parent=parent ) # Add reach to hash computation data self._hash_data.append(self._reach) self.setup_table() self.setup_graph() self.setup_connections() def setup_table(self): self._table = {} self._delegate_stricklers = ComboBoxDelegate( data=self._reach, study=self._study, mode="stricklers", trad=self._trad, parent=self ) table = self.find(QTableView, f"tableView") self._table = TableModel( table_view=table, table_headers=self._trad.get_dict("table_headers"), editable_headers=[ "name", "begin_rk", "end_rk", "begin_strickler", "end_strickler" ], delegates={ "begin_strickler": self._delegate_stricklers, "end_strickler": self._delegate_stricklers, }, data=self._reach, trad=self._trad, undo=self._undo_stack, opt_data=self._study ) table.setModel(self._table) table.setSelectionBehavior(QAbstractItemView.SelectRows) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.setAlternatingRowColors(True) def setup_graph(self): self.canvas = MplCanvas(width=5, height=4, dpi=100) self.canvas.setObjectName("canvas") self.plot_layout = self.find(QVBoxLayout, "verticalLayout") self.plot_layout.addWidget(self.canvas) self.plot = PlotRKZ( canvas=self.canvas, reach=self._reach, river=self._study.river, trad=self._trad, toolbar=None, parent=self ) self.plot.draw() self.canvas_2 = MplCanvas(width=5, height=4, dpi=100) self.canvas_2.setObjectName("canvas_2") self.plot_layout_2 = self.find(QVBoxLayout, "verticalLayout_2") self.plot_layout_2.addWidget(self.canvas_2) self.plot_2 = PlotStricklers( canvas=self.canvas_2, data=self._reach, trad=self._trad, toolbar=None ) self.plot_2.draw() def setup_connections(self): self.find(QAction, "action_add").triggered.connect(self.add) self.find(QAction, "action_del").triggered.connect(self.delete) self.find(QAction, "action_sort").triggered.connect(self.sort) self.find(QAction, "action_edit_stricklers").triggered.connect( self.edit_stricklers) table = self.find(QTableView, f"tableView") table.selectionModel()\ .selectionChanged\ .connect(self.update) self._table.dataChanged\ .connect(self.update) def index_selected_rows(self): table = self.find(QTableView, f"tableView") return list( # Delete duplicate set( map( lambda i: i.row(), table.selectedIndexes() ) ) ) def update(self): self._set_current_reach() # self._propagate_update(key=Modules.FRICTION) def _propagated_update(self, key=Modules(0)): if Modules.GEOMETRY not in key: return self.update_plot() def _set_current_reach(self): rows = self.index_selected_rows() data = None reach = None highlight = None if len(rows) > 0: data = self._reach reach = self._reach.reach sec = self._frictions.get(rows[0]) highlight = (sec.begin_rk, sec.end_rk) self.update_plot(highlight) def update_plot(self, highlight=None): self.plot.draw(highlight) if highlight is not None: self.plot_2.highlight = highlight self.plot_2.draw() def add(self): rows = self.index_selected_rows() if len(self._frictions) == 0 or len(rows) == 0: self._table.add(0) else: self._table.add(rows[0]) def delete(self): rows = self.index_selected_rows() if len(rows) == 0: return self._table.delete(rows) def sort(self): self._table.sort(False) def move_up(self): row = self.index_selected_row() self._table.move_up(row) def move_down(self): row = self.index_selected_row() self._table.move_down(row) def _copy(self): logger.info("TODO: copy") def _paste(self): logger.info("TODO: paste") def _undo(self): self._table.undo() def _redo(self): self._table.redo() def edit_stricklers(self): if self.sub_window_exists( StricklersWindow, data=[self._study, self.parent.conf] ): return strick = StricklersWindow( study=self._study, config=self.parent.conf, parent=self ) strick.show()