# Window.py -- Pamhyr # Copyright (C) 2023-2026 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, logger_exception from View.Tools.PamhyrWindow import PamhyrWindow, PamhyrDialog from View.Tools.PamhyrWidget import PamhyrWidget from View.Tools.PamhyrTree import ( PamhyrModelItem, PamhyrModelListItem, ) from PyQt5.QtGui import ( QKeySequence, ) from PyQt5 import QtWidgets from PyQt5.QtCore import ( Qt, QVariant, QAbstractTableModel, QCoreApplication, QModelIndex, pyqtSlot, QRect, QSettings, ) from PyQt5.QtWidgets import ( QDialogButtonBox, QPushButton, QLineEdit, QFileDialog, QTableView, QAbstractItemView, QUndoStack, QShortcut, QAction, QItemDelegate, QComboBox, QVBoxLayout, QHeaderView, QTabWidget, QGroupBox, QTreeWidget, ) from View.Ensembles.Edit.Translate import EnsembleEditTranslate logger = logging.getLogger() class StricklersCoefModelItem(PamhyrModelItem): def get_value(self): return (self._data, self.parent()._data) class StricklersModelItem(PamhyrModelItem): def __init__(self, data=None, trad=None, parent=None): super(StricklersModelItem, self).__init__( data=data, trad=trad, parent=parent, ) def _setup_children(self): for coef in ["strickler_minor", "strickler_medium"]: self.addChild( StricklersCoefModelItem(data=coef, parent=self) ) def get_value(self): return self._data class EnsembleEditDialog(PamhyrDialog): _pamhyr_ui = "EnsembleEditDialog" _pamhyr_name = "Parameters" def __init__(self, study=None, ensemble=None, parent=None): trad = EnsembleEditTranslate() super(EnsembleEditDialog, self).__init__( title=trad[self._pamhyr_name], trad=trad, options=[], parent=parent ) self._study = study self._ensemble = ensemble self._target_data = None self._tree = self.find(QTreeWidget, "treeWidget_target_data") self._tg_group_box = self.find(QGroupBox, "groupBox_target_data") self._init_tree() self._init_default_values() self._init_connection() def _init_tree(self): self._tree.setColumnCount(1) self._tree.setHeaderLabels(["Name"]) stricklers = PamhyrModelListItem( name="Stricklers", lst=self._study.river.stricklers, child_item_ctor=StricklersModelItem, parent=self._tree ) self._target_data = ( self._ensemble.data_type, self._ensemble.target_data ) self._tg_group_box.setTitle( self._format_target_data(self._target_data) ) item = stricklers.find_item_by_value(self._target_data) if item: self._tree.setCurrentItem(item) def _init_default_values(self): self.set_line_edit_text("lineEdit_name", self._ensemble.name) self.combobox_add_items( "comboBox_distribution", [self._trad["not_defined"]] + list( map( lambda d: d.name, self._study._ens_distributions.lst ) ) ) self._params_widget = None if self._ensemble.distribution is not None: self.set_combobox_text("comboBox_distribution", self._ensemble.distribution.name) self._set_widget(self._ensemble.distribution) def _init_connection(self): self.find(QComboBox, "comboBox_distribution")\ .currentTextChanged.connect(self.update_distribution) self._tree.itemClicked.connect(self._tree_item_select) def _tree_item_select(self, item): if type(item) is StricklersCoefModelItem: self._target_data = item.get_value() self._tg_group_box.setTitle( self._format_target_data(self._target_data) ) def _format_target_data(self, data): return f" Selection: {str(data[1])}, {data[0]}" def update_distribution(self, txt): # txt = self.get_combobox_text("comboBox_distribution") distribution = next( filter( lambda d: d.name == txt, self._study._ens_distributions.lst ), None ) self._set_widget(distribution) def _set_widget(self, distribution): box = self.find(QGroupBox, "groupBox_params") vbox = self.find(QVBoxLayout, "verticalLayout_params") if self._params_widget is not None: vbox.removeWidget(self._params_widget) self._params_widget.setParent(None) if distribution is None: return size = len(distribution._labels) if size == 1: self._params_widget = Ensemble1ParamsWidget( ensemble=self._ensemble, distribution=distribution, trad=self._trad, parent=box, ) vbox.addWidget(self._params_widget) elif size == 2: self._params_widget = Ensemble2ParamsWidget( ensemble=self._ensemble, distribution=distribution, trad=self._trad, parent=box, ) vbox.addWidget(self._params_widget) else: self._params_widget = None @property def values(self): return self._values def accept(self): txt = self.get_combobox_text("comboBox_distribution") distribution = next( filter( lambda d: d.name == txt, self._study._ens_distributions.lst ), None ) self._values = { "name": self.get_line_edit_text("lineEdit_name"), "data_type": self._target_data[0], "target_data": self._target_data[1], "distribution": distribution, "params": self._params_widget.values, } super().accept() def reject(self): self.close() class Ensemble1ParamsWidget(PamhyrWidget): _pamhyr_ui = "Ensemble1ParamsWidget" _pamhyr_name = "Parameters" def __init__(self, ensemble=None, distribution=None, trad=None, parent=None): super(Ensemble1ParamsWidget, self).__init__( parent=parent ) self._trad = trad self._ensemble = ensemble self._distribution = distribution self._labels = distribution.labels self._init_default_labels() self._init_default_values() def _init_default_labels(self): self.set_label_text("label_0", self._trad[self._labels[0]]) def _init_default_values(self): self._values = self._ensemble.params if len(self._values) != 1: self._values = self._distribution.default_values.copy() self.set_double_spin_box("doubleSpinBox_0", self._values[0]) @property def values(self): self._values = [ self.get_double_spin_box("doubleSpinBox_0"), ] return self._values class Ensemble2ParamsWidget(PamhyrWidget): _pamhyr_ui = "Ensemble2ParamsWidget" _pamhyr_name = "Parameters" def __init__(self, ensemble=None, distribution=None, trad=None, parent=None): super(Ensemble2ParamsWidget, self).__init__( parent=parent ) self._trad = trad self._ensemble = ensemble self._distribution = distribution self._labels = distribution.labels self._init_default_labels() self._init_default_values() def _init_default_labels(self): self.set_label_text("label_0", self._trad[self._labels[0]]) self.set_label_text("label_1", self._trad[self._labels[1]]) def _init_default_values(self): self._values = self._ensemble.params if len(self._values) != 2: self._values = self._distribution.default_values.copy() self.set_double_spin_box("doubleSpinBox_0", self._values[0]) self.set_double_spin_box("doubleSpinBox_1", self._values[1]) @property def values(self): self._values = [ self.get_double_spin_box("doubleSpinBox_0"), self.get_double_spin_box("doubleSpinBox_1") ] return self._values