mirror of https://gitlab.com/pamhyr/pamhyr2
characteristics pollutant
parent
1e8949067b
commit
37dd4ebaef
|
|
@ -86,7 +86,7 @@ class OutputKpAdists(SQLSubModel):
|
||||||
CREATE TABLE OutputKpAdists(
|
CREATE TABLE OutputKpAdists(
|
||||||
id INTEGER NOT NULL PRIMARY KEY,
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
reach INTEGER NOT NULL,
|
reach INTEGER NOT NULL,
|
||||||
kp INTEGER NOT NULL,
|
kp REAL NOT NULL,
|
||||||
title TEXT NOT NULL,
|
title TEXT NOT NULL,
|
||||||
FOREIGN KEY(edge) REFERENCES river_reach(id)
|
FOREIGN KEY(edge) REFERENCES river_reach(id)
|
||||||
)
|
)
|
||||||
|
|
@ -130,9 +130,18 @@ class OutputKpAdists(SQLSubModel):
|
||||||
|
|
||||||
def _db_save(self, execute, data=None):
|
def _db_save(self, execute, data=None):
|
||||||
|
|
||||||
|
print("print output kp unit")
|
||||||
|
print("id : ", self.id)
|
||||||
|
print("reach : ", self._reach)
|
||||||
|
print("kp : ", self._kp)
|
||||||
|
print("title : ", self._title)
|
||||||
|
print("title format : ", self._db_format(self._title))
|
||||||
|
|
||||||
|
execute(f"DELETE FROM OutputKpAdists WHERE id = {self.id}")
|
||||||
|
|
||||||
sql = (
|
sql = (
|
||||||
"INSERT INTO " +
|
"INSERT INTO " +
|
||||||
"OutputKpAdists(id, reach, kp, title " +
|
"OutputKpAdists(id, reach, kp, title) " +
|
||||||
"VALUES (" +
|
"VALUES (" +
|
||||||
f"{self.id}, {self._reach}, " +
|
f"{self.id}, {self._reach}, " +
|
||||||
f"{self._kp}, '{self._db_format(self._title)}'" +
|
f"{self._kp}, '{self._db_format(self._title)}'" +
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ class OutputKpAdistsList(PamhyrModelList):
|
||||||
return new
|
return new
|
||||||
|
|
||||||
def _db_save(self, execute, data=None):
|
def _db_save(self, execute, data=None):
|
||||||
|
print("save outputkpadists")
|
||||||
ok = True
|
ok = True
|
||||||
|
|
||||||
# Delete previous data
|
# Delete previous data
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ class Pollutants(SQLSubModel):
|
||||||
self._name = str(name)
|
self._name = str(name)
|
||||||
self._enabled = True
|
self._enabled = True
|
||||||
|
|
||||||
self._characteristics = []
|
self._data = []
|
||||||
|
|
||||||
Pollutants._id_cnt = max(
|
Pollutants._id_cnt = max(
|
||||||
Pollutants._id_cnt + 1, self.id)
|
Pollutants._id_cnt + 1, self.id)
|
||||||
|
|
@ -61,6 +61,9 @@ class Pollutants(SQLSubModel):
|
||||||
self._name = name
|
self._name = name
|
||||||
self._status.modified()
|
self._status.modified()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def data(self):
|
||||||
|
return self._data.copy()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_create(cls, execute):
|
def _db_create(cls, execute):
|
||||||
|
|
@ -125,7 +128,7 @@ class Pollutants(SQLSubModel):
|
||||||
for t in table:
|
for t in table:
|
||||||
new_data.append(t)
|
new_data.append(t)
|
||||||
|
|
||||||
new_pollutant._characteristics = new_data
|
new_pollutant._data.append(new_data)
|
||||||
|
|
||||||
new.append(new_pollutant)
|
new.append(new_pollutant)
|
||||||
|
|
||||||
|
|
@ -133,6 +136,8 @@ class Pollutants(SQLSubModel):
|
||||||
|
|
||||||
def _db_save(self, execute, data=None):
|
def _db_save(self, execute, data=None):
|
||||||
|
|
||||||
|
print("save in data base for pollutants")
|
||||||
|
|
||||||
execute(f"DELETE FROM Pollutants WHERE id = {self.id}")
|
execute(f"DELETE FROM Pollutants WHERE id = {self.id}")
|
||||||
execute(f"DELETE FROM Pollutants_characteristics WHERE pollutant = {self.id}")
|
execute(f"DELETE FROM Pollutants_characteristics WHERE pollutant = {self.id}")
|
||||||
|
|
||||||
|
|
@ -147,13 +152,13 @@ class Pollutants(SQLSubModel):
|
||||||
|
|
||||||
execute(sql)
|
execute(sql)
|
||||||
|
|
||||||
for d in self._characteristics:
|
for d in self._data:
|
||||||
sql = (
|
sql = (
|
||||||
"INSERT INTO " +
|
"INSERT INTO " +
|
||||||
"Pollutants_characteristics(type, diametre, rho, porosity, " +
|
"Pollutants_characteristics(type, diametre, rho, porosity, " +
|
||||||
"cdc_riv, cdc_cas, apd, ac, bc) " +
|
"cdc_riv, cdc_cas, apd, ac, bc, pollutant) " +
|
||||||
f"VALUES ({d[1]}, {d[2]}, {d[3]},{d[4]}, {d[5]}, "
|
f"VALUES ({d[0]}, {d[1]}, {d[2]},{d[3]}, {d[4]}, "
|
||||||
f"{d[6]}, {d[7]}, {d[8]}, {d[9]}, {self.id})"
|
f"{d[5]}, {d[6]}, {d[7]}, {d[8]}, {self.id})"
|
||||||
)
|
)
|
||||||
execute(sql)
|
execute(sql)
|
||||||
|
|
||||||
|
|
@ -168,6 +173,13 @@ class Pollutants(SQLSubModel):
|
||||||
self._enabled = enabled
|
self._enabled = enabled
|
||||||
self._status.modified()
|
self._status.modified()
|
||||||
|
|
||||||
|
def is_define(self):
|
||||||
|
return len(self._data) != 0
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._data)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ class PollutantsList(PamhyrModelList):
|
||||||
return new
|
return new
|
||||||
|
|
||||||
def _db_save(self, execute, data=None):
|
def _db_save(self, execute, data=None):
|
||||||
|
print("save pollutantsList")
|
||||||
ok = True
|
ok = True
|
||||||
|
|
||||||
# Delete previous data
|
# Delete previous data
|
||||||
|
|
|
||||||
|
|
@ -232,6 +232,7 @@ class River(Graph, SQLSubModel):
|
||||||
AddFileList,
|
AddFileList,
|
||||||
REPLineList,
|
REPLineList,
|
||||||
OutputKpAdistsList,
|
OutputKpAdistsList,
|
||||||
|
PollutantsList,
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, status=None):
|
def __init__(self, status=None):
|
||||||
|
|
|
||||||
|
|
@ -1,277 +0,0 @@
|
||||||
# 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()
|
|
||||||
|
|
@ -1,155 +0,0 @@
|
||||||
# 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"],
|
|
||||||
}
|
|
||||||
|
|
@ -1,153 +0,0 @@
|
||||||
# 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
|
|
||||||
|
|
@ -1,270 +0,0 @@
|
||||||
# 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,106 @@
|
||||||
|
# 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 datetime import date, time, datetime, timedelta
|
||||||
|
|
||||||
|
from tools import trace, timer
|
||||||
|
|
||||||
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel,
|
||||||
|
QCoreApplication, QModelIndex, pyqtSlot,
|
||||||
|
QRect, QTime, QDateTime,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QTableView, QAbstractItemView, QSpinBox, QItemDelegate,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Pollutants.Edit.UndoCommand import (
|
||||||
|
SetDataCommand, PasteCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class TableModel(PamhyrTableModel):
|
||||||
|
def data(self, index, role):
|
||||||
|
if role == Qt.TextAlignmentRole:
|
||||||
|
return Qt.AlignHCenter | Qt.AlignVCenter
|
||||||
|
|
||||||
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
|
return QVariant()
|
||||||
|
|
||||||
|
row = index.row()
|
||||||
|
column = index.column()
|
||||||
|
|
||||||
|
return self._data.data[row][column]
|
||||||
|
|
||||||
|
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] == "type":
|
||||||
|
self._undo.push(
|
||||||
|
SetDataCommand(
|
||||||
|
self._data, row, column, int(value)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._undo.push(
|
||||||
|
SetDataCommand(
|
||||||
|
self._data, row, column, float(value)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(e)
|
||||||
|
logger.debug(traceback.format_exc())
|
||||||
|
|
||||||
|
self.dataChanged.emit(index, index)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def paste(self, row, data):
|
||||||
|
if len(data) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.layoutAboutToBeChanged.emit()
|
||||||
|
|
||||||
|
self._undo.push(
|
||||||
|
PasteCommand(
|
||||||
|
self._data, row,
|
||||||
|
list(
|
||||||
|
map(
|
||||||
|
lambda d: self._data.new_from_data(d),
|
||||||
|
data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.layoutAboutToBeChanged.emit()
|
||||||
|
self.layoutChanged.emit()
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
# 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
|
||||||
|
|
||||||
|
from View.Pollutants.Translate import PollutantsTranslate
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
|
class EditPollutantTranslate(PollutantsTranslate):
|
||||||
|
def __init__(self):
|
||||||
|
super(EditPollutantTranslate, self).__init__()
|
||||||
|
|
||||||
|
self._dict["Edit Pollutant"] = _translate(
|
||||||
|
"Pollutants", "Edit Pollutant"
|
||||||
|
)
|
||||||
|
|
||||||
|
self._sub_dict["table_headers"] = {
|
||||||
|
"type": self._dict["type"],
|
||||||
|
"diametre": self._dict["unit_area"],
|
||||||
|
"rho": self._dict["unit_rho"],
|
||||||
|
"porosity": self._dict["unit_porosity"],
|
||||||
|
"cdc_riv": self._dict["unit_cdc_riv"],
|
||||||
|
"cdc_cas": self._dict["unit_cdc_cas"],
|
||||||
|
"apd": self._dict["unit_apd"],
|
||||||
|
"ac": self._dict["unit_ac"],
|
||||||
|
"bc": self._dict["unit_bc"],
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
# 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,
|
||||||
|
)
|
||||||
|
|
||||||
|
from Model.Pollutants.Pollutants import Pollutants
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class SetDataCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, index, column, new_value):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._index = index
|
||||||
|
self._column = column
|
||||||
|
self._old = self._data.data[self._index][self._column]
|
||||||
|
self._new = new_value
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._data.data[self._index][self._column] = self._old
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
self._data.data[self._index][self._column] = self._new
|
||||||
|
|
||||||
|
class PasteCommand(QUndoCommand):
|
||||||
|
def __init__(self, data, row, hs):
|
||||||
|
QUndoCommand.__init__(self)
|
||||||
|
|
||||||
|
self._data = data
|
||||||
|
self._row = row
|
||||||
|
self._h = hs
|
||||||
|
self._h.reverse()
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
self._data.delete_i(
|
||||||
|
range(self._row, self._row + len(self._h))
|
||||||
|
)
|
||||||
|
|
||||||
|
def redo(self):
|
||||||
|
for h in self._h:
|
||||||
|
self._data.insert(self._row, h)
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
# 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 View.Tools.PamhyrWidget import PamhyrWidget
|
||||||
|
|
||||||
|
from PyQt5.QtGui import (
|
||||||
|
QKeySequence,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5 import QtCore
|
||||||
|
from PyQt5.QtCore import (
|
||||||
|
Qt, QVariant, QAbstractTableModel, QCoreApplication,
|
||||||
|
pyqtSlot, pyqtSignal,
|
||||||
|
)
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialogButtonBox, QPushButton, QLineEdit,
|
||||||
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
|
QHeaderView, QDoubleSpinBox, QVBoxLayout,
|
||||||
|
)
|
||||||
|
|
||||||
|
from View.Pollutants.Edit.Translate import EditPollutantTranslate
|
||||||
|
from View.Pollutants.Edit.Table import TableModel
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
class EditPolluantWindow(PamhyrWindow):
|
||||||
|
_pamhyr_ui = "Pollutant"
|
||||||
|
_pamhyr_name = "Edit Pollutant"
|
||||||
|
|
||||||
|
def __init__(self, data=None, study=None, config=None, parent=None):
|
||||||
|
self._data = data
|
||||||
|
trad = EditPollutantTranslate()
|
||||||
|
|
||||||
|
name = trad[self._pamhyr_name]
|
||||||
|
print(name)
|
||||||
|
if self._data is not None:
|
||||||
|
name += (
|
||||||
|
f" - {study.name} " +
|
||||||
|
f" - {self._data.name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
super(EditPolluantWindow, self).__init__(
|
||||||
|
title=name,
|
||||||
|
study=study,
|
||||||
|
config=config,
|
||||||
|
trad=trad,
|
||||||
|
parent=parent
|
||||||
|
)
|
||||||
|
|
||||||
|
self._hash_data.append(data)
|
||||||
|
|
||||||
|
self.setup_table()
|
||||||
|
|
||||||
|
def setup_table(self):
|
||||||
|
headers = {}
|
||||||
|
table_headers = self._trad.get_dict("table_headers")
|
||||||
|
|
||||||
|
table = self.find(QTableView, "tableView")
|
||||||
|
self._table = TableModel(
|
||||||
|
table_view=table,
|
||||||
|
table_headers=table_headers,
|
||||||
|
editable_headers=table_headers,
|
||||||
|
delegates={},
|
||||||
|
data=self._data,
|
||||||
|
undo=self._undo_stack,
|
||||||
|
opt_data=self._study.time_system
|
||||||
|
)
|
||||||
|
|
||||||
|
table.setModel(self._table)
|
||||||
|
table.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||||
|
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||||
|
table.setAlternatingRowColors(True)
|
||||||
|
|
||||||
|
def index_selected_row(self):
|
||||||
|
table = self.find(QTableView, "tableView")
|
||||||
|
return table.selectionModel()\
|
||||||
|
.selectedRows()[0]\
|
||||||
|
.row()
|
||||||
|
|
||||||
|
def index_selected_rows(self):
|
||||||
|
table = self.find(QTableView, "tableView")
|
||||||
|
return list(
|
||||||
|
# Delete duplicate
|
||||||
|
set(
|
||||||
|
map(
|
||||||
|
lambda i: i.row(),
|
||||||
|
table.selectedIndexes()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def _copy(self):
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
|
||||||
|
table = []
|
||||||
|
# table.append(self._data.header)
|
||||||
|
table.append(self._trad.get_dict("table_headers"))
|
||||||
|
|
||||||
|
data = self._data.data
|
||||||
|
for row in rows:
|
||||||
|
table.append(list(data[row]))
|
||||||
|
|
||||||
|
self.copyTableIntoClipboard(table)
|
||||||
|
|
||||||
|
def _paste(self):
|
||||||
|
header, data = self.parseClipboardTable()
|
||||||
|
|
||||||
|
logger.debug(f"paste: h:{header}, d:{data}")
|
||||||
|
|
||||||
|
if len(data) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
row = 0
|
||||||
|
rows = self.index_selected_rows()
|
||||||
|
if len(rows) != 0:
|
||||||
|
row = rows[0]
|
||||||
|
|
||||||
|
self._table.paste(row, data)
|
||||||
|
|
||||||
|
def _undo(self):
|
||||||
|
self._table.undo()
|
||||||
|
|
||||||
|
def _redo(self):
|
||||||
|
self._table.redo()
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
# 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([], [])
|
|
||||||
|
|
@ -1,165 +0,0 @@
|
||||||
# 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()
|
|
||||||
|
|
@ -74,6 +74,7 @@ class AddCommand(QUndoCommand):
|
||||||
def redo(self):
|
def redo(self):
|
||||||
if self._new is None:
|
if self._new is None:
|
||||||
self._new = self._pollutants_lst.new(self._pollutants_lst, self._index)
|
self._new = self._pollutants_lst.new(self._pollutants_lst, self._index)
|
||||||
|
self._new._data = [[0, 0., 0., 0., 0., 0., 0., 0., 0.]]
|
||||||
else:
|
else:
|
||||||
self._pollutants_lst.insert(self._index, self._new)
|
self._pollutants_lst.insert(self._index, self._new)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,22 +35,13 @@ from PyQt5.QtWidgets import (
|
||||||
QHeaderView, QDoubleSpinBox, QVBoxLayout, QCheckBox
|
QHeaderView, QDoubleSpinBox, QVBoxLayout, QCheckBox
|
||||||
)
|
)
|
||||||
|
|
||||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
|
||||||
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
|
||||||
|
|
||||||
from View.Pollutants.PlotAC import PlotAC
|
|
||||||
from View.Pollutants.PlotKPC import PlotKPC
|
|
||||||
|
|
||||||
from View.Pollutants.Table import (
|
from View.Pollutants.Table import (
|
||||||
TableModel
|
TableModel
|
||||||
)
|
)
|
||||||
|
|
||||||
from View.Network.GraphWidget import GraphWidget
|
|
||||||
from View.Pollutants.Translate import PollutantsTranslate
|
from View.Pollutants.Translate import PollutantsTranslate
|
||||||
|
|
||||||
from View.Pollutants.BasicHydraulicStructures.Window import (
|
from View.Pollutants.Edit.Window import EditPolluantWindow
|
||||||
BasicHydraulicStructuresWindow
|
|
||||||
)
|
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
@ -183,12 +174,12 @@ class PollutantsWindow(PamhyrWindow):
|
||||||
data = self._pollutants_lst.get(row)
|
data = self._pollutants_lst.get(row)
|
||||||
|
|
||||||
if self.sub_window_exists(
|
if self.sub_window_exists(
|
||||||
BasicHydraulicStructuresWindow,
|
EditPolluantWindow,
|
||||||
data=[self._study, None, data]
|
data=[self._study, None, data]
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
win = BasicHydraulicStructuresWindow(
|
win = EditPolluantWindow(
|
||||||
data=data,
|
data=data,
|
||||||
study=self._study,
|
study=self._study,
|
||||||
parent=self
|
parent=self
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,14 @@ class UnitTranslate(CommonWordTranslate):
|
||||||
self._dict["unit_date_s"] = _translate("Unit", "Date (sec)")
|
self._dict["unit_date_s"] = _translate("Unit", "Date (sec)")
|
||||||
self._dict["unit_date_iso"] = _translate("Unit", "Date (ISO format)")
|
self._dict["unit_date_iso"] = _translate("Unit", "Date (ISO format)")
|
||||||
|
|
||||||
|
self._dict["unit_area"] = _translate("Unit", "Area")
|
||||||
|
self._dict["unit_rho"] = _translate("Unit", "Rho")
|
||||||
|
self._dict["unit_porosity"] = _translate("Unit", "Porosity")
|
||||||
|
self._dict["unit_cdc_riv"] = _translate("Unit", "CDC_RIV")
|
||||||
|
self._dict["unit_cdc_cas"] = _translate("Unit", "CDC_CAS")
|
||||||
|
self._dict["unit_apd"] = _translate("Unit", "APD")
|
||||||
|
self._dict["unit_ac"] = _translate("Unit", "AC")
|
||||||
|
self._dict["unit_bc"] = _translate("Unit", "BC")
|
||||||
|
|
||||||
class MainTranslate(UnitTranslate):
|
class MainTranslate(UnitTranslate):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>800</width>
|
||||||
|
<height>600</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>MainWindow</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QSplitter" name="splitter">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QTableView" name="tableView">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>300</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="baseSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="verticalLayoutWidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout"/>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenuBar" name="menubar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>800</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
|
<widget class="QToolBar" name="toolBar">
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>toolBar</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="toolBarArea">
|
||||||
|
<enum>TopToolBarArea</enum>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="toolBarBreak">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
|
|
@ -122,12 +122,8 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_edit">
|
<action name="action_edit">
|
||||||
<property name="icon">
|
|
||||||
<iconset>
|
|
||||||
<normaloff>ressources/edit.png</normaloff>ressources/edit.png</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Edit</string>
|
<string>Characteristics</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Edit selected hydraulic structure</string>
|
<string>Edit selected hydraulic structure</string>
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue