mirror of
https://gitlab.com/pamhyr/pamhyr2.git
synced 2026-10-30 03:20:41 +01:00
321 lines
9.4 KiB
Python
321 lines
9.4 KiB
Python
# 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 <https://www.gnu.org/licenses/>.
|
|
|
|
# -*- 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
|
|
)
|
|
parameters = self._params_widget.values
|
|
|
|
if distribution is not None:
|
|
ok, tips = distribution.is_valid_parameters(parameters)
|
|
if not ok:
|
|
self.message_box(
|
|
text=self._trad["checker_failed_text"],
|
|
informative_text="\n".join(
|
|
map(lambda t: " - " + self._trad[t], tips)
|
|
),
|
|
window_title=self._trad["checker_failed_title"],
|
|
)
|
|
return
|
|
|
|
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": parameters,
|
|
}
|
|
|
|
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
|