mirror of https://gitlab.com/pamhyr/pamhyr2
work 5
parent
f9fe5c9b6c
commit
b56b8099ab
|
|
@ -0,0 +1,3 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.10 (pamhyr)" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (pamhyr)" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/pamhyr.iml" filepath="$PROJECT_DIR$/.idea/pamhyr.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.10 (pamhyr)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="PyDocumentationSettings">
|
||||
<option name="format" value="PLAIN" />
|
||||
<option name="myDocStringFormat" value="Plain" />
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -101,8 +101,8 @@ class OutputKpAdists(SQLSubModel):
|
|||
def _db_load(cls, execute, data=None):
|
||||
new = []
|
||||
|
||||
reach = data["reach"]
|
||||
profile = data["profile"]
|
||||
#reach = data["reach"]
|
||||
#profile = data["profile"]
|
||||
status = data["status"]
|
||||
|
||||
table = execute(
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ from Model.OutputKpAdists.OutputKpAdists import OutputKpAdists
|
|||
|
||||
|
||||
class OutputKpAdistsList(PamhyrModelList):
|
||||
_sub_classes = [OutputKpAdistsList]
|
||||
_sub_classes = [OutputKpAdists]
|
||||
|
||||
@classmethod
|
||||
def _db_load(cls, execute, data=None):
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ from Model.REPLine.REPLineList import REPLineList
|
|||
|
||||
from Solver.Solvers import solver_type_list
|
||||
|
||||
from Model.OutputKpAdists.OutputKpListAdists import OutputKpAdistsList
|
||||
|
||||
|
||||
class RiverNode(Node, SQLSubModel):
|
||||
_sub_classes = []
|
||||
|
|
@ -228,6 +230,7 @@ class River(Graph, SQLSubModel):
|
|||
HydraulicStructureList,
|
||||
AddFileList,
|
||||
REPLineList,
|
||||
OutputKpAdistsList,
|
||||
]
|
||||
|
||||
def __init__(self, status=None):
|
||||
|
|
@ -251,6 +254,7 @@ class River(Graph, SQLSubModel):
|
|||
)
|
||||
self._additional_files = AddFileList(status=self._status)
|
||||
self._rep_lines = REPLineList(status=self._status)
|
||||
self._Output_kp_adists = OutputKpAdistsList(status=self._status)
|
||||
|
||||
@classmethod
|
||||
def _db_create(cls, execute):
|
||||
|
|
@ -325,6 +329,10 @@ class River(Graph, SQLSubModel):
|
|||
)
|
||||
new._rep_lines = REPLineList._db_load(execute, data)
|
||||
|
||||
new._Output_kp_adists = OutputKpAdistsList._db_load(
|
||||
execute, data
|
||||
)
|
||||
|
||||
return new
|
||||
|
||||
def _db_save(self, execute, data=None):
|
||||
|
|
@ -344,6 +352,8 @@ class River(Graph, SQLSubModel):
|
|||
for solver in self._parameters:
|
||||
objs.append(self._parameters[solver])
|
||||
|
||||
objs.append(self._Output_kp_adists)
|
||||
|
||||
self._save_submodel(execute, objs, data)
|
||||
return True
|
||||
|
||||
|
|
@ -466,6 +476,10 @@ Last export at: @date."""
|
|||
def parameters(self):
|
||||
return self._parameters
|
||||
|
||||
@property
|
||||
def Output_kp_adists(self):
|
||||
return self._Output_kp_adists
|
||||
|
||||
def get_params(self, solver):
|
||||
if solver in self._parameters:
|
||||
return self._parameters[solver]
|
||||
|
|
|
|||
|
|
@ -81,6 +81,10 @@ class AdisTS(CommandLineSolver):
|
|||
name = self._study.name
|
||||
return f"{name}.REP"
|
||||
|
||||
def log_file(self):
|
||||
name = self._study.name
|
||||
return f"{name}.TRA"
|
||||
|
||||
def _export_REP_additional_lines(self, study, rep_file):
|
||||
lines = filter(
|
||||
lambda line: line.is_enabled(),
|
||||
|
|
@ -117,6 +121,25 @@ class AdisTS(CommandLineSolver):
|
|||
|
||||
return True
|
||||
|
||||
###########
|
||||
# RESULTS #
|
||||
###########
|
||||
|
||||
def read_bin(self, study, repertory, results, qlog=None, name="0"):
|
||||
return
|
||||
|
||||
@timer
|
||||
def results(self, study, repertory, qlog=None, name="0"):
|
||||
results = Results(
|
||||
study=study,
|
||||
solver=self,
|
||||
repertory=repertory,
|
||||
name=name,
|
||||
)
|
||||
self.read_bin(study, repertory, results, qlog, name=name)
|
||||
|
||||
return results
|
||||
|
||||
################################
|
||||
# Adis-TS in low coupling mode #
|
||||
################################
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ from View.CheckList.Window import CheckListWindow
|
|||
from View.Results.Window import ResultsWindow
|
||||
from View.Results.ReadingResultsDialog import ReadingResultsDialog
|
||||
from View.Debug.Window import ReplWindow
|
||||
from View.OutputKpAdisTS.Window import OutputKpAdisTSWindow
|
||||
|
||||
# Optional internal display of documentation for make the application
|
||||
# package lighter...
|
||||
|
|
@ -118,7 +119,7 @@ define_model_action = [
|
|||
"action_menu_edit_hydraulic_structures", "action_menu_additional_file",
|
||||
"action_menu_results_last", "action_open_results_from_file",
|
||||
"action_menu_boundary_conditions_sediment",
|
||||
"action_menu_rep_additional_lines",
|
||||
"action_menu_rep_additional_lines", "action_menu_output_kp",
|
||||
]
|
||||
|
||||
action = (
|
||||
|
|
@ -232,6 +233,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||
"""
|
||||
actions = {
|
||||
# Menu action
|
||||
"action_menu_output_kp": self.open_output_kp_adists,
|
||||
"action_menu_config": self.open_configure,
|
||||
"action_menu_new": self.open_new_study,
|
||||
"action_menu_edit": self.open_edit_study,
|
||||
|
|
@ -860,6 +862,19 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||
# SUB WINDOWS #
|
||||
###############
|
||||
|
||||
def open_output_kp_adists(self):
|
||||
if self.sub_window_exists(
|
||||
OutputKpAdisTSWindow,
|
||||
data=[self._study, None]
|
||||
):
|
||||
return
|
||||
|
||||
Output_Kp_AdisTS = OutputKpAdisTSWindow(
|
||||
study=self._study,
|
||||
parent=self
|
||||
)
|
||||
Output_Kp_AdisTS.show()
|
||||
|
||||
def open_configure(self):
|
||||
"""Open configure window
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,277 @@
|
|||
# Table.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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
from tools import trace, timer
|
||||
|
||||
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, QMessageBox,
|
||||
)
|
||||
|
||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||
|
||||
from View.HydraulicStructures.BasicHydraulicStructures.UndoCommand import (
|
||||
SetNameCommand, SetTypeCommand,
|
||||
SetEnabledCommand, AddCommand, DelCommand,
|
||||
SetValueCommand,
|
||||
)
|
||||
from Model.HydraulicStructures.Basic.Types import BHS_types
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class ComboBoxDelegate(QItemDelegate):
|
||||
def __init__(self, data=None, trad=None, parent=None):
|
||||
super(ComboBoxDelegate, self).__init__(parent)
|
||||
|
||||
self._data = data
|
||||
self._trad = trad
|
||||
|
||||
self._long_types = {}
|
||||
if self._trad is not None:
|
||||
self._long_types = self._trad.get_dict("long_types")
|
||||
|
||||
def createEditor(self, parent, option, index):
|
||||
self.editor = QComboBox(parent)
|
||||
|
||||
lst = list(
|
||||
map(
|
||||
lambda k: self._long_types[k],
|
||||
BHS_types.keys()
|
||||
)
|
||||
)
|
||||
self.editor.addItems(lst)
|
||||
|
||||
self.editor.setCurrentText(index.data(Qt.DisplayRole))
|
||||
return self.editor
|
||||
|
||||
def setEditorData(self, editor, index):
|
||||
value = index.data(Qt.DisplayRole)
|
||||
self.editor.currentTextChanged.connect(self.currentItemChanged)
|
||||
|
||||
def setModelData(self, editor, model, index):
|
||||
text = str(editor.currentText())
|
||||
model.setData(index, text)
|
||||
editor.close()
|
||||
editor.deleteLater()
|
||||
|
||||
def updateEditorGeometry(self, editor, option, index):
|
||||
r = QRect(option.rect)
|
||||
if self.editor.windowFlags() & Qt.Popup:
|
||||
if editor.parent() is not None:
|
||||
r.setTopLeft(self.editor.parent().mapToGlobal(r.topLeft()))
|
||||
editor.setGeometry(r)
|
||||
|
||||
@pyqtSlot()
|
||||
def currentItemChanged(self):
|
||||
self.commitData.emit(self.sender())
|
||||
|
||||
|
||||
class TableModel(PamhyrTableModel):
|
||||
def __init__(self, trad=None, **kwargs):
|
||||
self._trad = trad
|
||||
self._long_types = {}
|
||||
if self._trad is not None:
|
||||
self._long_types = self._trad.get_dict("long_types")
|
||||
|
||||
super(TableModel, self).__init__(trad=trad, **kwargs)
|
||||
|
||||
def rowCount(self, parent):
|
||||
return len(self._lst)
|
||||
|
||||
def data(self, index, role):
|
||||
if role != Qt.ItemDataRole.DisplayRole:
|
||||
return QVariant()
|
||||
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
if self._headers[column] == "name":
|
||||
return self._data.basic_structure(row).name
|
||||
elif self._headers[column] == "type":
|
||||
return self._long_types[self._data.basic_structure(row).type]
|
||||
|
||||
return QVariant()
|
||||
|
||||
def setData(self, index, value, role=Qt.EditRole):
|
||||
if not index.isValid() or role != Qt.EditRole:
|
||||
return False
|
||||
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
try:
|
||||
if self._headers[column] == "name":
|
||||
self._undo.push(
|
||||
SetNameCommand(
|
||||
self._data, row, value
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "type":
|
||||
old_type = self._data.basic_structure(row).type
|
||||
|
||||
if old_type == "ND" or self._question_set_type():
|
||||
key = next(
|
||||
k for k, v in self._long_types.items()
|
||||
if v == value
|
||||
)
|
||||
|
||||
self._undo.push(
|
||||
SetTypeCommand(
|
||||
self._data, row, BHS_types[key]
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
def _question_set_type(self):
|
||||
question = QMessageBox(self._parent)
|
||||
|
||||
question.setWindowTitle(self._trad['msg_type_change_title'])
|
||||
question.setText(self._trad['msg_type_change_text'])
|
||||
question.setStandardButtons(QMessageBox.Cancel | QMessageBox.Ok)
|
||||
question.setIcon(QMessageBox.Question)
|
||||
|
||||
res = question.exec()
|
||||
return res == QMessageBox.Ok
|
||||
|
||||
def add(self, row, parent=QModelIndex()):
|
||||
self.beginInsertRows(parent, row, row - 1)
|
||||
|
||||
self._undo.push(
|
||||
AddCommand(
|
||||
self._data, row
|
||||
)
|
||||
)
|
||||
|
||||
self.endInsertRows()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def delete(self, rows, parent=QModelIndex()):
|
||||
self.beginRemoveRows(parent, rows[0], rows[-1])
|
||||
|
||||
self._undo.push(
|
||||
DelCommand(
|
||||
self._data, rows
|
||||
)
|
||||
)
|
||||
|
||||
self.endRemoveRows()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def enabled(self, row, enabled, parent=QModelIndex()):
|
||||
self._undo.push(
|
||||
SetEnabledCommand(
|
||||
self._lst, row, enabled
|
||||
)
|
||||
)
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def undo(self):
|
||||
self._undo.undo()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def redo(self):
|
||||
self._undo.redo()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
|
||||
class ParametersTableModel(PamhyrTableModel):
|
||||
def __init__(self, trad=None, **kwargs):
|
||||
self._trad = trad
|
||||
self._long_types = {}
|
||||
|
||||
if self._trad is not None:
|
||||
self._long_types = self._trad.get_dict("long_types")
|
||||
|
||||
self._hs_index = None
|
||||
|
||||
super(ParametersTableModel, self).__init__(trad=trad, **kwargs)
|
||||
|
||||
def rowCount(self, parent):
|
||||
if self._hs_index is None:
|
||||
return 0
|
||||
|
||||
return len(
|
||||
self._data.basic_structure(self._hs_index)
|
||||
)
|
||||
|
||||
def data(self, index, role):
|
||||
if role != Qt.ItemDataRole.DisplayRole:
|
||||
return QVariant()
|
||||
|
||||
if self._hs_index is None:
|
||||
return QVariant()
|
||||
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
hs = self._data.basic_structure(self._hs_index)
|
||||
|
||||
if self._headers[column] == "name":
|
||||
return self._trad[hs.parameters[row].name]
|
||||
elif self._headers[column] == "value":
|
||||
return str(hs.parameters[row].value)
|
||||
|
||||
return QVariant()
|
||||
|
||||
def setData(self, index, value, role=Qt.EditRole):
|
||||
if not index.isValid() or role != Qt.EditRole:
|
||||
return False
|
||||
|
||||
if self._hs_index is None:
|
||||
return QVariant()
|
||||
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
try:
|
||||
if self._headers[column] == "value":
|
||||
self._undo.push(
|
||||
SetValueCommand(
|
||||
self._data.basic_structure(self._hs_index),
|
||||
row, value
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
def update_hs_index(self, index):
|
||||
self._hs_index = index
|
||||
self.layoutChanged.emit()
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
# translate.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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from PyQt5.QtCore import QCoreApplication
|
||||
|
||||
from View.Translate import MainTranslate
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class BasicHydraulicStructuresTranslate(MainTranslate):
|
||||
def __init__(self):
|
||||
super(BasicHydraulicStructuresTranslate, self).__init__()
|
||||
|
||||
self._dict["Basic Hydraulic Structures"] = _translate(
|
||||
"BasicHydraulicStructures", "Basic Hydraulic Structures"
|
||||
)
|
||||
|
||||
self._dict['msg_type_change_title'] = _translate(
|
||||
"BasicHydraulicStructures",
|
||||
"Change hydraulic structure type"
|
||||
)
|
||||
|
||||
self._dict['msg_type_change_text'] = _translate(
|
||||
"BasicHydraulicStructures",
|
||||
"Do you want to change the hydraulic structure type and reset \
|
||||
hydraulic structure values?"
|
||||
)
|
||||
|
||||
# BHSValues translation
|
||||
|
||||
self._dict['width'] = self._dict["unit_width"]
|
||||
self._dict['height'] = self._dict["unit_thickness"]
|
||||
self._dict['elevation'] = self._dict["unit_elevation"]
|
||||
self._dict['diameter'] = self._dict["unit_diameter"]
|
||||
self._dict['discharge_coefficient'] = _translate(
|
||||
"BasicHydraulicStructures", "Discharge coefficient"
|
||||
)
|
||||
self._dict['loading_elevation'] = _translate(
|
||||
"BasicHydraulicStructures", "Upper elevation (m)"
|
||||
)
|
||||
self._dict['half-angle_tangent'] = _translate(
|
||||
"BasicHydraulicStructures", "Half-angle tangent"
|
||||
)
|
||||
self._dict['maximal_loading_elevation'] = _translate(
|
||||
"BasicHydraulicStructures", "Maximal loading elevation"
|
||||
)
|
||||
self._dict['siltation_height'] = _translate(
|
||||
"BasicHydraulicStructures", "Siltation height (m)"
|
||||
)
|
||||
self._dict['top_of_the_vault'] = _translate(
|
||||
"BasicHydraulicStructures", "Top of the vault (m)"
|
||||
)
|
||||
self._dict['bottom_of_the_vault'] = _translate(
|
||||
"BasicHydraulicStructures", "Bottom of the vault (m)"
|
||||
)
|
||||
self._dict['opening'] = _translate(
|
||||
"BasicHydraulicStructures", "Opening"
|
||||
)
|
||||
self._dict['maximal_opening'] = _translate(
|
||||
"BasicHydraulicStructures", "Maximal opening"
|
||||
)
|
||||
self._dict['step_space'] = _translate(
|
||||
"BasicHydraulicStructures", "Step space"
|
||||
)
|
||||
self._dict['weir'] = _translate(
|
||||
"BasicHydraulicStructures", "Weir"
|
||||
)
|
||||
self._dict['coefficient'] = _translate(
|
||||
"BasicHydraulicStructures", "Coefficient"
|
||||
)
|
||||
|
||||
# Dummy parameters
|
||||
|
||||
self._dict['parameter_1'] = _translate(
|
||||
"BasicHydraulicStructures", "Parameter 1"
|
||||
)
|
||||
self._dict['parameter_2'] = _translate(
|
||||
"BasicHydraulicStructures", "Parameter 2"
|
||||
)
|
||||
self._dict['parameter_3'] = _translate(
|
||||
"BasicHydraulicStructures", "Parameter 3"
|
||||
)
|
||||
self._dict['parameter_4'] = _translate(
|
||||
"BasicHydraulicStructures", "Parameter 4"
|
||||
)
|
||||
self._dict['parameter_5'] = _translate(
|
||||
"BasicHydraulicStructures", "Parameter 5"
|
||||
)
|
||||
|
||||
# BHS types long names
|
||||
|
||||
self._sub_dict["long_types"] = {
|
||||
"ND": self._dict["not_defined"],
|
||||
"S1": _translate(
|
||||
"BasicHydraulicStructures", "Discharge weir"
|
||||
),
|
||||
"S2": _translate(
|
||||
"BasicHydraulicStructures", "Trapezoidal weir"
|
||||
),
|
||||
"S3": _translate(
|
||||
"BasicHydraulicStructures", "Triangular weir"
|
||||
),
|
||||
"OR": _translate(
|
||||
"BasicHydraulicStructures", "Rectangular orifice"
|
||||
),
|
||||
"OC": _translate(
|
||||
"BasicHydraulicStructures", "Circular orifice"
|
||||
),
|
||||
"OV": _translate(
|
||||
"BasicHydraulicStructures", "Vaulted orifice"
|
||||
),
|
||||
"V1": _translate(
|
||||
"BasicHydraulicStructures", "Rectangular gate"
|
||||
),
|
||||
"V2": _translate(
|
||||
"BasicHydraulicStructures", "Simplified rectangular gate"
|
||||
),
|
||||
"BO": _translate(
|
||||
"BasicHydraulicStructures", "Borda-type head loss"
|
||||
),
|
||||
"CV": _translate(
|
||||
"BasicHydraulicStructures", "Check valve"
|
||||
),
|
||||
"UD": _translate(
|
||||
"BasicHydraulicStructures", "User defined"
|
||||
),
|
||||
}
|
||||
|
||||
# Tables
|
||||
|
||||
self._sub_dict["table_headers"] = {
|
||||
"name": self._dict["name"],
|
||||
"type": self._dict["type"],
|
||||
}
|
||||
|
||||
self._sub_dict["table_headers_parameters"] = {
|
||||
"name": self._dict["name"],
|
||||
"value": self._dict["value"],
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
# UndoCommand.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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from copy import deepcopy
|
||||
from tools import trace, timer
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QMessageBox, QUndoCommand, QUndoStack,
|
||||
)
|
||||
|
||||
|
||||
class SetNameCommand(QUndoCommand):
|
||||
def __init__(self, hs, index, new_value):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._hs = hs
|
||||
self._index = index
|
||||
self._old = self._hs.basic_structure(self._index).name
|
||||
self._new = str(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._hs.basic_structure(self._index).name = self._old
|
||||
|
||||
def redo(self):
|
||||
self._hs.basic_structure(self._index).name = self._new
|
||||
|
||||
|
||||
class SetTypeCommand(QUndoCommand):
|
||||
def __init__(self, hs, index, new_type):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._hs = hs
|
||||
self._index = index
|
||||
self._type = new_type
|
||||
self._old = self._hs.basic_structure(self._index)
|
||||
self._new = self._hs.basic_structure(self._index)\
|
||||
.convert(self._type)
|
||||
|
||||
def undo(self):
|
||||
self._hs.delete_i([self._index])
|
||||
self._hs.insert(self._index, self._old)
|
||||
|
||||
def redo(self):
|
||||
self._hs.delete_i([self._index])
|
||||
self._hs.insert(self._index, self._new)
|
||||
|
||||
|
||||
class SetEnabledCommand(QUndoCommand):
|
||||
def __init__(self, hs, index, enabled):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._hs = hs
|
||||
self._index = index
|
||||
self._old = not enabled
|
||||
self._new = enabled
|
||||
|
||||
def undo(self):
|
||||
self._hs.basic_structure(self._index).enabled = self._old
|
||||
|
||||
def redo(self):
|
||||
self._hs.basic_structure(self._index).enabled = self._new
|
||||
|
||||
|
||||
class AddCommand(QUndoCommand):
|
||||
def __init__(self, hs, index):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._hs = hs
|
||||
|
||||
self._index = index
|
||||
self._new = None
|
||||
|
||||
def undo(self):
|
||||
self._hs.delete_i([self._index])
|
||||
|
||||
def redo(self):
|
||||
if self._new is None:
|
||||
self._new = self._hs.add(self._index)
|
||||
else:
|
||||
self._hs.insert(self._index, self._new)
|
||||
|
||||
|
||||
class DelCommand(QUndoCommand):
|
||||
def __init__(self, hs, rows):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._hs = hs
|
||||
|
||||
self._rows = rows
|
||||
|
||||
self._bhs = []
|
||||
for row in rows:
|
||||
self._bhs.append((row, self._hs.basic_structure(row)))
|
||||
|
||||
def undo(self):
|
||||
for row, el in self._bhs:
|
||||
self._hs.insert(row, el)
|
||||
|
||||
def redo(self):
|
||||
self._hs.delete_i(self._rows)
|
||||
|
||||
|
||||
class PasteCommand(QUndoCommand):
|
||||
def __init__(self, hs, row, h_s):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._hs = hs
|
||||
|
||||
self._row = row
|
||||
self._bhs = deepcopy(h_s)
|
||||
self._bhs.reverse()
|
||||
|
||||
def undo(self):
|
||||
self._hs.delete_i(range(self._row, self._row + len(self._bhs)))
|
||||
|
||||
def redo(self):
|
||||
for r in self._bhs:
|
||||
self._hs.insert(self._row, r)
|
||||
|
||||
####################################
|
||||
# Basic hydraulic structure values #
|
||||
####################################
|
||||
|
||||
|
||||
class SetValueCommand(QUndoCommand):
|
||||
def __init__(self, bhs, index, value):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._bhs = bhs
|
||||
self._index = index
|
||||
self._old = self._bhs.parameters[self._index].value
|
||||
self._new = self._bhs.parameters[self._index].type(value)
|
||||
|
||||
def undo(self):
|
||||
self._bhs.parameters[self._index].value = self._old
|
||||
|
||||
def redo(self):
|
||||
self._bhs.parameters[self._index].value = self._new
|
||||
|
|
@ -0,0 +1,270 @@
|
|||
# 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
|
||||
from tools import timer, trace
|
||||
|
||||
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||
|
||||
from PyQt5 import QtCore
|
||||
from PyQt5.QtCore import (
|
||||
Qt, QVariant, QAbstractTableModel, QCoreApplication,
|
||||
pyqtSlot, pyqtSignal, QItemSelectionModel,
|
||||
)
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialogButtonBox, QPushButton, QLineEdit,
|
||||
QFileDialog, QTableView, QAbstractItemView,
|
||||
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||
QHeaderView, QDoubleSpinBox, QVBoxLayout, QCheckBox
|
||||
)
|
||||
|
||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
||||
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
||||
|
||||
from View.HydraulicStructures.PlotAC import PlotAC
|
||||
|
||||
from View.HydraulicStructures.BasicHydraulicStructures.Table import (
|
||||
ComboBoxDelegate, TableModel, ParametersTableModel,
|
||||
)
|
||||
|
||||
from View.Network.GraphWidget import GraphWidget
|
||||
from View.HydraulicStructures.BasicHydraulicStructures.Translate import (
|
||||
BasicHydraulicStructuresTranslate
|
||||
)
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class BasicHydraulicStructuresWindow(PamhyrWindow):
|
||||
_pamhyr_ui = "BasicHydraulicStructures"
|
||||
_pamhyr_name = "Basic Hydraulic Structures"
|
||||
|
||||
def __init__(self, data=None, study=None, config=None, parent=None):
|
||||
trad = BasicHydraulicStructuresTranslate()
|
||||
name = " - ".join([
|
||||
trad[self._pamhyr_name], data.name, study.name
|
||||
])
|
||||
|
||||
super(BasicHydraulicStructuresWindow, self).__init__(
|
||||
title=name,
|
||||
study=study,
|
||||
config=config,
|
||||
trad=trad,
|
||||
parent=parent
|
||||
)
|
||||
|
||||
self._hash_data.append(data)
|
||||
|
||||
self._hs = data
|
||||
|
||||
self.setup_table()
|
||||
self.setup_checkbox()
|
||||
self.setup_plot()
|
||||
self.setup_connections()
|
||||
|
||||
self.update()
|
||||
|
||||
def setup_table(self):
|
||||
self.setup_table_bhs()
|
||||
self.setup_table_bhs_parameters()
|
||||
|
||||
def setup_table_bhs(self):
|
||||
self._table = None
|
||||
|
||||
self._delegate_type = ComboBoxDelegate(
|
||||
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", "type"],
|
||||
delegates={
|
||||
"type": self._delegate_type,
|
||||
},
|
||||
trad=self._trad,
|
||||
data=self._hs,
|
||||
undo=self._undo_stack,
|
||||
parent=self,
|
||||
)
|
||||
|
||||
selectionModel = table.selectionModel()
|
||||
index = table.model().index(0, 0)
|
||||
|
||||
selectionModel.select(
|
||||
index,
|
||||
QItemSelectionModel.Rows |
|
||||
QItemSelectionModel.ClearAndSelect |
|
||||
QItemSelectionModel.Select
|
||||
)
|
||||
table.scrollTo(index)
|
||||
|
||||
def setup_table_bhs_parameters(self):
|
||||
self._table_parameters = None
|
||||
|
||||
table = self.find(QTableView, f"tableView_2")
|
||||
self._table_parameters = ParametersTableModel(
|
||||
table_view=table,
|
||||
table_headers=self._trad.get_dict("table_headers_parameters"),
|
||||
editable_headers=["value"],
|
||||
delegates={},
|
||||
trad=self._trad,
|
||||
data=self._hs,
|
||||
undo=self._undo_stack,
|
||||
parent=self,
|
||||
)
|
||||
|
||||
def setup_checkbox(self):
|
||||
self._checkbox = self.find(QCheckBox, f"checkBox")
|
||||
self._set_checkbox_state()
|
||||
|
||||
def setup_plot(self):
|
||||
self.canvas = MplCanvas(width=5, height=4, dpi=100)
|
||||
self.canvas.setObjectName("canvas")
|
||||
self.toolbar = PamhyrPlotToolbar(
|
||||
self.canvas, self
|
||||
)
|
||||
self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
|
||||
self.plot_layout.addWidget(self.toolbar)
|
||||
self.plot_layout.addWidget(self.canvas)
|
||||
|
||||
reach = self._hs.input_reach
|
||||
profile_kp = self._hs.input_kp
|
||||
if profile_kp is not None:
|
||||
profiles = reach.reach.get_profiles_from_kp(float(profile_kp))
|
||||
else:
|
||||
profiles = None
|
||||
if profiles is not None:
|
||||
profile = profiles[0]
|
||||
else:
|
||||
profile = None
|
||||
|
||||
self.plot_ac = PlotAC(
|
||||
canvas=self.canvas,
|
||||
river=self._study.river,
|
||||
reach=self._hs.input_reach,
|
||||
profile=profile,
|
||||
trad=self._trad,
|
||||
toolbar=self.toolbar
|
||||
)
|
||||
self.plot_ac.draw()
|
||||
|
||||
def setup_connections(self):
|
||||
self.find(QAction, "action_add").triggered.connect(self.add)
|
||||
self.find(QAction, "action_delete").triggered.connect(self.delete)
|
||||
self._checkbox.clicked.connect(self._set_basic_structure_state)
|
||||
|
||||
table = self.find(QTableView, "tableView")
|
||||
table.selectionModel()\
|
||||
.selectionChanged\
|
||||
.connect(self.update)
|
||||
|
||||
self._table.dataChanged.connect(self.update)
|
||||
self._table.layoutChanged.connect(self.update)
|
||||
|
||||
def index_selected(self):
|
||||
table = self.find(QTableView, "tableView")
|
||||
r = table.selectionModel().selectedRows()
|
||||
|
||||
if len(r) > 0:
|
||||
return r[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def index_selected_row(self):
|
||||
table = self.find(QTableView, "tableView")
|
||||
r = table.selectionModel().selectedRows()
|
||||
|
||||
if len(r) > 0:
|
||||
return r[0].row()
|
||||
else:
|
||||
return None
|
||||
|
||||
def index_selected_rows(self):
|
||||
table = self.find(QTableView, "tableView")
|
||||
return list(
|
||||
# Delete duplicate
|
||||
set(
|
||||
map(
|
||||
lambda i: i.row(),
|
||||
table.selectedIndexes()
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def add(self):
|
||||
rows = self.index_selected_rows()
|
||||
|
||||
if len(self._hs) == 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 _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 _set_checkbox_state(self):
|
||||
row = self.index_selected_row()
|
||||
|
||||
if row is None:
|
||||
self._checkbox.setEnabled(False)
|
||||
self._checkbox.setChecked(True)
|
||||
else:
|
||||
self._checkbox.setEnabled(True)
|
||||
self._checkbox.setChecked(self._hs.basic_structure(row).enabled)
|
||||
|
||||
def _set_basic_structure_state(self):
|
||||
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()
|
||||
self._update_parameters_table()
|
||||
|
||||
def _update_parameters_table(self):
|
||||
row = self.index_selected_row()
|
||||
self._table_parameters.update_hs_index(row)
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
# PlotAC.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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from tools import timer
|
||||
from View.Tools.PamhyrPlot import PamhyrPlot
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
|
||||
class PlotAC(PamhyrPlot):
|
||||
def __init__(self, canvas=None, trad=None, toolbar=None,
|
||||
river=None, reach=None, profile=None,
|
||||
parent=None):
|
||||
super(PlotAC, 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["x"]
|
||||
self.label_y = self._trad["unit_elevation"]
|
||||
|
||||
self._isometric_axis = False
|
||||
|
||||
self._auto_relim_update = True
|
||||
self._autoscale_update = True
|
||||
|
||||
@property
|
||||
def river(self):
|
||||
return self.data
|
||||
|
||||
@river.setter
|
||||
def river(self, river):
|
||||
self.data = river
|
||||
|
||||
@timer
|
||||
def draw(self):
|
||||
self.init_axes()
|
||||
|
||||
if self.data is None:
|
||||
self.line_kp = None
|
||||
return
|
||||
|
||||
if self._current_reach is None:
|
||||
self.line_kp = None
|
||||
return
|
||||
|
||||
self.draw_data()
|
||||
|
||||
self.idle()
|
||||
self._init = True
|
||||
|
||||
def draw_data(self):
|
||||
reach = self._current_reach
|
||||
|
||||
if self._current_profile is None:
|
||||
self.line_kp = None
|
||||
else:
|
||||
profile = self._current_profile
|
||||
x = profile.get_station()
|
||||
z = profile.z()
|
||||
|
||||
self.line_kp, = self.canvas.axes.plot(
|
||||
x, z,
|
||||
color=self.color_plot_river_bottom,
|
||||
**self.plot_default_kargs
|
||||
)
|
||||
|
||||
def set_reach(self, reach):
|
||||
self._current_reach = reach
|
||||
self.update()
|
||||
|
||||
def set_profile(self, profile):
|
||||
self._current_profile = profile
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
if self.line_kp is None:
|
||||
self.draw()
|
||||
return
|
||||
|
||||
if self._current_reach is None or self._current_profile is None:
|
||||
self.update_clear()
|
||||
else:
|
||||
self.update_data()
|
||||
|
||||
self.update_idle()
|
||||
|
||||
def update_data(self):
|
||||
profile = self._current_profile
|
||||
x = profile.get_station()
|
||||
z = profile.z()
|
||||
|
||||
self.line_kp.set_data(x, z)
|
||||
|
||||
def clear(self):
|
||||
self.update_clear()
|
||||
|
||||
def update_clear(self):
|
||||
if self.line_kp is not None:
|
||||
self.line_kp.set_data([], [])
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
# 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from tools import timer
|
||||
from View.Tools.PamhyrPlot import PamhyrPlot
|
||||
|
||||
from PyQt5.QtCore import (
|
||||
QCoreApplication
|
||||
)
|
||||
|
||||
from matplotlib.collections import LineCollection
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class PlotKPC(PamhyrPlot):
|
||||
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
|
||||
|
||||
@property
|
||||
def river(self):
|
||||
return self.data
|
||||
|
||||
@river.setter
|
||||
def river(self, river):
|
||||
self.data = river
|
||||
|
||||
@timer
|
||||
def draw(self, highlight=None):
|
||||
self.init_axes()
|
||||
|
||||
if self.data is None:
|
||||
self.profile = None
|
||||
self.line_kp_zmin_zmax = None
|
||||
self.line_kp_zmin = None
|
||||
return
|
||||
|
||||
if self._current_reach is None:
|
||||
self.profile = None
|
||||
self.line_kp_zmin_zmax = None
|
||||
self.line_kp_zmin = None
|
||||
return
|
||||
|
||||
self.draw_data()
|
||||
self.draw_current()
|
||||
|
||||
self.idle()
|
||||
self._init = True
|
||||
|
||||
def draw_data(self):
|
||||
reach = self._current_reach
|
||||
|
||||
kp = reach.reach.get_kp()
|
||||
z_min = reach.reach.get_z_min()
|
||||
z_max = reach.reach.get_z_max()
|
||||
|
||||
self.line_kp_zmin, = self.canvas.axes.plot(
|
||||
kp, z_min,
|
||||
color=self.color_plot_river_bottom,
|
||||
lw=1.
|
||||
)
|
||||
|
||||
if len(kp) != 0:
|
||||
self.line_kp_zmin_zmax = self.canvas.axes.vlines(
|
||||
x=kp,
|
||||
ymin=z_min, ymax=z_max,
|
||||
color=self.color_plot,
|
||||
lw=1.
|
||||
)
|
||||
|
||||
def draw_current(self):
|
||||
if self._current_profile is None:
|
||||
self.profile = None
|
||||
else:
|
||||
kp = [self._current_profile.kp,
|
||||
self._current_profile.kp]
|
||||
min_max = [self._current_profile.z_min(),
|
||||
self._current_profile.z_max()]
|
||||
|
||||
self.profile = self.canvas.axes.plot(
|
||||
kp, min_max,
|
||||
color=self.color_plot_current,
|
||||
lw=1.
|
||||
)
|
||||
|
||||
def set_reach(self, reach):
|
||||
self._current_reach = reach
|
||||
self._current_profile = None
|
||||
self.update()
|
||||
|
||||
def set_profile(self, profile):
|
||||
self._current_profile = profile
|
||||
self.update_current_profile()
|
||||
|
||||
def update(self):
|
||||
self.draw()
|
||||
|
||||
def update_current_profile(self):
|
||||
reach = self._current_reach
|
||||
kp = reach.reach.get_kp()
|
||||
z_min = reach.reach.get_z_min()
|
||||
z_max = reach.reach.get_z_max()
|
||||
|
||||
if self.profile is None:
|
||||
self.draw()
|
||||
else:
|
||||
self.profile.set_data(
|
||||
[self._current_profile.kp, self._current_profile.kp],
|
||||
[self._current_profile.z_min(), self._current_profile.z_max()],
|
||||
)
|
||||
|
||||
self.update_idle()
|
||||
|
||||
def clear(self):
|
||||
if self.profile is not None:
|
||||
self.profile[0].set_data([], [])
|
||||
|
||||
if self.line_kp_zmin_zmax is not None:
|
||||
self.line_kp_zmin_zmax.remove()
|
||||
self.line_kp_zmin_zmax = None
|
||||
|
||||
if self.line_kp_zmin is not None:
|
||||
self.line_kp_zmin.set_data([], [])
|
||||
|
||||
self.canvas.figure.canvas.draw_idle()
|
||||
|
||||
def clear_profile(self):
|
||||
if self.profile is not None:
|
||||
self.profile.set_data([], [])
|
||||
|
||||
self.canvas.figure.canvas.draw_idle()
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
# Table.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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
from tools import trace, timer
|
||||
|
||||
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,
|
||||
)
|
||||
|
||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||
|
||||
from View.HydraulicStructures.UndoCommand import (
|
||||
SetNameCommand, SetReachCommand, SetKpCommand,
|
||||
SetEnabledCommand, AddCommand, DelCommand,
|
||||
)
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class ComboBoxDelegate(QItemDelegate):
|
||||
def __init__(self, data=None, trad=None, parent=None, mode="reaches"):
|
||||
super(ComboBoxDelegate, self).__init__(parent)
|
||||
|
||||
self._data = data
|
||||
self._trad = trad
|
||||
self._mode = mode
|
||||
|
||||
def createEditor(self, parent, option, index):
|
||||
self.editor = QComboBox(parent)
|
||||
|
||||
val = []
|
||||
if self._mode == "kp":
|
||||
reach = self._data.hydraulic_structures\
|
||||
.get(index.row())\
|
||||
.input_reach
|
||||
if reach is not None:
|
||||
val = list(
|
||||
map(
|
||||
lambda kp: str(kp), reach.reach.get_kp()
|
||||
)
|
||||
)
|
||||
else:
|
||||
val = list(
|
||||
map(
|
||||
lambda n: n.name, self._data.edges()
|
||||
)
|
||||
)
|
||||
|
||||
self.editor.addItems(
|
||||
[self._trad['not_associated']] +
|
||||
val
|
||||
)
|
||||
|
||||
self.editor.setCurrentText(str(index.data(Qt.DisplayRole)))
|
||||
return self.editor
|
||||
|
||||
def setEditorData(self, editor, index):
|
||||
value = index.data(Qt.DisplayRole)
|
||||
self.editor.currentTextChanged.connect(self.currentItemChanged)
|
||||
|
||||
def setModelData(self, editor, model, index):
|
||||
text = str(editor.currentText())
|
||||
model.setData(index, text)
|
||||
editor.close()
|
||||
editor.deleteLater()
|
||||
|
||||
def updateEditorGeometry(self, editor, option, index):
|
||||
r = QRect(option.rect)
|
||||
if self.editor.windowFlags() & Qt.Popup:
|
||||
if editor.parent() is not None:
|
||||
r.setTopLeft(self.editor.parent().mapToGlobal(r.topLeft()))
|
||||
editor.setGeometry(r)
|
||||
|
||||
@pyqtSlot()
|
||||
def currentItemChanged(self):
|
||||
self.commitData.emit(self.sender())
|
||||
|
||||
|
||||
class TableModel(PamhyrTableModel):
|
||||
def _setup_lst(self):
|
||||
self._lst = self._data._hydraulic_structures
|
||||
|
||||
def rowCount(self, parent):
|
||||
return len(self._lst)
|
||||
|
||||
def data(self, index, role):
|
||||
if role != Qt.ItemDataRole.DisplayRole:
|
||||
return QVariant()
|
||||
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
if self._headers[column] == "name":
|
||||
return self._lst.get(row).name
|
||||
elif self._headers[column] == "reach":
|
||||
n = self._lst.get(row).input_reach
|
||||
if n is None:
|
||||
return self._trad['not_associated']
|
||||
return n.name
|
||||
elif self._headers[column] == "kp":
|
||||
n = self._lst.get(row).input_kp
|
||||
if n is None:
|
||||
return self._trad['not_associated']
|
||||
return n
|
||||
|
||||
return QVariant()
|
||||
|
||||
def setData(self, index, value, role=Qt.EditRole):
|
||||
if not index.isValid() or role != Qt.EditRole:
|
||||
return False
|
||||
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
na = self._trad['not_associated']
|
||||
|
||||
try:
|
||||
if self._headers[column] == "name":
|
||||
self._undo.push(
|
||||
SetNameCommand(
|
||||
self._lst, row, value
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "reach":
|
||||
if value == na:
|
||||
value = None
|
||||
|
||||
self._undo.push(
|
||||
SetReachCommand(
|
||||
self._lst, row, self._data.edge(value)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "kp":
|
||||
if value == na:
|
||||
value = None
|
||||
|
||||
self._undo.push(
|
||||
SetKpCommand(
|
||||
self._lst, row, value
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
def add(self, row, parent=QModelIndex()):
|
||||
self.beginInsertRows(parent, row, row - 1)
|
||||
|
||||
self._undo.push(
|
||||
AddCommand(
|
||||
self._lst, row
|
||||
)
|
||||
)
|
||||
|
||||
self.endInsertRows()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def delete(self, rows, parent=QModelIndex()):
|
||||
self.beginRemoveRows(parent, rows[0], rows[-1])
|
||||
|
||||
self._undo.push(
|
||||
DelCommand(
|
||||
self._lst, rows
|
||||
)
|
||||
)
|
||||
|
||||
self.endRemoveRows()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def enabled(self, row, enabled, parent=QModelIndex()):
|
||||
self._undo.push(
|
||||
SetEnabledCommand(
|
||||
self._lst, row, enabled
|
||||
)
|
||||
)
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def undo(self):
|
||||
self._undo.undo()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def redo(self):
|
||||
self._undo.redo()
|
||||
self.layoutChanged.emit()
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
# translate.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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from PyQt5.QtCore import QCoreApplication
|
||||
|
||||
from View.Translate import MainTranslate
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class OutputKpAdisTSTranslate(MainTranslate):
|
||||
def __init__(self):
|
||||
super(OutputKpAdisTSTranslate, self).__init__()
|
||||
|
||||
self._dict["Output Kp"] = _translate(
|
||||
"OutputKpAdisTS", "Output Kp"
|
||||
)
|
||||
|
||||
self._dict["x"] = _translate("OutputKpAdisTS", "X (m)")
|
||||
|
||||
self._sub_dict["table_headers"] = {
|
||||
"name": self._dict["name"],
|
||||
"reach": self._dict["reach"],
|
||||
"kp": self._dict["unit_kp"],
|
||||
}
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
# UndoCommand.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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
|
||||
from copy import deepcopy
|
||||
from tools import trace, timer
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QMessageBox, QUndoCommand, QUndoStack,
|
||||
)
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class SetNameCommand(QUndoCommand):
|
||||
def __init__(self, h_s_lst, index, new_value):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._h_s_lst = h_s_lst
|
||||
self._index = index
|
||||
self._old = self._h_s_lst.get(self._index).name
|
||||
self._new = str(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._h_s_lst.get(self._index).name = self._old
|
||||
|
||||
def redo(self):
|
||||
self._h_s_lst.get(self._index).name = self._new
|
||||
|
||||
|
||||
class SetReachCommand(QUndoCommand):
|
||||
def __init__(self, h_s_lst, index, reach):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._h_s_lst = h_s_lst
|
||||
self._index = index
|
||||
self._old = self._h_s_lst.get(self._index).input_reach
|
||||
self._new = reach
|
||||
self._old_kp = self._h_s_lst.get(self._index).input_kp
|
||||
self._new_kp = None
|
||||
|
||||
def undo(self):
|
||||
i = self._h_s_lst.get(self._index)
|
||||
i.input_reach = self._old
|
||||
i.input_kp = self._old_kp
|
||||
|
||||
def redo(self):
|
||||
i = self._h_s_lst.get(self._index)
|
||||
i.input_reach = self._new
|
||||
i.input_kp = self._new_kp
|
||||
|
||||
|
||||
class SetKpCommand(QUndoCommand):
|
||||
def __init__(self, h_s_lst, index, kp):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._h_s_lst = h_s_lst
|
||||
self._index = index
|
||||
self._old = self._h_s_lst.get(self._index).input_kp
|
||||
self._new = kp
|
||||
|
||||
def undo(self):
|
||||
self._h_s_lst.get(self._index).input_kp = self._old
|
||||
|
||||
def redo(self):
|
||||
self._h_s_lst.get(self._index).input_kp = self._new
|
||||
|
||||
|
||||
class SetEnabledCommand(QUndoCommand):
|
||||
def __init__(self, h_s_lst, index, enabled):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._h_s_lst = h_s_lst
|
||||
self._index = index
|
||||
self._old = not enabled
|
||||
self._new = enabled
|
||||
|
||||
def undo(self):
|
||||
self._h_s_lst.get(self._index).enabled = self._old
|
||||
|
||||
def redo(self):
|
||||
self._h_s_lst.get(self._index).enabled = self._new
|
||||
|
||||
|
||||
class AddCommand(QUndoCommand):
|
||||
def __init__(self, h_s_lst, index):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._h_s_lst = h_s_lst
|
||||
|
||||
self._index = index
|
||||
self._new = None
|
||||
|
||||
def undo(self):
|
||||
self._h_s_lst.delete_i([self._index])
|
||||
|
||||
def redo(self):
|
||||
if self._new is None:
|
||||
self._new = self._h_s_lst.new(self._h_s_lst, self._index)
|
||||
else:
|
||||
self._h_s_lst.insert(self._index, self._new)
|
||||
|
||||
|
||||
class DelCommand(QUndoCommand):
|
||||
def __init__(self, h_s_lst, rows):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._h_s_lst = h_s_lst
|
||||
|
||||
self._rows = rows
|
||||
|
||||
self._h_s = []
|
||||
for row in rows:
|
||||
self._h_s.append((row, self._h_s_lst.get(row)))
|
||||
self._h_s.sort()
|
||||
|
||||
def undo(self):
|
||||
for row, el in self._h_s:
|
||||
self._h_s_lst.insert(row, el)
|
||||
|
||||
def redo(self):
|
||||
self._h_s_lst.delete_i(self._rows)
|
||||
|
||||
|
||||
class PasteCommand(QUndoCommand):
|
||||
def __init__(self, h_s_lst, row, h_s):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._h_s_lst = h_s_lst
|
||||
|
||||
self._row = row
|
||||
self._h_s = deepcopy(h_s)
|
||||
self._h_s.reverse()
|
||||
|
||||
def undo(self):
|
||||
self._h_s_lst.delete_i(
|
||||
self._tab,
|
||||
range(self._row, self._row + len(self._h_s))
|
||||
)
|
||||
|
||||
def redo(self):
|
||||
for r in self._h_s:
|
||||
self._h_s_lst.insert(self._row, r)
|
||||
|
|
@ -0,0 +1,315 @@
|
|||
# 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
|
||||
from tools import timer, trace
|
||||
|
||||
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||
|
||||
from PyQt5 import QtCore
|
||||
from PyQt5.QtCore import (
|
||||
Qt, QVariant, QAbstractTableModel, QCoreApplication,
|
||||
pyqtSlot, pyqtSignal, QItemSelectionModel,
|
||||
)
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialogButtonBox, QPushButton, QLineEdit,
|
||||
QFileDialog, QTableView, QAbstractItemView,
|
||||
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||
QHeaderView, QDoubleSpinBox, QVBoxLayout, QCheckBox
|
||||
)
|
||||
|
||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
||||
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
||||
|
||||
from View.OutputKpAdisTS.PlotAC import PlotAC
|
||||
from View.OutputKpAdisTS.PlotKPC import PlotKPC
|
||||
|
||||
from View.OutputKpAdisTS.Table import (
|
||||
TableModel, ComboBoxDelegate
|
||||
)
|
||||
|
||||
from View.Network.GraphWidget import GraphWidget
|
||||
from View.OutputKpAdisTS.Translate import OutputKpAdisTSTranslate
|
||||
|
||||
from View.OutputKpAdisTS.BasicHydraulicStructures.Window import (
|
||||
BasicHydraulicStructuresWindow
|
||||
)
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class OutputKpAdisTSWindow(PamhyrWindow):
|
||||
_pamhyr_ui = "OutputKpAdisTS"
|
||||
_pamhyr_name = "Output Kp"
|
||||
|
||||
def __init__(self, study=None, config=None, parent=None):
|
||||
trad = OutputKpAdisTSTranslate()
|
||||
name = trad[self._pamhyr_name] + " - " + study.name
|
||||
|
||||
super(OutputKpAdisTSWindow, self).__init__(
|
||||
title=name,
|
||||
study=study,
|
||||
config=config,
|
||||
trad=trad,
|
||||
parent=parent
|
||||
)
|
||||
|
||||
self._hs_lst = self._study.river._hydraulic_structures
|
||||
|
||||
self.setup_table()
|
||||
#self.setup_checkbox()
|
||||
#self.setup_plots()
|
||||
self.setup_connections()
|
||||
|
||||
#self.update()
|
||||
|
||||
def setup_table(self):
|
||||
self._table = None
|
||||
|
||||
self._delegate_reach = ComboBoxDelegate(
|
||||
trad=self._trad,
|
||||
data=self._study.river,
|
||||
parent=self,
|
||||
mode="reaches"
|
||||
)
|
||||
self._delegate_kp = ComboBoxDelegate(
|
||||
trad=self._trad,
|
||||
data=self._study.river,
|
||||
parent=self,
|
||||
mode="kp"
|
||||
)
|
||||
|
||||
table = self.find(QTableView, f"tableView")
|
||||
self._table = TableModel(
|
||||
table_view=table,
|
||||
table_headers=self._trad.get_dict("table_headers"),
|
||||
editable_headers=["name", "reach", "kp"],
|
||||
delegates={
|
||||
"reach": self._delegate_reach,
|
||||
"kp": self._delegate_kp,
|
||||
},
|
||||
trad=self._trad,
|
||||
data=self._study.river,
|
||||
undo=self._undo_stack,
|
||||
)
|
||||
|
||||
selectionModel = table.selectionModel()
|
||||
index = table.model().index(0, 0)
|
||||
|
||||
selectionModel.select(
|
||||
index,
|
||||
QItemSelectionModel.Rows |
|
||||
QItemSelectionModel.ClearAndSelect |
|
||||
QItemSelectionModel.Select
|
||||
)
|
||||
table.scrollTo(index)
|
||||
|
||||
def setup_checkbox(self):
|
||||
self._checkbox = self.find(QCheckBox, f"checkBox")
|
||||
self._set_checkbox_state()
|
||||
|
||||
def setup_plots(self):
|
||||
self.canvas = MplCanvas(width=5, height=4, dpi=100)
|
||||
self.canvas.setObjectName("canvas")
|
||||
self.toolbar = PamhyrPlotToolbar(
|
||||
self.canvas, self
|
||||
)
|
||||
self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
|
||||
self.plot_layout.addWidget(self.toolbar)
|
||||
self.plot_layout.addWidget(self.canvas)
|
||||
|
||||
self.plot_kpc = PlotKPC(
|
||||
canvas=self.canvas,
|
||||
river=self._study.river,
|
||||
reach=None,
|
||||
profile=None,
|
||||
trad=self._trad,
|
||||
toolbar=self.toolbar
|
||||
)
|
||||
self.plot_kpc.draw()
|
||||
|
||||
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.plot_layout_2 = self.find(QVBoxLayout, "verticalLayout_2")
|
||||
self.plot_layout_2.addWidget(self.toolbar_2)
|
||||
self.plot_layout_2.addWidget(self.canvas_2)
|
||||
|
||||
self.plot_ac = PlotAC(
|
||||
canvas=self.canvas_2,
|
||||
river=self._study.river,
|
||||
reach=None,
|
||||
profile=None,
|
||||
trad=self._trad,
|
||||
toolbar=self.toolbar_2
|
||||
)
|
||||
self.plot_ac.draw()
|
||||
|
||||
def setup_connections(self):
|
||||
self.find(QAction, "action_add").triggered.connect(self.add)
|
||||
self.find(QAction, "action_delete").triggered.connect(self.delete)
|
||||
self.find(QAction, "action_edit").triggered.connect(self.edit)
|
||||
self._checkbox.clicked.connect(self._set_structure_state)
|
||||
|
||||
table = self.find(QTableView, "tableView")
|
||||
table.selectionModel()\
|
||||
.selectionChanged\
|
||||
.connect(self.update)
|
||||
|
||||
self._table.dataChanged.connect(self.update)
|
||||
self._table.layoutChanged.connect(self.update)
|
||||
|
||||
def index_selected(self):
|
||||
table = self.find(QTableView, "tableView")
|
||||
r = table.selectionModel().selectedRows()
|
||||
|
||||
if len(r) > 0:
|
||||
return r[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def index_selected_row(self):
|
||||
table = self.find(QTableView, "tableView")
|
||||
r = table.selectionModel().selectedRows()
|
||||
|
||||
if len(r) > 0:
|
||||
return r[0].row()
|
||||
else:
|
||||
return None
|
||||
|
||||
def index_selected_rows(self):
|
||||
table = self.find(QTableView, "tableView")
|
||||
return list(
|
||||
# Delete duplicate
|
||||
set(
|
||||
map(
|
||||
lambda i: i.row(),
|
||||
table.selectedIndexes()
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def add(self):
|
||||
rows = self.index_selected_rows()
|
||||
if len(self._hs_lst) == 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 _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(self):
|
||||
rows = self.index_selected_rows()
|
||||
for row in rows:
|
||||
data = self._hs_lst.get(row)
|
||||
|
||||
if self.sub_window_exists(
|
||||
BasicHydraulicStructuresWindow,
|
||||
data=[self._study, None, data]
|
||||
):
|
||||
continue
|
||||
|
||||
win = BasicHydraulicStructuresWindow(
|
||||
data=data,
|
||||
study=self._study,
|
||||
parent=self
|
||||
)
|
||||
win.show()
|
||||
|
||||
def _set_checkbox_state(self):
|
||||
row = self.index_selected_row()
|
||||
if row is None:
|
||||
self._checkbox.setEnabled(False)
|
||||
self._checkbox.setChecked(True)
|
||||
else:
|
||||
self._checkbox.setEnabled(True)
|
||||
self._checkbox.setChecked(self._hs_lst.get(row).enabled)
|
||||
|
||||
def _set_structure_state(self):
|
||||
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()
|
||||
self._update_clear_plot()
|
||||
|
||||
def _update_clear_plot(self):
|
||||
rows = self.index_selected_rows()
|
||||
|
||||
if len(rows) == 0 or len(self._hs_lst) == 0:
|
||||
self._update_clear_all()
|
||||
return
|
||||
|
||||
reach = self._hs_lst.get(rows[0]).input_reach
|
||||
if reach is not None:
|
||||
self.plot_kpc.set_reach(reach)
|
||||
self.plot_ac.set_reach(reach)
|
||||
|
||||
profile_kp = self._hs_lst.get(rows[0]).input_kp
|
||||
if profile_kp is not None:
|
||||
profiles = reach.reach\
|
||||
.get_profiles_from_kp(
|
||||
float(profile_kp)
|
||||
)
|
||||
|
||||
if len(profiles) != 0 and profiles is not None:
|
||||
profile = profiles[0]
|
||||
|
||||
self.plot_kpc.set_profile(profile)
|
||||
self.plot_ac.set_profile(profile)
|
||||
else:
|
||||
self._update_clear_profile()
|
||||
else:
|
||||
self._update_clear_profile()
|
||||
else:
|
||||
self._update_clear_all()
|
||||
|
||||
def _update_clear_all(self):
|
||||
self.plot_kpc.clear()
|
||||
self.plot_ac.clear()
|
||||
|
||||
def _update_clear_profile(self):
|
||||
self.plot_ac.clear()
|
||||
self.plot_kpc.clear_profile()
|
||||
Binary file not shown.
Loading…
Reference in New Issue