OutputRK: delete all references to this useless feature

dev_dylan
Dylan Jeannin 2026-07-22 12:54:50 +02:00
parent ae39f33131
commit d027946fb2
15 changed files with 2 additions and 1194 deletions

View File

@ -1,52 +0,0 @@
# Adists.py -- Pamhyr study checkers
# Copyright (C) 2023-2026 INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
import time
import logging
from functools import reduce
from PyQt5.QtCore import QCoreApplication
from Modules import Modules
from Checker.Checker import AbstractModelChecker, STATUS
_translate = QCoreApplication.translate
logger = logging.getLogger()
class AdistsOutputRKChecker(AbstractModelChecker):
def __init__(self):
super(AdistsOutputRKChecker, self).__init__()
self._name = _translate("Checker", "AdisTS output RK checker")
self._description = _translate(
"Checker", "Check output RK"
)
self._modules = Modules.OUTPUT_RK
def run(self, study):
ok = True
nerror = 0
self._summary = "ok"
self._status = STATUS.OK
if not self.basic_check(study):
return False
return ok

View File

@ -1,208 +0,0 @@
# OutputRKAdists.py -- Pamhyr
# Copyright (C) 2023-2026 INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
import logging
from tools import (
trace, timer,
old_pamhyr_date_to_timestamp,
date_iso_to_timestamp,
date_dmy_to_timestamp,
)
from Model.Tools.PamhyrDB import SQLSubModel
from Model.Except import NotImplementedMethodeError
from Model.Scenario import Scenario
logger = logging.getLogger()
class OutputRKAdists(SQLSubModel):
_sub_classes = []
def __init__(self, id: int = -1, reach=None,
rk=None, title: str = "", status=None,
owner_scenario=-1):
super(OutputRKAdists, self).__init__(
id=id, status=status,
owner_scenario=owner_scenario
)
self._reach = reach
self._rk = rk
self._title = str(title)
self._enabled = True
@property
def reach(self):
return self._reach
@reach.setter
def reach(self, reach_id):
self._reach = reach_id
self._status.modified()
@property
def rk(self):
return self._rk
@rk.setter
def rk(self, profile_id):
self._rk = profile_id
self._status.modified()
@property
def title(self):
return self._title
@title.setter
def title(self, title):
self._title = title
self._status.modified()
@classmethod
def _db_create(cls, execute, ext=""):
execute(f"""
CREATE TABLE output_rk_adists{ext}(
{cls.create_db_add_pamhyr_id()},
deleted BOOLEAN NOT NULL DEFAULT FALSE,
reach INTEGER NOT NULL,
rk REAL NOT NULL,
title TEXT NOT NULL,
{Scenario.create_db_add_scenario()},
{Scenario.create_db_add_scenario_fk()},
FOREIGN KEY(reach) REFERENCES river_reach(id)
)
""")
return cls._create_submodel(execute)
@classmethod
def _db_update(cls, execute, version, data=None):
major, minor, release = version.strip().split(".")
if major == "0" and int(minor) < 2:
if cls.is_table_exists(execute, "OutputRKAdists"):
cls._db_update_to_0_2_0(execute, data)
else:
cls._db_create(execute)
return True
@classmethod
def _db_update_to_0_2_0(cls, execute, data):
table = "OutputRKAdists"
table_new = "output_rk_adists"
reachs = data['id2pid']['river_reach']
cls.update_db_add_pamhyr_id(execute, table, data)
Scenario.update_db_add_scenario(execute, table)
cls._db_create(execute, ext="_tmp")
execute(
f"INSERT INTO {table_new}_tmp " +
"(pamhyr_id, reach, rk, title, scenario) " +
"SELECT pamhyr_id, reach, rk, title, scenario " +
f"FROM {table}"
)
execute(f"DROP TABLE {table}")
execute(f"ALTER TABLE {table_new}_tmp RENAME TO {table_new}")
cls._db_update_to_0_2_0_set_reach_pid(execute, table_new, reachs)
@classmethod
def _db_load(cls, execute, data=None):
new = []
status = data['status']
scenario = data["scenario"]
loaded = data['loaded_pid']
# reach = data["reach"]
# profile = data["profile"]
if scenario is None:
return new
table = execute(
"SELECT pamhyr_id, deleted, reach, rk, title, scenario " +
f"FROM output_rk_adists"
)
if table is not None:
for row in table:
it = iter(row)
pid = next(it)
deleted = (next(it) == 1)
id_reach = next(it)
id_rk = next(it)
title = next(it)
owner_scenario = next(it)
new_output = cls(
id=pid, reach=id_reach,
rk=id_rk, title=title,
status=status,
owner_scenario=owner_scenario,
)
if deleted:
new_output.set_as_deleted()
loaded.add(pid)
new.append(new_output)
data["scenario"] = scenario.parent
new += cls._db_load(execute, data)
data["scenario"] = scenario
return new
def _db_save(self, execute, data=None):
if not self.must_be_saved():
return True
execute(
"DELETE FROM output_rk_adists " +
f"WHERE pamhyr_id = {self.id} " +
f"AND scenario = {self._status.scenario_id} "
)
execute(
"INSERT INTO " +
"output_rk_adists(pamhyr_id, deleted, " +
"reach, rk, title, scenario) " +
"VALUES (" +
f"{self.id}, {self._db_format(self.is_deleted())}, " +
f"{self._reach}, {self._rk}, " +
f"'{self._db_format(self._title)}', " +
f"{self._status.scenario_id}" +
")"
)
return True
@property
def enabled(self):
return self._enabled
@enabled.setter
def enabled(self, enabled):
self._enabled = enabled
self._status.modified()

View File

@ -1,59 +0,0 @@
# OutputRKListAdists.py -- Pamhyr
# Copyright (C) 2024-2025 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 trace, timer
from Model.Except import NotImplementedMethodeError
from Model.Tools.PamhyrListExt import PamhyrModelList
from Model.OutputRKAdists.OutputRKAdists import OutputRKAdists
class OutputRKAdistsList(PamhyrModelList):
_sub_classes = [OutputRKAdists]
@classmethod
def _db_load(cls, execute, data=None):
new = cls(status=data["status"])
new._lst = OutputRKAdists._db_load(execute, data)
return new
def _db_save(self, execute, data=None):
ok = True
# Delete previous data
execute(
"DELETE FROM output_rk_adists " +
f"WHERE scenario = {self._status.scenario_id}"
)
for sl in self._lst:
ok &= sl._db_save(execute, data)
return ok
@property
def OutputRK_List(self):
return self.lst
def new(self, lst, index):
n = OutputRKAdists(status=self._status)
self._lst.insert(index, n)
self._status.modified()
return n

View File

@ -49,7 +49,6 @@ from Model.REPLine.REPLineList import REPLineList
from Solver.Solvers import solver_type_list from Solver.Solvers import solver_type_list
from Model.OutputRKAdists.OutputRKListAdists import OutputRKAdistsList
from Model.Pollutants.PollutantsList import PollutantsList from Model.Pollutants.PollutantsList import PollutantsList
from Model.InitialConditionsAdisTS.InitialConditionsAdisTSList \ from Model.InitialConditionsAdisTS.InitialConditionsAdisTSList \
import InitialConditionsAdisTSList import InitialConditionsAdisTSList
@ -478,7 +477,6 @@ class River(Graph):
HydraulicStructureList, HydraulicStructureList,
AddFileList, AddFileList,
REPLineList, REPLineList,
OutputRKAdistsList,
PollutantsList, PollutantsList,
InitialConditionsAdisTSList, InitialConditionsAdisTSList,
BoundaryConditionsAdisTSList, BoundaryConditionsAdisTSList,
@ -515,7 +513,6 @@ class River(Graph):
) )
self._additional_files = AddFileList(status=self._status) self._additional_files = AddFileList(status=self._status)
self._rep_lines = REPLineList(status=self._status) self._rep_lines = REPLineList(status=self._status)
self._Output_rk_adists = OutputRKAdistsList(status=self._status)
self._Pollutants = PollutantsList(status=self._status) self._Pollutants = PollutantsList(status=self._status)
self._InitialConditionsAdisTS = InitialConditionsAdisTSList( self._InitialConditionsAdisTS = InitialConditionsAdisTSList(
status=self._status) status=self._status)
@ -630,10 +627,6 @@ class River(Graph):
new._Pollutants = PollutantsList._db_load(execute, data) new._Pollutants = PollutantsList._db_load(execute, data)
new._Output_rk_adists = OutputRKAdistsList._db_load(
execute, data
)
new._InitialConditionsAdisTS = InitialConditionsAdisTSList._db_load( new._InitialConditionsAdisTS = InitialConditionsAdisTSList._db_load(
execute, data) execute, data)
@ -682,7 +675,6 @@ class River(Graph):
for solver in self._parameters: for solver in self._parameters:
objs.append(self._parameters[solver]) objs.append(self._parameters[solver])
objs.append(self._Output_rk_adists)
objs.append(self._Pollutants) objs.append(self._Pollutants)
objs.append(self._InitialConditionsAdisTS) objs.append(self._InitialConditionsAdisTS)
objs.append(self._BoundaryConditionsAdisTS) objs.append(self._BoundaryConditionsAdisTS)
@ -766,7 +758,6 @@ class River(Graph):
self._hydraulic_structures, self._hydraulic_structures,
self._additional_files, self._additional_files,
self._rep_lines, self._rep_lines,
self._Output_rk_adists,
self._Pollutants, self._Pollutants,
self._InitialConditionsAdisTS, self._InitialConditionsAdisTS,
self._BoundaryConditionsAdisTS, self._BoundaryConditionsAdisTS,
@ -880,10 +871,6 @@ Last export at: @date."""
def parameters(self): def parameters(self):
return self._parameters return self._parameters
@property
def Output_rk_adists(self):
return self._Output_rk_adists
@property @property
def Pollutants(self): def Pollutants(self):
return self._Pollutants return self._Pollutants

View File

@ -32,7 +32,6 @@ class Scenario(SQLSubModel):
tables_with_deleted_column = [ tables_with_deleted_column = [
# Adists # Adists
"output_rk_adists",
"boundary_condition_adists", "boundary_condition_data_adists", "boundary_condition_adists", "boundary_condition_data_adists",
"lateral_contribution_adists", "lateral_contribution_data_adists", "lateral_contribution_adists", "lateral_contribution_data_adists",
"initial_conditions_adists", "initial_conditions_adists_spec", "initial_conditions_adists", "initial_conditions_adists_spec",

View File

@ -55,7 +55,6 @@ class Modules(IterableFlag):
RESERVOIR = auto() RESERVOIR = auto()
SEDIMENT_LAYER = auto() SEDIMENT_LAYER = auto()
ADDITIONAL_FILES = auto() ADDITIONAL_FILES = auto()
OUTPUT_RK = auto()
GEOTIFF = auto() GEOTIFF = auto()
# Results # Results
@ -81,7 +80,6 @@ class Modules(IterableFlag):
cls.ADDITIONAL_FILES, cls.ADDITIONAL_FILES,
cls.RESULTS, cls.RESULTS,
cls.WINDOW_LIST, cls.WINDOW_LIST,
cls.OUTPUT_RK,
cls.GEOTIFF cls.GEOTIFF
] ]

View File

@ -35,10 +35,6 @@ from Solver.CommandLine import CommandLineSolver
from Model.Results.ResultsAdisTS import Results from Model.Results.ResultsAdisTS import Results
from Model.Results.River.River import River, Reach, Profile from Model.Results.River.River import River, Reach, Profile
from Checker.Adists import (
AdistsOutputRKChecker,
)
from itertools import chain from itertools import chain
logger = logging.getLogger() logger = logging.getLogger()
@ -90,11 +86,7 @@ class AdisTS(CommandLineSolver):
@classmethod @classmethod
def checkers(cls): def checkers(cls):
lst = [ return []
AdistsOutputRKChecker(),
]
return lst
########## ##########
# Export # # Export #
@ -821,33 +813,8 @@ class AdisTSwc(AdisTS):
if name != "command_line_arguments": if name != "command_line_arguments":
f.write(f"{dict_names[name]} = {value}\n") f.write(f"{dict_names[name]} = {value}\n")
outputrks = study.river.Output_rk_adists.OutputRK_List
for outputrk in outputrks:
self._export_outputrk(study, outputrk, f, qlog)
return files return files
def _export_outputrk(self, study, outputrk, f, qlog, name="0"):
if (outputrk.reach is None
or outputrk.rk is None
or outputrk.title is None):
return
edges = study.river.enable_edges()
id_edges = list(map(lambda x: x.id, edges))
id_reach = outputrk.reach
reach = next((x for x in edges if x.id == id_reach), None)
rk = outputrk.rk
title = outputrk.title
if reach is None:
return
f.write(f"output = {study.river.get_edge_id(reach)+1} {rk} {title}\n")
@timer @timer
def read_bin(self, study, repertory, results, qlog=None, name="0"): def read_bin(self, study, repertory, results, qlog=None, name="0"):

View File

@ -107,7 +107,6 @@ from View.Results.WindowAdisTT import ResultsWindowAdisTT
from View.Results.ReadingResultsDialog import ReadingResultsDialog from View.Results.ReadingResultsDialog import ReadingResultsDialog
from View.Debug.Window import ReplWindow, TimerWindow from View.Debug.Window import ReplWindow, TimerWindow
from View.OutputRKAdisTS.Window import OutputRKAdisTSWindow
from View.Pollutants.Window import PollutantsWindow from View.Pollutants.Window import PollutantsWindow
from View.D90AdisTS.Window import D90AdisTSWindow from View.D90AdisTS.Window import D90AdisTSWindow
from View.DIFAdisTS.Window import DIFAdisTSWindow from View.DIFAdisTS.Window import DIFAdisTSWindow
@ -173,7 +172,7 @@ define_model_action = [
"action_menu_results_last", "action_menu_open_results_from_file", "action_menu_results_last", "action_menu_open_results_from_file",
"action_menu_compare_scenarios_results", "action_menu_compare_scenarios_results",
"action_menu_boundary_conditions_sediment", "action_menu_boundary_conditions_sediment",
"action_menu_rep_additional_lines", "action_menu_output_rk", "action_menu_rep_additional_lines",
"action_menu_run_adists", "action_menu_pollutants", "action_menu_run_adists", "action_menu_pollutants",
"action_menu_d90", "action_menu_dif", "action_menu_edit_geotiff", "action_menu_d90", "action_menu_dif", "action_menu_edit_geotiff",
"action_menu_boundary_conditions_temperature", "action_menu_boundary_conditions_temperature",
@ -301,7 +300,6 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
self.select_run_solver_adists, self.select_run_solver_adists,
"action_menu_run_adistt": "action_menu_run_adistt":
self.select_run_solver_adistt, self.select_run_solver_adistt,
"action_menu_output_rk": self.open_output_rk_adists,
"action_menu_config": self.open_configure, "action_menu_config": self.open_configure,
"action_menu_new": self.open_new_study, "action_menu_new": self.open_new_study,
"action_menu_edit": self.open_edit_study, "action_menu_edit": self.open_edit_study,
@ -1166,19 +1164,6 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
) )
Pollutants.show() Pollutants.show()
def open_output_rk_adists(self):
if self.sub_window_exists(
OutputRKAdisTSWindow,
data=[self._study, None]
):
return
Output_RK_AdisTS = OutputRKAdisTSWindow(
study=self._study,
parent=self
)
Output_RK_AdisTS.show()
def open_configure(self): def open_configure(self):
"""Open configure window """Open configure window

View File

@ -1,229 +0,0 @@
# Table.py -- Pamhyr
# Copyright (C) 2023-2026 INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
import logging
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.OutputRKAdisTS.UndoCommand import (
SetTitleCommand, SetReachCommand, SetRKCommand,
SetEnabledCommand, AddCommand, DelCommand,
)
from functools import reduce
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 == "rk":
reach_id = self._data.Output_rk_adists \
.get(index.row()) \
.reach
if reach_id is not None:
reach = next(
filter(
lambda edge: edge.id == reach_id, self._data.edges()
)
)
val = list(
map(
lambda rk: str(rk), reach.reach.get_rk()
)
)
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._Output_rk_adists
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] == "title":
return self._lst.get(row).title
elif self._headers[column] == "reach":
n = self._lst.get(row).reach
if n is None:
return self._trad['not_associated']
return next(filter(
lambda edge: edge.id == n, self._data.edges())
).name
elif self._headers[column] == "rk":
n = self._lst.get(row).rk
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
if self.is_same_data(index, value):
return False
row = index.row()
column = index.column()
na = self._trad['not_associated']
try:
if self._headers[column] == "title":
self._undo.push(
SetTitleCommand(
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] == "rk":
if value == na:
value = None
self._undo.push(
SetRKCommand(
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()

View File

@ -1,40 +0,0 @@
# translate.py -- Pamhyr
# Copyright (C) 2023-2026 INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
from PyQt5.QtCore import QCoreApplication
from View.Translate import MainTranslate
_translate = QCoreApplication.translate
class OutputRKAdisTSTranslate(MainTranslate):
def __init__(self):
super(OutputRKAdisTSTranslate, self).__init__()
self._dict["Output RK"] = _translate(
"OutputRKAdisTS", "Output RK"
)
self._dict["x"] = _translate("OutputRKAdisTS", "X (m)")
self._sub_dict["table_headers"] = {
"title": self._dict["title"],
"reach": self._dict["reach"],
"rk": self._dict["unit_rk"],
}

View File

@ -1,155 +0,0 @@
# UndoCommand.py -- Pamhyr
# Copyright (C) 2023-2026 INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
import logging
from copy import deepcopy
from tools import trace, timer
from PyQt5.QtWidgets import (
QMessageBox, QUndoCommand, QUndoStack,
)
logger = logging.getLogger()
class SetTitleCommand(QUndoCommand):
def __init__(self, outputrk_lst, index, new_value):
QUndoCommand.__init__(self)
self._outputrk_lst = outputrk_lst
self._index = index
self._old = self._outputrk_lst.get(self._index).title
self._new = str(new_value)
def undo(self):
self._outputrk_lst.get(self._index).title = self._old
def redo(self):
self._outputrk_lst.get(self._index).title = self._new
class SetReachCommand(QUndoCommand):
def __init__(self, outputrk_lst, index, reach):
QUndoCommand.__init__(self)
self._outputrk_lst = outputrk_lst
self._index = index
self._old = self._outputrk_lst.get(self._index).reach
self._new = reach.id
def undo(self):
i = self._outputrk_lst.get(self._index)
i.reach = self._old
def redo(self):
i = self._outputrk_lst.get(self._index)
i.reach = self._new
class SetRKCommand(QUndoCommand):
def __init__(self, outputrk_lst, index, rk):
QUndoCommand.__init__(self)
self._outputrk_lst = outputrk_lst
self._index = index
self._old = self._outputrk_lst.get(self._index).rk
self._new = rk
def undo(self):
self._outputrk_lst.get(self._index).rk = self._old
def redo(self):
self._outputrk_lst.get(self._index).rk = self._new
class SetEnabledCommand(QUndoCommand):
def __init__(self, outputrk_lst, index, enabled):
QUndoCommand.__init__(self)
self._outputrk_lst = outputrk_lst
self._index = index
self._old = not enabled
self._new = enabled
def undo(self):
self._outputrk_lst.get(self._index).enabled = self._old
def redo(self):
self._outputrk_lst.get(self._index).enabled = self._new
class AddCommand(QUndoCommand):
def __init__(self, outputrk_lst, index):
QUndoCommand.__init__(self)
self._outputrk_lst = outputrk_lst
self._index = index
self._new = None
def undo(self):
self._outputrk_lst.delete_i([self._index])
def redo(self):
if self._new is None:
self._new = self._outputrk_lst.new(self._outputrk_lst, self._index)
else:
self._outputrk_lst.insert(self._index, self._new)
class DelCommand(QUndoCommand):
def __init__(self, outputrk_lst, rows):
QUndoCommand.__init__(self)
self._outputrk_lst = outputrk_lst
self._rows = rows
self._outputrk = []
for row in rows:
self._outputrk.append((row, self._outputrk_lst.get(row)))
self._outputrk.sort()
def undo(self):
for row, el in self._outputrk:
self._outputrk_lst.insert(row, el)
def redo(self):
self._outputrk_lst.delete_i(self._rows)
class PasteCommand(QUndoCommand):
def __init__(self, outputrk_lst, row, outputrk):
QUndoCommand.__init__(self)
self._outputrk_lst = outputrk_lst
self._row = row
self._outputrk = deepcopy(outputrk)
self._outputrk.reverse()
def undo(self):
self._outputrk_lst.delete_i(
self._tab,
range(self._row, self._row + len(self._outputrk))
)
def redo(self):
for r in self._outputrk:
self._outputrk_lst.insert(self._row, r)

View File

@ -1,209 +0,0 @@
# Window.py -- Pamhyr
# Copyright (C) 2023-2026 INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
import logging
from tools import 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.OutputRKAdisTS.Table import (
TableModel, ComboBoxDelegate,
)
from View.Network.GraphWidget import GraphWidget
from View.OutputRKAdisTS.Translate import OutputRKAdisTSTranslate
logger = logging.getLogger()
class OutputRKAdisTSWindow(PamhyrWindow):
_pamhyr_ui = "OutputRKAdisTS"
_pamhyr_name = "Output RK"
def __init__(self, study=None, config=None, parent=None):
trad = OutputRKAdisTSTranslate()
name = trad[self._pamhyr_name] + " - " + study.name
super(OutputRKAdisTSWindow, self).__init__(
title=name,
study=study,
config=config,
trad=trad,
parent=parent
)
self._outputrk_lst = self._study.river._Output_rk_adists
self.setup_table()
self.setup_checkbox()
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_rk = ComboBoxDelegate(
trad=self._trad,
data=self._study.river,
parent=self,
mode="rk"
)
table = self.find(QTableView, f"tableView")
self._table = TableModel(
table_view=table,
table_headers=self._trad.get_dict("table_headers"),
editable_headers=["title", "reach", "rk"],
delegates={
"reach": self._delegate_reach,
"rk": self._delegate_rk,
},
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_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_outputrk_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._outputrk_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 _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._outputrk_lst.get(row).enabled)
def _set_outputrk_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()

View File

@ -225,7 +225,6 @@
<property name="title"> <property name="title">
<string>AdisTS</string> <string>AdisTS</string>
</property> </property>
<addaction name="action_menu_output_rk"/>
<addaction name="action_menu_pollutants"/> <addaction name="action_menu_pollutants"/>
<addaction name="action_menu_d90"/> <addaction name="action_menu_d90"/>
<addaction name="action_menu_dif"/> <addaction name="action_menu_dif"/>
@ -766,11 +765,6 @@
<string>Edit scenarios tree</string> <string>Edit scenarios tree</string>
</property> </property>
</action> </action>
<action name="action_menu_output_rk">
<property name="text">
<string>Output RK</string>
</property>
</action>
<action name="action_menu_run_adists"> <action name="action_menu_run_adists">
<property name="icon"> <property name="icon">
<iconset> <iconset>

View File

@ -1,126 +0,0 @@
<?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>450</height>
</rect>
</property>
<property name="windowTitle">
<string>Hydraulic structures</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QSplitter" name="splitter_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="verticalLayoutWidget_3">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<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>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>5</number>
</property>
<item>
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Enable / Disable Output RK AdisTS</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QWidget" name="verticalLayoutWidget">
<layout class="QVBoxLayout" name="verticalLayout"/>
</widget>
<widget class="QWidget" name="verticalLayoutWidget_2">
<layout class="QVBoxLayout" name="verticalLayout_2"/>
</widget>
</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>
<addaction name="action_add"/>
<addaction name="action_delete"/>
</widget>
<action name="action_add">
<property name="icon">
<iconset>
<normaloff>ressources/add.png</normaloff>ressources/add.png</iconset>
</property>
<property name="text">
<string>Add</string>
</property>
<property name="toolTip">
<string>Add a new point</string>
</property>
</action>
<action name="action_delete">
<property name="icon">
<iconset>
<normaloff>ressources/del.png</normaloff>ressources/del.png</iconset>
</property>
<property name="text">
<string>Delete</string>
</property>
<property name="toolTip">
<string>Delete points</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -406,16 +406,6 @@ Cette fonctionnalité nécessite un bief muni d'une géométrie.</translation>
<source>Check if exists at least one reach exists</source> <source>Check if exists at least one reach exists</source>
<translation>Vérificateur si il exists au moins un bief</translation> <translation>Vérificateur si il exists au moins un bief</translation>
</message> </message>
<message>
<location filename="../Checker/Adists.py" line="37"/>
<source>AdisTS output RK checker</source>
<translation>Vérifie les PK de sortie AdisTS</translation>
</message>
<message>
<location filename="../Checker/Adists.py" line="38"/>
<source>Check output RK</source>
<translation>Vérifie les PK de sortie</translation>
</message>
</context> </context>
<context> <context>
<name>Checklist</name> <name>Checklist</name>
@ -2167,7 +2157,6 @@ Some profiles don&apos;t contain any point.</source>
<translation>Éditer les casiers</translation> <translation>Éditer les casiers</translation>
</message> </message>
<message> <message>
<location filename="../View/ui/OutputRKAdisTS.ui" line="14"/>
<source>Hydraulic structures</source> <source>Hydraulic structures</source>
<translation>Ouvrages hydrauliques</translation> <translation>Ouvrages hydrauliques</translation>
</message> </message>
@ -2386,16 +2375,6 @@ Some profiles don&apos;t contain any point.</source>
<source>Enable / Disable basic hydraulic structure</source> <source>Enable / Disable basic hydraulic structure</source>
<translation>Activer/Désactiver l'ouvrage hydraulique élémentaire</translation> <translation>Activer/Désactiver l'ouvrage hydraulique élémentaire</translation>
</message> </message>
<message>
<location filename="../View/ui/OutputRKAdisTS.ui" line="108"/>
<source>Add a new point</source>
<translation>Ajouter un nouveau point</translation>
</message>
<message>
<location filename="../View/ui/OutputRKAdisTS.ui" line="120"/>
<source>Delete points</source>
<translation>Supprimer les points</translation>
</message>
<message> <message>
<location filename="../View/ui/HydraulicStructures.ui" line="133"/> <location filename="../View/ui/HydraulicStructures.ui" line="133"/>
<source>Edit selected hydraulic structure</source> <source>Edit selected hydraulic structure</source>
@ -2906,11 +2885,6 @@ Some profiles don&apos;t contain any point.</source>
<source>AdisTS</source> <source>AdisTS</source>
<translation>AdisTS</translation> <translation>AdisTS</translation>
</message> </message>
<message>
<location filename="../View/ui/MainWindow.ui" line="769"/>
<source>Output RK</source>
<translation>Pk de sortie</translation>
</message>
<message> <message>
<location filename="../View/ui/MainWindow.ui" line="778"/> <location filename="../View/ui/MainWindow.ui" line="778"/>
<source>Run AdisTS</source> <source>Run AdisTS</source>
@ -2936,11 +2910,6 @@ Some profiles don&apos;t contain any point.</source>
<source>Open results AdisTS</source> <source>Open results AdisTS</source>
<translation>Ouvrir des résultats AdisTS</translation> <translation>Ouvrir des résultats AdisTS</translation>
</message> </message>
<message>
<location filename="../View/ui/OutputRKAdisTS.ui" line="49"/>
<source>Enable / Disable Output RK AdisTS</source>
<translation>Activer / Désactiver la sortie AdisTS</translation>
</message>
<message> <message>
<location filename="../View/ui/EditBoundaryConditionsAdisTS.ui" line="89"/> <location filename="../View/ui/EditBoundaryConditionsAdisTS.ui" line="89"/>
<source>Add a new point in boundary condition or punctual contribution</source> <source>Add a new point in boundary condition or punctual contribution</source>
@ -3388,19 +3357,6 @@ Some profiles don&apos;t contain any point.</source>
<translation>Sélectionner le profile</translation> <translation>Sélectionner le profile</translation>
</message> </message>
</context> </context>
<context>
<name>OutputRKAdisTS</name>
<message>
<location filename="../View/OutputRKAdisTS/Translate.py" line="30"/>
<source>Output RK</source>
<translation>Pk de sortie</translation>
</message>
<message>
<location filename="../View/OutputRKAdisTS/Translate.py" line="34"/>
<source>X (m)</source>
<translation>X (m)</translation>
</message>
</context>
<context> <context>
<name>Pamhyr</name> <name>Pamhyr</name>
<message> <message>