mirror of
https://gitlab.com/pamhyr/pamhyr2.git
synced 2026-10-30 03:20:41 +01:00
Merge branch 'master' into sediment
This commit is contained in:
commit
23fb3e6fb3
147 files changed
+6916
-1002
No files matched your search
+51
-5
@@ -1,3 +1,19 @@
|
||||
# ASubWindow.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 os
|
||||
@@ -19,6 +35,7 @@ from PyQt5.QtWidgets import (
|
||||
QRadioButton, QComboBox, QFileDialog,
|
||||
QMessageBox, QTableView, QAction,
|
||||
QDateTimeEdit, QWidget, QPlainTextEdit,
|
||||
QLabel,
|
||||
)
|
||||
from PyQt5.QtCore import (
|
||||
QTime, QDateTime,
|
||||
@@ -61,13 +78,14 @@ class WindowToolKit(object):
|
||||
|
||||
return header, values
|
||||
|
||||
def file_dialog(self, select_file=True, callback=lambda x: None):
|
||||
def file_dialog(self, select_file=True, callback=lambda x: None, directory=None):
|
||||
"""Open a new file dialog and send result to callback function
|
||||
|
||||
Args:
|
||||
select_file: Select a file if True, else select a dir
|
||||
callback: The callback function with one arguments, files
|
||||
selection list
|
||||
directory: Defaut directory
|
||||
|
||||
Returns:
|
||||
The returns of callback
|
||||
@@ -80,6 +98,8 @@ class WindowToolKit(object):
|
||||
mode = QFileDialog.FileMode.Directory
|
||||
|
||||
dialog.setFileMode(mode)
|
||||
if directory is not None:
|
||||
dialog.setDirectory(directory)
|
||||
|
||||
if dialog.exec_():
|
||||
file_names = dialog.selectedFiles()
|
||||
@@ -130,6 +150,30 @@ class ASubWindowFeatures(object):
|
||||
|
||||
return qtype
|
||||
|
||||
def get_label_text(self, name:str):
|
||||
"""Get text of label component
|
||||
|
||||
Args:
|
||||
label: The label component name
|
||||
|
||||
Returns:
|
||||
Text
|
||||
"""
|
||||
return self.find(QLabel, name).text()
|
||||
|
||||
def set_label_text(self, name:str, text:str):
|
||||
"""Set text of label component
|
||||
|
||||
Args:
|
||||
text_edit: The label component name
|
||||
text: The text
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
self.find(QLabel, name).setText(text)
|
||||
|
||||
|
||||
def set_line_edit_text(self, name:str, text:str):
|
||||
"""Set text of line edit component
|
||||
|
||||
@@ -421,10 +465,12 @@ class ASubWindowFeatures(object):
|
||||
class ASubMainWindow(QMainWindow, ASubWindowFeatures, WindowToolKit):
|
||||
def __init__(self, name="", ui="dummy", parent=None):
|
||||
super(ASubMainWindow, self).__init__(parent=parent)
|
||||
self.ui = loadUi(
|
||||
os.path.join(os.path.dirname(__file__), "ui", f"{ui}.ui"),
|
||||
self
|
||||
)
|
||||
if ui is not None:
|
||||
self.ui = loadUi(
|
||||
os.path.join(os.path.dirname(__file__), "ui", f"{ui}.ui"),
|
||||
self
|
||||
)
|
||||
|
||||
self.name = name
|
||||
self.parent = parent
|
||||
if self.parent is not None:
|
||||
|
||||
@@ -1,8 +1,63 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 os
|
||||
import logging
|
||||
|
||||
from View.ASubWindow import ASubWindow
|
||||
|
||||
from PyQt5.QtCore import QCoreApplication
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
logger = logging.getLogger()
|
||||
|
||||
class AboutWindow(ASubWindow):
|
||||
def _path_file(self, filename):
|
||||
return os.path.abspath(
|
||||
os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
"..", "..", filename
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def __init__(self, title="About", parent=None):
|
||||
super(AboutWindow, self).__init__(name=title, ui="about", parent=parent)
|
||||
self.ui.setWindowTitle(title)
|
||||
|
||||
# Version
|
||||
with open(self._path_file("VERSION"), "r") as f:
|
||||
version = f.readline().strip()
|
||||
logger.info(f"version: {version}")
|
||||
|
||||
label = self.get_label_text("label_version")
|
||||
label = label.replace("@version", version)
|
||||
self.set_label_text("label_version", label)
|
||||
|
||||
# Authors
|
||||
with open(self._path_file("AUTHORS"), "r") as f:
|
||||
label = ""
|
||||
try:
|
||||
while True:
|
||||
author = next(f).strip()
|
||||
logger.info(f"author: {author}")
|
||||
label = f"\n - {author}" + label
|
||||
except StopIteration:
|
||||
label = _translate("About", "Contributors: ") + label
|
||||
label = "Copyright © 2023 INRAE\n" + label
|
||||
self.set_label_text("label_copyright", label)
|
||||
@@ -1,5 +1,23 @@
|
||||
# Plot.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 datetime import datetime
|
||||
|
||||
from tools import timer, trace
|
||||
@@ -13,6 +31,8 @@ from View.BoundaryCondition.Edit.translate import *
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
class Plot(APlot):
|
||||
def __init__(self, canvas=None, data=None,
|
||||
mode = "time", toolbar=None):
|
||||
@@ -25,6 +45,9 @@ class Plot(APlot):
|
||||
self._mode = mode
|
||||
|
||||
def custom_ticks(self):
|
||||
if self.data.header[0] != "time":
|
||||
return
|
||||
|
||||
t0 = datetime.fromtimestamp(0)
|
||||
nb = len(self.data.data)
|
||||
mod = int(nb / 5)
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -196,11 +213,15 @@ class TableModel(QAbstractTableModel):
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
self._undo.push(
|
||||
SetDataCommand(
|
||||
self._data, row, column, value
|
||||
try:
|
||||
self._undo.push(
|
||||
SetDataCommand(
|
||||
self._data, row, column, value
|
||||
)
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -17,7 +33,8 @@ class SetDataCommand(QUndoCommand):
|
||||
self._index = index
|
||||
self._column = column
|
||||
self._old = self._data.get_i(self._index)[self._column]
|
||||
self._new = new_value
|
||||
_type = self._data.get_type_column(self._column)
|
||||
self._new = _type(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._data._set_i_c_v(self._index, self._column, self._old)
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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, trace
|
||||
@@ -55,7 +71,7 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
|
||||
self._title = (
|
||||
_translate("Edit boundary condition", self._title) +
|
||||
f" - {self._study.name} " +
|
||||
f" - {self._data.name} " +
|
||||
f" - {self._data.name} ({self._data.id}) " +
|
||||
f"({long_types[self._data.bctype]} - {node_name})"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# translate.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 (
|
||||
@@ -27,6 +46,8 @@ from View.BoundaryCondition.UndoCommand import (
|
||||
)
|
||||
from View.BoundaryCondition.translate import *
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
class ComboBoxDelegate(QItemDelegate):
|
||||
@@ -137,25 +158,29 @@ class TableModel(QAbstractTableModel):
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
if self._headers[column] == "name":
|
||||
self._undo.push(
|
||||
SetNameCommand(
|
||||
self._bcs, self._tab,row, value
|
||||
try:
|
||||
if self._headers[column] == "name":
|
||||
self._undo.push(
|
||||
SetNameCommand(
|
||||
self._bcs, self._tab,row, value
|
||||
)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "type":
|
||||
key = next(k for k, v in long_types.items() if v == value)
|
||||
self._undo.push(
|
||||
SetTypeCommand(
|
||||
self._bcs, self._tab,row, BC_types[key]
|
||||
elif self._headers[column] == "type":
|
||||
key = next(k for k, v in long_types.items() if v == value)
|
||||
self._undo.push(
|
||||
SetTypeCommand(
|
||||
self._bcs, self._tab,row, BC_types[key]
|
||||
)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "node":
|
||||
self._undo.push(
|
||||
SetNodeCommand(
|
||||
self._bcs, self._tab,row, self._data.node(value)
|
||||
elif self._headers[column] == "node":
|
||||
self._undo.push(
|
||||
SetNodeCommand(
|
||||
self._bcs, self._tab,row, self._data.node(value)
|
||||
)
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -18,7 +34,7 @@ class SetNameCommand(QUndoCommand):
|
||||
self._tab = tab
|
||||
self._index = index
|
||||
self._old = self._bcs.get(self._tab, self._index).name
|
||||
self._new = new_value
|
||||
self._new = str(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._bcs.get(self._tab, self._index).name = self._old
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -49,7 +65,7 @@ logger = logging.getLogger()
|
||||
|
||||
class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
|
||||
def __init__(self, title="Boundary conditions", study=None, parent=None):
|
||||
title = title + " - " + study.name
|
||||
self._title = title + " - " + study.name
|
||||
|
||||
super(BoundaryConditionWindow, self).__init__(
|
||||
name=title, ui="BoundaryConditions", parent=parent
|
||||
@@ -63,7 +79,7 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
|
||||
self.setup_graph()
|
||||
self.setup_connections()
|
||||
|
||||
self.ui.setWindowTitle(title)
|
||||
self.ui.setWindowTitle(self._title)
|
||||
|
||||
def setup_sc(self):
|
||||
self._undo_stack = QUndoStack()
|
||||
@@ -204,9 +220,17 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
|
||||
tab = self.current_tab()
|
||||
rows = self.index_selected_rows()
|
||||
for row in rows:
|
||||
win = EditBoundaryConditionWindow(
|
||||
data=self._bcs.get(tab, row),
|
||||
study=self._study,
|
||||
parent=self
|
||||
win = self.sub_win_filter_first(
|
||||
"Edit boundary condition",
|
||||
contain = [f"({self._bcs.get(tab, row).id})"]
|
||||
)
|
||||
win.show()
|
||||
|
||||
if win is None:
|
||||
win = EditBoundaryConditionWindow(
|
||||
data=self._bcs.get(tab, row),
|
||||
study=self._study,
|
||||
parent=self
|
||||
)
|
||||
win.show()
|
||||
else:
|
||||
win.activateWindow()
|
||||
@@ -1,3 +1,19 @@
|
||||
# translate.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Worker.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 View.ASubWindow import ASubWindow
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# DummyWindow.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 View.ASubWindow import ASubWindow
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# PlotStricklers.py -- Pamhyr
|
||||
# Copyright (C) 2023 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, flatten
|
||||
|
||||
+50
-25
@@ -1,5 +1,24 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 (
|
||||
@@ -24,6 +43,8 @@ from View.Frictions.UndoCommand import (
|
||||
|
||||
from View.Frictions.translate import *
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
class ComboBoxDelegate(QItemDelegate):
|
||||
@@ -132,36 +153,40 @@ class TableModel(QAbstractTableModel):
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
if self._headers[column] == "name":
|
||||
self._undo.push(
|
||||
SetNameCommand(
|
||||
self._frictions, row, value
|
||||
try:
|
||||
if self._headers[column] == "name":
|
||||
self._undo.push(
|
||||
SetNameCommand(
|
||||
self._frictions, row, value
|
||||
)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "begin_kp":
|
||||
self._undo.push(
|
||||
SetBeginCommand(
|
||||
self._frictions, row, value
|
||||
elif self._headers[column] == "begin_kp":
|
||||
self._undo.push(
|
||||
SetBeginCommand(
|
||||
self._frictions, row, value
|
||||
)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "end_kp":
|
||||
self._undo.push(
|
||||
SetEndCommand(
|
||||
self._frictions, row, value
|
||||
elif self._headers[column] == "end_kp":
|
||||
self._undo.push(
|
||||
SetEndCommand(
|
||||
self._frictions, row, value
|
||||
)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "begin_strickler":
|
||||
self._undo.push(
|
||||
SetBeginStricklerCommand(
|
||||
self._frictions, row, self._study.river.strickler(value)
|
||||
elif self._headers[column] == "begin_strickler":
|
||||
self._undo.push(
|
||||
SetBeginStricklerCommand(
|
||||
self._frictions, row, self._study.river.strickler(value)
|
||||
)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "end_strickler":
|
||||
self._undo.push(
|
||||
SetEndStricklerCommand(
|
||||
self._frictions, row, self._study.river.strickler(value)
|
||||
elif self._headers[column] == "end_strickler":
|
||||
self._undo.push(
|
||||
SetEndStricklerCommand(
|
||||
self._frictions, row, self._study.river.strickler(value)
|
||||
)
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -17,7 +33,7 @@ class SetNameCommand(QUndoCommand):
|
||||
self._frictions = frictions
|
||||
self._index = index
|
||||
self._old = self._frictions.get(self._index).name
|
||||
self._new = new_value
|
||||
self._new = str(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._frictions.get(self._index).name = self._old
|
||||
@@ -32,7 +48,7 @@ class SetBeginCommand(QUndoCommand):
|
||||
self._frictions = frictions
|
||||
self._index = index
|
||||
self._old = self._frictions.get(self._index).begin_kp
|
||||
self._new = new_value
|
||||
self._new = float(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._frictions.get(self._index).begin_kp = float(self._old)
|
||||
@@ -47,7 +63,7 @@ class SetEndCommand(QUndoCommand):
|
||||
self._frictions = frictions
|
||||
self._index = index
|
||||
self._old = self._frictions.get(self._index).end_kp
|
||||
self._new = new_value
|
||||
self._new = float(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._frictions.get(self._index).end_kp = float(self._old)
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -52,7 +68,7 @@ class FrictionsWindow(ASubMainWindow, ListedSubWindow):
|
||||
self.setup_title(title)
|
||||
|
||||
super(FrictionsWindow, self).__init__(
|
||||
name=self._title, ui="Frictions", parent=parent
|
||||
name=title, ui="Frictions", parent=parent
|
||||
)
|
||||
|
||||
self.setup_sc()
|
||||
@@ -230,9 +246,17 @@ class FrictionsWindow(ASubMainWindow, ListedSubWindow):
|
||||
self._table.redo()
|
||||
|
||||
def edit_stricklers(self):
|
||||
self.strick = StricklersWindow(
|
||||
study = self._study,
|
||||
config = self.parent.conf,
|
||||
parent = self
|
||||
strick = self.sub_win_filter_first(
|
||||
"Stricklers",
|
||||
contain = []
|
||||
)
|
||||
self.strick.show()
|
||||
|
||||
if strick is None:
|
||||
strick = StricklersWindow(
|
||||
study = self._study,
|
||||
config = self.parent.conf,
|
||||
parent = self
|
||||
)
|
||||
strick.show()
|
||||
else:
|
||||
strick.activateWindow()
|
||||
@@ -1,3 +1,19 @@
|
||||
# translate.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# PlotAC.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# PlotKPC.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# PlotXY.py -- Pamhyr
|
||||
# Copyright (C) 2023 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, trace
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Plot.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,6 +1,24 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 numpy as np
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
from tools import timer, trace
|
||||
|
||||
@@ -20,6 +38,8 @@ from Model.Geometry.ProfileXYZ import ProfileXYZ
|
||||
|
||||
from View.Geometry.Profile.UndoCommand import *
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
@@ -132,38 +152,42 @@ class TableEditableModel(QAbstractTableModel):
|
||||
column = index.column()
|
||||
|
||||
if role == Qt.EditRole:
|
||||
if column == 0:
|
||||
self._undo_stack.push(
|
||||
SetXCommand(
|
||||
self._profile, row,
|
||||
self._profile.point(row).x,
|
||||
value
|
||||
try:
|
||||
if column == 0:
|
||||
self._undo_stack.push(
|
||||
SetXCommand(
|
||||
self._profile, row,
|
||||
self._profile.point(row).x,
|
||||
value
|
||||
)
|
||||
)
|
||||
)
|
||||
elif column == 1:
|
||||
self._undo_stack.push(
|
||||
SetYCommand(
|
||||
self._profile, row,
|
||||
self._profile.point(row).y,
|
||||
value
|
||||
elif column == 1:
|
||||
self._undo_stack.push(
|
||||
SetYCommand(
|
||||
self._profile, row,
|
||||
self._profile.point(row).y,
|
||||
value
|
||||
)
|
||||
)
|
||||
)
|
||||
elif column == 2:
|
||||
self._undo_stack.push(
|
||||
SetZCommand(
|
||||
self._profile, row,
|
||||
self._profile.point(row).z,
|
||||
value
|
||||
elif column == 2:
|
||||
self._undo_stack.push(
|
||||
SetZCommand(
|
||||
self._profile, row,
|
||||
self._profile.point(row).z,
|
||||
value
|
||||
)
|
||||
)
|
||||
)
|
||||
elif column == 3:
|
||||
self._undo_stack.push(
|
||||
SetNameCommand(
|
||||
self._profile, row,
|
||||
self._profile.point(row).name,
|
||||
value
|
||||
elif column == 3:
|
||||
self._undo_stack.push(
|
||||
SetNameCommand(
|
||||
self._profile, row,
|
||||
self._profile.point(row).name,
|
||||
value
|
||||
)
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -16,9 +32,13 @@ class SetDataCommand(QUndoCommand):
|
||||
self._profile = profile
|
||||
self._index = index
|
||||
self._old = old_value
|
||||
self._new = new_value
|
||||
self._new = self.type(new_value)
|
||||
|
||||
class SetXCommand(SetDataCommand):
|
||||
def __init__(self, reach, index, old_value, new_value):
|
||||
self.type = float
|
||||
super(SetXCommand, self).__init__(reach, index, old_value, new_value)
|
||||
|
||||
def undo(self):
|
||||
self._profile.point(self._index).x = self._old
|
||||
|
||||
@@ -26,6 +46,10 @@ class SetXCommand(SetDataCommand):
|
||||
self._profile.point(self._index).x = self._new
|
||||
|
||||
class SetYCommand(SetDataCommand):
|
||||
def __init__(self, reach, index, old_value, new_value):
|
||||
self.type = float
|
||||
super(SetYCommand, self).__init__(reach, index, old_value, new_value)
|
||||
|
||||
def undo(self):
|
||||
self._profile.point(self._index).y = self._old
|
||||
|
||||
@@ -33,6 +57,10 @@ class SetYCommand(SetDataCommand):
|
||||
self._profile.point(self._index).y = self._new
|
||||
|
||||
class SetZCommand(SetDataCommand):
|
||||
def __init__(self, reach, index, old_value, new_value):
|
||||
self.type = float
|
||||
super(SetZCommand, self).__init__(reach, index, old_value, new_value)
|
||||
|
||||
def undo(self):
|
||||
self._profile.point(self._index).z = self._old
|
||||
|
||||
@@ -40,6 +68,10 @@ class SetZCommand(SetDataCommand):
|
||||
self._profile.point(self._index).z = self._new
|
||||
|
||||
class SetNameCommand(SetDataCommand):
|
||||
def __init__(self, reach, index, old_value, new_value):
|
||||
self.type = str
|
||||
super(SetNameCommand, self).__init__(reach, index, old_value, new_value)
|
||||
|
||||
def undo(self):
|
||||
self._profile.point(self._index).name = self._old
|
||||
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 copy
|
||||
@@ -21,7 +37,7 @@ from PyQt5.QtWidgets import (
|
||||
from Model.Geometry.Reach import Reach
|
||||
from Model.Geometry.ProfileXYZ import ProfileXYZ
|
||||
|
||||
from View.ASubWindow import WindowToolKit
|
||||
from View.ASubWindow import ASubMainWindow
|
||||
from View.Geometry.Profile.mainwindow_ui_profile import Ui_MainWindow
|
||||
from View.Geometry.Profile.Plot import Plot
|
||||
from View.Geometry.Profile.Table import *
|
||||
@@ -29,10 +45,14 @@ from View.Geometry.Profile.Table import *
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class ProfileWindow(QMainWindow, WindowToolKit):
|
||||
def __init__(self, profile=None, parent=None):
|
||||
class ProfileWindow(ASubMainWindow):
|
||||
def __init__(self, profile=None, title="Profile", parent=None):
|
||||
self._title = title
|
||||
self.parent = parent
|
||||
super(ProfileWindow, self).__init__(self.parent)
|
||||
super(ProfileWindow, self).__init__(
|
||||
name=self._title,
|
||||
parent=self.parent
|
||||
)
|
||||
|
||||
self.ui = Ui_MainWindow()
|
||||
self.ui.setupUi(self)
|
||||
@@ -66,12 +86,14 @@ class ProfileWindow(QMainWindow, WindowToolKit):
|
||||
if (name is None) or (name == ""):
|
||||
name = _translate("MainWindowProfile", "(no name)")
|
||||
|
||||
self.setWindowTitle(
|
||||
self._title = (
|
||||
header + " - " +
|
||||
f"{self._profile.reach.name}" + " - " +
|
||||
f"{name} ({self._profile.kp})"
|
||||
)
|
||||
|
||||
self.setWindowTitle(self._title)
|
||||
|
||||
def setup_sc(self):
|
||||
self._undo_stack = QUndoStack()
|
||||
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# mainwindow_ui_profile.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 os.path
|
||||
|
||||
+36
-13
@@ -1,6 +1,24 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
import traceback
|
||||
|
||||
from tools import timer, trace
|
||||
|
||||
@@ -21,6 +39,7 @@ from Model.Geometry import Reach
|
||||
from Model.Geometry.ProfileXYZ import ProfileXYZ
|
||||
from View.Geometry.UndoCommand import *
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
@@ -98,23 +117,27 @@ class TableEditableModel(QAbstractTableModel):
|
||||
column = index.column()
|
||||
|
||||
if role == Qt.EditRole and index.column() != 2:
|
||||
if index.column() == 0:
|
||||
self._undo_stack.push(
|
||||
SetNameCommand(
|
||||
self._reach, index.row(),
|
||||
self._reach.profile(index.row()).name,
|
||||
value
|
||||
try:
|
||||
if index.column() == 0:
|
||||
self._undo_stack.push(
|
||||
SetNameCommand(
|
||||
self._reach, index.row(),
|
||||
self._reach.profile(index.row()).name,
|
||||
value
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
if index.column() == 1:
|
||||
self._undo_stack.push(
|
||||
SetKPCommand(
|
||||
self._reach, index.row(),
|
||||
self._reach.profile(index.row()).kp,
|
||||
if index.column() == 1:
|
||||
self._undo_stack.push(
|
||||
SetKPCommand(
|
||||
self._reach, index.row(),
|
||||
self._reach.profile(index.row()).kp,
|
||||
value
|
||||
)
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
self.dataChanged.emit(index, index)
|
||||
self.layoutChanged.emit()
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -17,9 +33,13 @@ class SetDataCommand(QUndoCommand):
|
||||
self._reach = reach
|
||||
self._index = index
|
||||
self._old = old_value
|
||||
self._new = new_value
|
||||
self._new = self.type(new_value)
|
||||
|
||||
class SetNameCommand(SetDataCommand):
|
||||
def __init__(self, reach, index, old_value, new_value):
|
||||
self.type = str
|
||||
super(SetNameCommand, self).__init__(reach, index, old_value, new_value)
|
||||
|
||||
def undo(self):
|
||||
self._reach.profile(self._index).name = self._old
|
||||
|
||||
@@ -27,6 +47,10 @@ class SetNameCommand(SetDataCommand):
|
||||
self._reach.profile(self._index).name = self._new
|
||||
|
||||
class SetKPCommand(SetDataCommand):
|
||||
def __init__(self, reach, index, old_value, new_value):
|
||||
self.type = float
|
||||
super(SetKPCommand, self).__init__(reach, index, old_value, new_value)
|
||||
|
||||
def undo(self):
|
||||
self._reach.profile(self._index).kp = self._old
|
||||
|
||||
|
||||
+39
-10
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 os
|
||||
@@ -25,7 +41,8 @@ from View.Geometry.PlotXY import PlotXY
|
||||
from View.Geometry.PlotKPZ import PlotKPZ
|
||||
from View.Geometry.PlotAC import PlotAC
|
||||
|
||||
from View.ASubWindow import WindowToolKit
|
||||
from View.ASubWindow import ASubMainWindow, WindowToolKit
|
||||
from View.ListedSubWindow import ListedSubWindow
|
||||
from View.Geometry.mainwindow_ui_reach import Ui_MainWindow
|
||||
from View.Geometry.Table import *
|
||||
from View.Geometry.Profile.Window import ProfileWindow
|
||||
@@ -33,10 +50,14 @@ from View.Geometry.Profile.Window import ProfileWindow
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class GeometryWindow(QMainWindow, WindowToolKit):
|
||||
def __init__(self, model=None, parent=None):
|
||||
class GeometryWindow(ASubMainWindow, ListedSubWindow):
|
||||
def __init__(self, model=None, title="Geometry", parent=None):
|
||||
self._title = title
|
||||
self.parent = parent
|
||||
super(GeometryWindow, self).__init__(parent=parent)
|
||||
super(GeometryWindow, self).__init__(
|
||||
name=self._title,
|
||||
parent=parent
|
||||
)
|
||||
|
||||
self._model = model
|
||||
self._reach = model.river.current_reach().reach
|
||||
@@ -59,7 +80,8 @@ class GeometryWindow(QMainWindow, WindowToolKit):
|
||||
self.changed_slider_value()
|
||||
|
||||
def setup_window(self):
|
||||
self.setWindowTitle(f"{self.ui.mainwindow_title} - {self._reach.name}")
|
||||
self._title = f"{self.ui.mainwindow_title} - {self._reach.name}"
|
||||
self.setWindowTitle(self._title)
|
||||
|
||||
def setup_sc(self):
|
||||
self._undo_stack = QUndoStack()
|
||||
@@ -162,13 +184,20 @@ class GeometryWindow(QMainWindow, WindowToolKit):
|
||||
for row in rows:
|
||||
profile = self._reach.profile(row)
|
||||
|
||||
win = ProfileWindow(
|
||||
profile = profile,
|
||||
parent = self,
|
||||
win = self.sub_win_filter_first(
|
||||
"Profile",
|
||||
contain = [self._reach.name, str(profile.kp)]
|
||||
)
|
||||
|
||||
self._profile_window.append(win)
|
||||
win.show()
|
||||
if win is None:
|
||||
win = ProfileWindow(
|
||||
profile = profile,
|
||||
parent = self,
|
||||
)
|
||||
self._profile_window.append(win)
|
||||
win.show()
|
||||
else:
|
||||
win.activateWindow()
|
||||
|
||||
self.tableView.model().blockSignals(False)
|
||||
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# mainwindow_ui_reach.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 sys
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# DialogDischarge.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 View.ASubWindow import ASubWindow
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# DialogHeight.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 View.ASubWindow import ASubWindow
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# PlotDKP.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -26,7 +42,7 @@ class PlotDKP(APlot):
|
||||
return
|
||||
|
||||
self.canvas.axes.set_ylabel(
|
||||
_translate("MainWindow_reach", "Draft (m)"),
|
||||
_translate("MainWindow_reach", "Elevation (m)"),
|
||||
color='green', fontsize=11
|
||||
)
|
||||
self.canvas.axes.set_xlabel(
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# PlotDischarge.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 (
|
||||
@@ -23,6 +41,8 @@ from View.InitialConditions.UndoCommand import (
|
||||
|
||||
from View.InitialConditions.translate import *
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
class ComboBoxDelegate(QItemDelegate):
|
||||
@@ -119,12 +139,16 @@ class TableModel(QAbstractTableModel):
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
if self._headers[column] is not None:
|
||||
self._undo.push(
|
||||
SetCommand(
|
||||
self._ics, row, self._headers[column], value
|
||||
try:
|
||||
if self._headers[column] is not None:
|
||||
self._undo.push(
|
||||
SetCommand(
|
||||
self._ics, row, self._headers[column], value
|
||||
)
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -18,7 +34,12 @@ class SetCommand(QUndoCommand):
|
||||
self._row = row
|
||||
self._column = column
|
||||
self._old = self._ics.get(self._row)[column]
|
||||
self._new = new_value
|
||||
|
||||
_type = float
|
||||
if column == "name" or column == "comment":
|
||||
_type = str
|
||||
|
||||
self._new = _type(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._ics.get(self._row)[self._column] = self._old
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# translate.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Plot.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 datetime import datetime
|
||||
@@ -25,6 +41,9 @@ class Plot(APlot):
|
||||
self._mode = mode
|
||||
|
||||
def custom_ticks(self):
|
||||
if self.data.header[0] != "time":
|
||||
return
|
||||
|
||||
t0 = datetime.fromtimestamp(0)
|
||||
nb = len(self.data.data)
|
||||
mod = int(nb / 5)
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -194,11 +211,15 @@ class TableModel(QAbstractTableModel):
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
self._undo.push(
|
||||
SetDataCommand(
|
||||
self._data, row, column, value
|
||||
try:
|
||||
self._undo.push(
|
||||
SetDataCommand(
|
||||
self._data, row, column, value
|
||||
)
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -17,7 +33,8 @@ class SetDataCommand(QUndoCommand):
|
||||
self._index = index
|
||||
self._column = column
|
||||
self._old = self._data.get_i(self._index)[self._column]
|
||||
self._new = new_value
|
||||
_type = self._data.get_type_column(self._column)
|
||||
self._new = _type(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._data._set_i_c_v(self._index, self._column, self._old)
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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, trace
|
||||
@@ -29,7 +45,7 @@ from View.LateralContribution.Edit.Plot import Plot
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow):
|
||||
def __init__(self, title="Edit lateral conditribution",
|
||||
def __init__(self, title="Edit lateral contribution",
|
||||
data=None, study=None, parent=None):
|
||||
self._data = data
|
||||
self._study = study
|
||||
@@ -38,7 +54,7 @@ class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow):
|
||||
self.compute_title()
|
||||
|
||||
super(EditLateralContributionWindow, self).__init__(
|
||||
name=self._title, ui="EditLateralContribution", parent=parent
|
||||
name=title, ui="EditLateralContribution", parent=parent
|
||||
)
|
||||
|
||||
self.ui.setWindowTitle(self._title)
|
||||
@@ -53,9 +69,9 @@ class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow):
|
||||
edge_name = (self._data.edge.name if self._data.edge is not None
|
||||
else _translate("LateralContribution", "Not associate"))
|
||||
self._title = (
|
||||
_translate("Edit Lateral contribution", self._title) +
|
||||
_translate("Edit lateral contribution", self._title) +
|
||||
f" - {self._study.name} " +
|
||||
f" - {self._data.name} " +
|
||||
f" - {self._data.name} ({self._data.id}) " +
|
||||
f"({long_types[self._data.lctype]} - {edge_name})"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# translate.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 (
|
||||
@@ -27,6 +46,8 @@ from Model.LateralContribution.LateralContributionTypes import (
|
||||
)
|
||||
from View.LateralContribution.translate import *
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
class ComboBoxDelegate(QItemDelegate):
|
||||
@@ -140,37 +161,41 @@ class TableModel(QAbstractTableModel):
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
if self._headers[column] == "name":
|
||||
self._undo.push(
|
||||
SetNameCommand(
|
||||
self._lcs, self._tab, row, value
|
||||
try:
|
||||
if self._headers[column] == "name":
|
||||
self._undo.push(
|
||||
SetNameCommand(
|
||||
self._lcs, self._tab, row, value
|
||||
)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "type":
|
||||
key = next(k for k, v in long_types.items() if v == value)
|
||||
self._undo.push(
|
||||
SetTypeCommand(
|
||||
self._lcs, self._tab, row, LC_types[key]
|
||||
elif self._headers[column] == "type":
|
||||
key = next(k for k, v in long_types.items() if v == value)
|
||||
self._undo.push(
|
||||
SetTypeCommand(
|
||||
self._lcs, self._tab, row, LC_types[key]
|
||||
)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "edge":
|
||||
self._undo.push(
|
||||
SetEdgeCommand(
|
||||
self._lcs, self._tab, row, self._data.edge(value)
|
||||
elif self._headers[column] == "edge":
|
||||
self._undo.push(
|
||||
SetEdgeCommand(
|
||||
self._lcs, self._tab, row, self._data.edge(value)
|
||||
)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "begin_kp":
|
||||
self._undo.push(
|
||||
SetBeginCommand(
|
||||
self._lcs, self._tab, row, value
|
||||
elif self._headers[column] == "begin_kp":
|
||||
self._undo.push(
|
||||
SetBeginCommand(
|
||||
self._lcs, self._tab, row, value
|
||||
)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "end_kp":
|
||||
self._undo.push(
|
||||
SetEndCommand(
|
||||
self._lcs, self._tab, row, value
|
||||
elif self._headers[column] == "end_kp":
|
||||
self._undo.push(
|
||||
SetEndCommand(
|
||||
self._lcs, self._tab, row, value
|
||||
)
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -18,7 +34,7 @@ class SetNameCommand(QUndoCommand):
|
||||
self._tab = tab
|
||||
self._index = index
|
||||
self._old = self._lcs.get(self._tab, self._index).name
|
||||
self._new = new_value
|
||||
self._new = str(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._lcs.get(self._tab, self._index).name = self._old
|
||||
@@ -34,7 +50,7 @@ class SetBeginCommand(QUndoCommand):
|
||||
self._tab = tab
|
||||
self._index = index
|
||||
self._old = self._lcs.get(self._tab, self._index).begin_kp
|
||||
self._new = new_value
|
||||
self._new = float(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._lcs.get(self._tab, self._index).begin_kp = float(self._old)
|
||||
@@ -50,7 +66,7 @@ class SetEndCommand(QUndoCommand):
|
||||
self._tab = tab
|
||||
self._index = index
|
||||
self._old = self._lcs.get(self._tab, self._index).end_kp
|
||||
self._new = new_value
|
||||
self._new = float(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._lcs.get(self._tab, self._index).end_kp = float(self._old)
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -49,7 +65,7 @@ logger = logging.getLogger()
|
||||
|
||||
class LateralContributionWindow(ASubMainWindow, ListedSubWindow):
|
||||
def __init__(self, title="Lateral contribution", study=None, parent=None):
|
||||
title = title + " - " + study.name
|
||||
self._title = title + " - " + study.name
|
||||
|
||||
super(LateralContributionWindow, self).__init__(
|
||||
name=title, ui="LateralContributions", parent=parent
|
||||
@@ -63,7 +79,7 @@ class LateralContributionWindow(ASubMainWindow, ListedSubWindow):
|
||||
self.setup_graph()
|
||||
self.setup_connections()
|
||||
|
||||
self.ui.setWindowTitle(title)
|
||||
self.ui.setWindowTitle(self._title)
|
||||
|
||||
def setup_sc(self):
|
||||
self._undo_stack = QUndoStack()
|
||||
@@ -250,9 +266,17 @@ class LateralContributionWindow(ASubMainWindow, ListedSubWindow):
|
||||
tab = self.current_tab()
|
||||
rows = self.index_selected_rows()
|
||||
for row in rows:
|
||||
win = EditLateralContributionWindow(
|
||||
data=self._lcs.get(tab, row),
|
||||
study=self._study,
|
||||
parent=self
|
||||
win = self.sub_win_filter_first(
|
||||
"Edit lateral contribution",
|
||||
contain = [f"({self._lcs.get(tab, row).id})"]
|
||||
)
|
||||
win.show()
|
||||
|
||||
if win is None:
|
||||
win = EditLateralContributionWindow(
|
||||
data=self._lcs.get(tab, row),
|
||||
study=self._study,
|
||||
parent=self
|
||||
)
|
||||
win.show()
|
||||
else:
|
||||
win.activateWindow()
|
||||
@@ -1,3 +1,19 @@
|
||||
# translate.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# ListedSubWindow.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -32,9 +48,50 @@ class ListedSubWindow(object):
|
||||
self.sub_win_cnt = len(self.sub_win_list)
|
||||
logger.info(f"Close window: {name} ({self.sub_win_cnt})")
|
||||
|
||||
def sub_win_exists(self, name):
|
||||
def _sub_win_exists(self, name):
|
||||
return reduce(
|
||||
lambda acc, n: (acc or (n[0] == name)),
|
||||
self.sub_win_list,
|
||||
False
|
||||
)
|
||||
|
||||
def _sub_win_exists_with_contain(self, name, contain):
|
||||
return reduce(
|
||||
lambda acc, n: (
|
||||
acc or
|
||||
(
|
||||
(n[0] == name) and
|
||||
reduce(
|
||||
lambda acc, c: acc and (c in n[1]._title),
|
||||
contain,
|
||||
True
|
||||
)
|
||||
)
|
||||
),
|
||||
self.sub_win_list,
|
||||
False
|
||||
)
|
||||
|
||||
def sub_win_exists(self, name, contain = []):
|
||||
if contain == []:
|
||||
return self._sub_win_exists(name)
|
||||
else:
|
||||
return self._sub_win_exists_with_contain(name, contain)
|
||||
|
||||
def sub_win_filter_first(self, name, contain):
|
||||
try:
|
||||
return next(
|
||||
filter(
|
||||
lambda n: (
|
||||
(name in n[0]) and
|
||||
reduce(
|
||||
lambda acc, c: acc and (c in n[1]._title),
|
||||
contain,
|
||||
True
|
||||
)
|
||||
),
|
||||
self.sub_win_list,
|
||||
)
|
||||
)[1]
|
||||
except:
|
||||
return None
|
||||
+185
-32
@@ -1,3 +1,19 @@
|
||||
# MainWindow.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 os
|
||||
@@ -39,6 +55,7 @@ from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow
|
||||
from View.SolverParameters.Window import SolverParametersWindow
|
||||
from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow
|
||||
from View.CheckList.Window import CheckListWindow
|
||||
from View.Results.Window import ResultsWindow
|
||||
from View.Debug.Window import ReplWindow
|
||||
|
||||
from Model.Study import Study
|
||||
@@ -93,6 +110,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||
# Model
|
||||
self.model = None
|
||||
|
||||
# Results
|
||||
self._last_results = None
|
||||
|
||||
# UI
|
||||
self.ui = loadUi(
|
||||
os.path.join(os.path.dirname(__file__), "ui", "MainWindow.ui"),
|
||||
@@ -107,6 +127,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||
self.trans = QTranslator(self)
|
||||
#self.ui.retranslateUi()
|
||||
|
||||
if self.conf.last_study != "" and not self.conf.close_correctly:
|
||||
self.dialog_reopen_study()
|
||||
|
||||
def set_title(self):
|
||||
if self.model is not None:
|
||||
self.setWindowTitle(f"PAMHYR - {self.model.name}")
|
||||
@@ -192,16 +215,24 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||
if self.model is not None and not self.model.is_saved:
|
||||
self._close_question = True
|
||||
if self.dialog_close():
|
||||
# PAMHYR is close correctly (no crash)
|
||||
self.conf.set_close_correctly()
|
||||
|
||||
super(ApplicationWindow, self).close()
|
||||
else:
|
||||
self._close_question = False
|
||||
else:
|
||||
# PAMHYR is close correctly (no crash)
|
||||
self.conf.set_close_correctly()
|
||||
|
||||
super(ApplicationWindow, self).close()
|
||||
|
||||
def closeEvent(self, event):
|
||||
if not self._close_question:
|
||||
if self.model is not None and not self.model.is_saved:
|
||||
if self.dialog_close(cancel = False):
|
||||
# PAMHYR is close correctly (no crash)
|
||||
self.conf.set_close_correctly()
|
||||
super(ApplicationWindow, self).closeEvent(event)
|
||||
else:
|
||||
super(ApplicationWindow, self).closeEvent(event)
|
||||
@@ -261,11 +292,13 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||
def set_model(self, model):
|
||||
self.model = model
|
||||
self.update_enable_action()
|
||||
self.conf.set_last_study(self.model.filename)
|
||||
self.set_title()
|
||||
|
||||
def close_model(self):
|
||||
self.model = None
|
||||
self.update_enable_action()
|
||||
self.conf.set_close_correctly()
|
||||
self.set_title()
|
||||
|
||||
def update_enable_action(self):
|
||||
@@ -288,10 +321,26 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||
for action in model_action:
|
||||
self.enable_actions(action, not no_model)
|
||||
|
||||
def set_results(self, results):
|
||||
self._last_results = results
|
||||
|
||||
############
|
||||
# FEATURES #
|
||||
############
|
||||
|
||||
def open_study(self, filename):
|
||||
"""Open a study
|
||||
|
||||
Args:
|
||||
filename: The study path
|
||||
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
self.set_model(Study.open(filename))
|
||||
logger.info(f"Open Study - {self.model.name}")
|
||||
self.set_title()
|
||||
|
||||
def save_study(self):
|
||||
"""Save current study
|
||||
|
||||
@@ -348,6 +397,27 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||
"Geometry edition need a reach selected "
|
||||
"into river network window to work on it")
|
||||
|
||||
def dialog_reopen_study(self):
|
||||
dlg = QMessageBox(self)
|
||||
|
||||
dlg.setWindowTitle("Last open study")
|
||||
dlg.setText("Do you want to open again the last open study?")
|
||||
opt = QMessageBox.Cancel | QMessageBox.Ok #| QMessageBox.Open
|
||||
|
||||
dlg.setStandardButtons(opt)
|
||||
dlg.setIcon(QMessageBox.Question)
|
||||
|
||||
res = dlg.exec()
|
||||
|
||||
if res == QMessageBox.Ok:
|
||||
self.open_study(self.conf.last_study)
|
||||
return True
|
||||
elif res == QMessageBox.Open:
|
||||
self.open_model()
|
||||
return True
|
||||
elif res == QMessageBox.Cancel:
|
||||
return False
|
||||
|
||||
def dialog_close(self, cancel = True):
|
||||
dlg = QMessageBox(self)
|
||||
|
||||
@@ -408,12 +478,11 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||
dialog.setDefaultSuffix(".pamhyr")
|
||||
#dialog.setFilter(dialog.filter() | QtCore.QDir.Hidden)
|
||||
dialog.setNameFilters(['PamHyr (*.pamhyr)'])
|
||||
dialog.setDirectory(os.path.dirname(self.conf.last_study))
|
||||
|
||||
if dialog.exec_():
|
||||
file_name = dialog.selectedFiles()
|
||||
self.set_model(Study.open(file_name[0]))
|
||||
logger.info(f"Open Study - {self.model.name}")
|
||||
self.set_title()
|
||||
self.open_study(file_name[0])
|
||||
|
||||
def open_new_study(self):
|
||||
"""Open dialog to set new study
|
||||
@@ -441,10 +510,12 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
if (self.model is not None and
|
||||
not self.sub_win_exists("River network")):
|
||||
self.network = NetworkWindow(model=self.model, parent=self)
|
||||
self.network.show()
|
||||
if self.model is not None:
|
||||
if not self.sub_win_exists("River network"):
|
||||
self.network = NetworkWindow(model=self.model, parent=self)
|
||||
self.network.show()
|
||||
else:
|
||||
self.network.activateWindow()
|
||||
|
||||
def open_geometry(self):
|
||||
"""Open geometry window
|
||||
@@ -452,56 +523,112 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
if (self.model is not None and
|
||||
self.model.river.has_current_reach()):
|
||||
geometry = GeometryWindow(model=self.model, parent=self)
|
||||
geometry.show()
|
||||
if (self.model is not None and self.model.river.has_current_reach()):
|
||||
geometry = self.sub_win_filter_first(
|
||||
"Geometry",
|
||||
contain = [self.model.river.current_reach().name]
|
||||
)
|
||||
|
||||
if geometry is None:
|
||||
geometry = GeometryWindow(model=self.model, parent=self)
|
||||
geometry.show()
|
||||
else:
|
||||
geometry.activateWindow()
|
||||
else:
|
||||
self.msg_select_reach()
|
||||
|
||||
def open_boundary_cond(self):
|
||||
bound = BoundaryConditionWindow(study = self.model, parent = self)
|
||||
bound.show()
|
||||
bound = self.sub_win_filter_first(
|
||||
"Boundary conditions",
|
||||
contain = []
|
||||
)
|
||||
|
||||
if bound is None:
|
||||
bound = BoundaryConditionWindow(study = self.model, parent = self)
|
||||
bound.show()
|
||||
else:
|
||||
bound.activateWindow()
|
||||
|
||||
def open_lateral_contrib(self):
|
||||
lateral = LateralContributionWindow(study = self.model, parent = self)
|
||||
lateral.show()
|
||||
lateral = self.sub_win_filter_first(
|
||||
"Lateral contribution",
|
||||
contain = []
|
||||
)
|
||||
|
||||
if lateral is None:
|
||||
lateral = LateralContributionWindow(study = self.model, parent = self)
|
||||
lateral.show()
|
||||
else:
|
||||
lateral.activateWindow()
|
||||
|
||||
def open_stricklers(self):
|
||||
strick = StricklersWindow(
|
||||
study = self.model,
|
||||
config = self.conf,
|
||||
parent = self
|
||||
strick = self.sub_win_filter_first(
|
||||
"Stricklers",
|
||||
contain = []
|
||||
)
|
||||
strick.show()
|
||||
|
||||
if strick is None:
|
||||
strick = StricklersWindow(
|
||||
study = self.model,
|
||||
config = self.conf,
|
||||
parent = self
|
||||
)
|
||||
strick.show()
|
||||
else:
|
||||
strick.activateWindow()
|
||||
|
||||
def open_frictions(self):
|
||||
if (self.model is not None and
|
||||
self.model.river.has_current_reach()):
|
||||
frictions = FrictionsWindow(
|
||||
study = self.model,
|
||||
parent = self
|
||||
|
||||
frictions = self.sub_win_filter_first(
|
||||
"Frictions",
|
||||
contain = [self.model.river.current_reach().name]
|
||||
)
|
||||
frictions.show()
|
||||
|
||||
if frictions is None:
|
||||
frictions = FrictionsWindow(
|
||||
study = self.model,
|
||||
parent = self
|
||||
)
|
||||
frictions.show()
|
||||
else:
|
||||
frictions.activateWindow()
|
||||
else:
|
||||
self.msg_select_reach()
|
||||
|
||||
def open_initial_conditions(self):
|
||||
if self.model.river.has_current_reach():
|
||||
initial = InitialConditionsWindow(
|
||||
study = self.model,
|
||||
parent = self
|
||||
initial = self.sub_win_filter_first(
|
||||
"Initial condition",
|
||||
contain = [self.model.river.current_reach().name]
|
||||
)
|
||||
initial.show()
|
||||
|
||||
if initial is None:
|
||||
initial = InitialConditionsWindow(
|
||||
study = self.model,
|
||||
parent = self
|
||||
)
|
||||
initial.show()
|
||||
else:
|
||||
initial.activateWindow()
|
||||
else:
|
||||
self.msg_select_reach()
|
||||
|
||||
def open_solver_parameters(self):
|
||||
params = SolverParametersWindow(
|
||||
study = self.model,
|
||||
parent = self
|
||||
params = self.sub_win_filter_first(
|
||||
"Solver parameters",
|
||||
contain = []
|
||||
)
|
||||
params.show()
|
||||
|
||||
if params is None:
|
||||
params = SolverParametersWindow(
|
||||
study = self.model,
|
||||
parent = self
|
||||
)
|
||||
params.show()
|
||||
else:
|
||||
params.activateWindow()
|
||||
|
||||
def open_sediment_layers(self):
|
||||
sl = SedimentLayersWindow(
|
||||
@@ -545,6 +672,32 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||
)
|
||||
sol.show()
|
||||
|
||||
def open_solver_results(self, solver, results = None):
|
||||
# If no specific results, get last results
|
||||
if results is None:
|
||||
results = self._last_results
|
||||
|
||||
# No results available
|
||||
if results is None:
|
||||
return
|
||||
|
||||
# Windows already opened
|
||||
res = self.sub_win_filter_first(
|
||||
"Results",
|
||||
contain = [solver.name, results.date]
|
||||
)
|
||||
|
||||
if res is None:
|
||||
res = ResultsWindow(
|
||||
study = self.model,
|
||||
solver = solver,
|
||||
results = results,
|
||||
parent = self
|
||||
)
|
||||
res.show()
|
||||
else:
|
||||
res.activateWindow()
|
||||
|
||||
#########
|
||||
# DEBUG #
|
||||
#########
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
# GraphWidget.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 math
|
||||
import logging
|
||||
|
||||
from tools import timer
|
||||
|
||||
@@ -23,6 +40,8 @@ from Model.Network.Graph import Graph
|
||||
|
||||
from View.Network.UndoCommand import *
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
@@ -158,7 +177,7 @@ class EdgeItem(QGraphicsItem):
|
||||
if self.graph.selected_item() == self:
|
||||
color = Qt.red
|
||||
elif self.graph.current_edge() == self:
|
||||
color = Qt.blue
|
||||
color = Qt.black
|
||||
elif not self.graph.graph.is_enable_edge(self.edge):
|
||||
color = Qt.darkGray
|
||||
|
||||
@@ -555,14 +574,17 @@ class GraphWidget(QGraphicsView):
|
||||
Returns:
|
||||
Nothing
|
||||
"""
|
||||
previous_item = self._selected_item
|
||||
self._selected_item = item
|
||||
try:
|
||||
previous_item = self._selected_item
|
||||
self._selected_item = item
|
||||
|
||||
if previous_item:
|
||||
previous_item.update()
|
||||
if previous_item:
|
||||
previous_item.update()
|
||||
|
||||
if item:
|
||||
item.update()
|
||||
if item:
|
||||
item.update()
|
||||
except Exception as e:
|
||||
logger.debug(str(e))
|
||||
|
||||
def selected_new_edge_src_node(self):
|
||||
"""The current node item selected to add new edge
|
||||
@@ -714,6 +736,9 @@ class GraphWidget(QGraphicsView):
|
||||
def mouseReleaseEvent(self, event):
|
||||
self.clicked = False
|
||||
|
||||
if self._only_display:
|
||||
return
|
||||
|
||||
if self._state == "move":
|
||||
if self._current_moved_node is not None:
|
||||
pos = self.mapToScene(event.pos())
|
||||
@@ -819,6 +844,9 @@ class GraphWidget(QGraphicsView):
|
||||
self.reverse_edge(items[0])
|
||||
|
||||
def contextMenuEvent(self, event):
|
||||
if self._only_display:
|
||||
return
|
||||
|
||||
pos = self.mapToScene(event.pos())
|
||||
items = self.items(event.pos())
|
||||
|
||||
|
||||
+46
-23
@@ -1,5 +1,24 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 Model.Network.Node import Node
|
||||
from Model.Network.Edge import Edge
|
||||
from Model.Network.Graph import Graph
|
||||
@@ -137,31 +156,35 @@ class GraphTableModel(QAbstractTableModel):
|
||||
def setData(self, index, value, role=Qt.EditRole):
|
||||
if index.isValid():
|
||||
if role == Qt.EditRole:
|
||||
if (self.headers[index.column()] == "node1" or
|
||||
self.headers[index.column()] == "node2"):
|
||||
node = self.graph.node(value)
|
||||
self._undo.push(
|
||||
SetNodeCommand(
|
||||
self.graph,
|
||||
self.rows[index.row()],
|
||||
self.headers[index.column()],
|
||||
node
|
||||
try:
|
||||
if (self.headers[index.column()] == "node1" or
|
||||
self.headers[index.column()] == "node2"):
|
||||
node = self.graph.node(value)
|
||||
self._undo.push(
|
||||
SetNodeCommand(
|
||||
self.graph,
|
||||
self.rows[index.row()],
|
||||
self.headers[index.column()],
|
||||
node
|
||||
)
|
||||
)
|
||||
)
|
||||
elif self.headers[index.column()] == "enable":
|
||||
self._undo.push(
|
||||
EnableEdgeCommand(
|
||||
self.rows[index.row()], value
|
||||
# elif self.headers[index.column()] == "enable":
|
||||
# self._undo.push(
|
||||
# EnableEdgeCommand(
|
||||
# self.rows[index.row()], value
|
||||
# )
|
||||
# )
|
||||
else:
|
||||
self._undo.push(
|
||||
SetCommand(
|
||||
self.rows[index.row()],
|
||||
self.headers[index.column()],
|
||||
value
|
||||
)
|
||||
)
|
||||
)
|
||||
else:
|
||||
self._undo.push(
|
||||
SetCommand(
|
||||
self.rows[index.row()],
|
||||
self.headers[index.column()],
|
||||
value
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
self.dataChanged.emit(index, index, [Qt.DisplayRole])
|
||||
self.layoutChanged.emit()
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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.QtGui import (
|
||||
@@ -34,7 +50,7 @@ class NetworkWindow(ASubMainWindow):
|
||||
self.setup_title()
|
||||
|
||||
super(NetworkWindow, self).__init__(
|
||||
name=self._title, ui="Network", parent=parent
|
||||
name=title, ui="Network", parent=parent
|
||||
)
|
||||
self.ui.setWindowTitle(self._title)
|
||||
|
||||
@@ -71,7 +87,8 @@ class NetworkWindow(ASubMainWindow):
|
||||
# Edges table
|
||||
|
||||
self._reachs_model = GraphTableModel(
|
||||
headers = ["name", "enable", "node1", "node2"],
|
||||
headers = ["name", # "enable",
|
||||
"node1", "node2"],
|
||||
graph = self._graph,
|
||||
rows_type = "edges",
|
||||
undo = self._undo_stack,
|
||||
@@ -86,9 +103,9 @@ class NetworkWindow(ASubMainWindow):
|
||||
|
||||
table = self.find(QTableView, "tableView_reachs")
|
||||
table.setModel(self._reachs_model)
|
||||
table.setItemDelegateForColumn(1, self.delegate_true_false_combobox)
|
||||
# table.setItemDelegateForColumn(1, self.delegate_true_false_combobox)
|
||||
table.setItemDelegateForColumn(1, self.delegate_combobox)
|
||||
table.setItemDelegateForColumn(2, self.delegate_combobox)
|
||||
table.setItemDelegateForColumn(3, self.delegate_combobox)
|
||||
table.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||
#table.resizeColumnsToContents()
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# APlot.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 -*-
|
||||
|
||||
class APlot(object):
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# MplCanvas.py -- Pamhyr
|
||||
# Copyright (C) 2023 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/>.
|
||||
|
||||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
|
||||
from matplotlib.figure import Figure
|
||||
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# mpl_canvas_onpick_event.py -- Pamhyr
|
||||
# Copyright (C) 2023 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/>.
|
||||
|
||||
import logging
|
||||
|
||||
from time import time
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# navigation_toolbar_2qt.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 os
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
# PlotAC.py -- Pamhyr
|
||||
# Copyright (C) 2023 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.Plot.APlot import APlot
|
||||
|
||||
from PyQt5.QtCore import (
|
||||
QCoreApplication
|
||||
)
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
class PlotAC(APlot):
|
||||
def __init__(self, canvas=None, results=None,
|
||||
reach_id=0, profile_id=0,
|
||||
toolbar=None):
|
||||
super(PlotAC, self).__init__(
|
||||
canvas=canvas,
|
||||
data=results,
|
||||
toolbar=toolbar
|
||||
)
|
||||
|
||||
self._current_timestamp = max(results.get("timestamps"))
|
||||
self._current_reach_id = reach_id
|
||||
self._current_profile_id = profile_id
|
||||
|
||||
@property
|
||||
def results(self):
|
||||
return self.data
|
||||
|
||||
@timer
|
||||
def draw(self, highlight=None):
|
||||
self.canvas.axes.cla()
|
||||
self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
|
||||
|
||||
if self.results is None:
|
||||
return
|
||||
|
||||
self.canvas.axes.set_xlabel(
|
||||
_translate("MainWindow_reach", "X (m)"),
|
||||
color='green', fontsize=11
|
||||
)
|
||||
self.canvas.axes.set_ylabel(
|
||||
_translate("MainWindow_reach", "Elevation (m)"),
|
||||
color='green', fontsize=11
|
||||
)
|
||||
|
||||
reach = self.results.river.reach(self._current_reach_id)
|
||||
profile = reach.profile(self._current_profile_id)
|
||||
x = profile.geometry.get_station()
|
||||
z = profile.geometry.z()
|
||||
|
||||
self.canvas.axes.set_xlim(
|
||||
left = min(x), right = max(x)
|
||||
)
|
||||
|
||||
self.line_kp, = self.canvas.axes.plot(
|
||||
x, z,
|
||||
linestyle="solid",
|
||||
lw=1.8,
|
||||
color='grey',
|
||||
)
|
||||
|
||||
kp = reach.geometry.get_kp()
|
||||
|
||||
# Water elevation
|
||||
water_z = profile.get_ts_key(self._current_timestamp, "Z")
|
||||
|
||||
self.canvas.axes.plot(
|
||||
[min(x), max(x)], [water_z, water_z],
|
||||
lw=1., color='b',
|
||||
)
|
||||
|
||||
x_z = list(map(lambda _: water_z, x))
|
||||
self.canvas.axes.fill_between(
|
||||
x, z, water_z,
|
||||
where=z <= water_z,
|
||||
color='blue', alpha=0.5, interpolate=True
|
||||
)
|
||||
|
||||
self.canvas.figure.tight_layout()
|
||||
self.canvas.figure.canvas.draw_idle()
|
||||
if self.toolbar is not None:
|
||||
self.toolbar.update()
|
||||
|
||||
def set_reach(self, reach_id):
|
||||
self._current_reach_id = reach_id
|
||||
self._current_profile_id = 0
|
||||
self.draw()
|
||||
|
||||
def set_profile(self, profile_id):
|
||||
self._current_profile_id = profile_id
|
||||
self.draw()
|
||||
|
||||
def set_timestamp(self, timestamp):
|
||||
self._current_timestamp = timestamp
|
||||
self.draw()
|
||||
|
||||
def update(self):
|
||||
self.draw()
|
||||
@@ -0,0 +1,131 @@
|
||||
# PlotH.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 functools import reduce
|
||||
|
||||
from tools import timer, trace
|
||||
from View.Plot.APlot import APlot
|
||||
|
||||
from PyQt5.QtCore import (
|
||||
QCoreApplication
|
||||
)
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
class PlotH(APlot):
|
||||
def __init__(self, canvas=None, results=None,
|
||||
reach_id=0, profile_id=0,
|
||||
toolbar=None, display_current=True):
|
||||
super(PlotH, self).__init__(
|
||||
canvas=canvas,
|
||||
data=results,
|
||||
toolbar=toolbar
|
||||
)
|
||||
|
||||
self.display_current = display_current
|
||||
|
||||
self._current_timestamp = max(results.get("timestamps"))
|
||||
self._current_reach_id = reach_id
|
||||
self._current_profile_id = profile_id
|
||||
|
||||
@property
|
||||
def results(self):
|
||||
return self.data
|
||||
|
||||
@timer
|
||||
def draw(self, highlight=None):
|
||||
self.canvas.axes.cla()
|
||||
self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
|
||||
|
||||
if self.results is None:
|
||||
return
|
||||
|
||||
reach = self.results.river.reach(self._current_reach_id)
|
||||
profile = reach.profile(self._current_profile_id)
|
||||
|
||||
if reach.geometry.number_profiles == 0:
|
||||
self._init = False
|
||||
return
|
||||
|
||||
kp_min, kp_max = (-1, -1)
|
||||
if highlight is not None:
|
||||
kp_min, kp_max = highlight
|
||||
|
||||
# Axes
|
||||
self.canvas.axes.set_xlabel(
|
||||
_translate("Results", "Time (s)"),
|
||||
color='green', fontsize=12
|
||||
)
|
||||
self.canvas.axes.set_ylabel(
|
||||
_translate("Results", "Discharge (m³/s)"),
|
||||
color='green', fontsize=12
|
||||
)
|
||||
|
||||
ts = list(self.results.get("timestamps"))
|
||||
ts.sort()
|
||||
|
||||
self.canvas.axes.set_xlim(
|
||||
left = min(ts), right = max(ts)
|
||||
)
|
||||
|
||||
# Draw discharge for each timestamp
|
||||
x = ts
|
||||
y = profile.get_key("Q")
|
||||
|
||||
if len(ts) != len(x):
|
||||
logger.warning(
|
||||
"Results as less Q data ({len(x)}) " +
|
||||
"than timestamps ({len(ts)}) " +
|
||||
"for profile {self._current_profile_id}"
|
||||
)
|
||||
return
|
||||
|
||||
self._line = [
|
||||
self.canvas.axes.plot(
|
||||
x, y, lw=1.,
|
||||
color='r',
|
||||
markersize=3, marker='+'
|
||||
)
|
||||
]
|
||||
|
||||
self.canvas.axes.autoscale_view(True, True, True)
|
||||
self.canvas.axes.autoscale()
|
||||
self.canvas.figure.tight_layout()
|
||||
self.canvas.figure.canvas.draw_idle()
|
||||
if self.toolbar is not None:
|
||||
self.toolbar.update()
|
||||
|
||||
def set_reach(self, reach_id):
|
||||
self._current_reach_id = reach_id
|
||||
self._current_profile_id = 0
|
||||
self.draw()
|
||||
|
||||
def set_profile(self, profile_id):
|
||||
self._current_profile_id = profile_id
|
||||
self.draw()
|
||||
|
||||
def set_timestamp(self, timestamp):
|
||||
self._current_timestamp = timestamp
|
||||
self.draw()
|
||||
|
||||
def update(self):
|
||||
self.draw()
|
||||
@@ -0,0 +1,117 @@
|
||||
# PlotKPC.py -- Pamhyr
|
||||
# Copyright (C) 2023 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.Plot.APlot import APlot
|
||||
|
||||
from PyQt5.QtCore import (
|
||||
QCoreApplication
|
||||
)
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
class PlotKPC(APlot):
|
||||
def __init__(self, canvas=None, results=None,
|
||||
reach_id=0, profile_id=0,
|
||||
toolbar=None):
|
||||
super(PlotKPC, self).__init__(
|
||||
canvas=canvas,
|
||||
data=results,
|
||||
toolbar=toolbar
|
||||
)
|
||||
|
||||
self._current_timestamp = max(results.get("timestamps"))
|
||||
self._current_reach_id = reach_id
|
||||
self._current_profile_id = profile_id
|
||||
|
||||
@property
|
||||
def results(self):
|
||||
return self.data
|
||||
|
||||
@timer
|
||||
def draw(self, highlight=None):
|
||||
self.canvas.axes.cla()
|
||||
self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
|
||||
|
||||
if self.results is None:
|
||||
return
|
||||
|
||||
reach = self.results.river.reach(self._current_reach_id)
|
||||
|
||||
self.canvas.axes.set_ylabel(
|
||||
_translate("MainWindow_reach", "Elevation (m)"),
|
||||
color='green', fontsize=11
|
||||
)
|
||||
self.canvas.axes.set_xlabel(
|
||||
_translate("MainWindow_reach", "KP (m)"),
|
||||
color='green', fontsize=11
|
||||
)
|
||||
|
||||
kp = reach.geometry.get_kp()
|
||||
z_min = reach.geometry.get_z_min()
|
||||
|
||||
self.canvas.axes.set_xlim(
|
||||
left = min(kp), right = max(kp)
|
||||
)
|
||||
|
||||
self.line_kp_zmin = self.canvas.axes.plot(
|
||||
kp, z_min,
|
||||
color='grey', lw=1.
|
||||
)
|
||||
|
||||
if len(reach.geometry.profiles) != 0:
|
||||
kp = reach.geometry.get_kp()
|
||||
|
||||
# Water elevation
|
||||
water_z = list(
|
||||
map(
|
||||
lambda p: p.get_ts_key(self._current_timestamp, "Z"),
|
||||
reach.profiles
|
||||
)
|
||||
)
|
||||
|
||||
self.canvas.axes.plot(
|
||||
kp, water_z, lw=1.,
|
||||
color='b',
|
||||
)
|
||||
|
||||
self.canvas.axes.fill_between(
|
||||
kp, z_min, water_z,
|
||||
color='blue', alpha=0.5, interpolate=True
|
||||
)
|
||||
|
||||
self.canvas.figure.tight_layout()
|
||||
self.canvas.figure.canvas.draw_idle()
|
||||
if self.toolbar is not None:
|
||||
self.toolbar.update()
|
||||
|
||||
def set_reach(self, reach_id):
|
||||
self._current_reach_id = reach_id
|
||||
self._current_profile_id = 0
|
||||
self.draw()
|
||||
|
||||
def set_profile(self, profile_id):
|
||||
self._current_profile_id = profile_id
|
||||
self.draw()
|
||||
|
||||
def set_timestamp(self, timestamp):
|
||||
self._current_timestamp = timestamp
|
||||
self.draw()
|
||||
|
||||
def update(self):
|
||||
self.draw()
|
||||
@@ -0,0 +1,186 @@
|
||||
# PlotXY.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 functools import reduce
|
||||
|
||||
from tools import timer, trace
|
||||
from View.Plot.APlot import APlot
|
||||
|
||||
from PyQt5.QtCore import (
|
||||
QCoreApplication
|
||||
)
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
class PlotXY(APlot):
|
||||
def __init__(self, canvas=None, results=None,
|
||||
reach_id=0, profile_id=0,
|
||||
toolbar=None, display_current=True):
|
||||
super(PlotXY, self).__init__(
|
||||
canvas=canvas,
|
||||
data=results,
|
||||
toolbar=toolbar
|
||||
)
|
||||
|
||||
self.display_current = display_current
|
||||
|
||||
self.line_xy = []
|
||||
self.line_gl = []
|
||||
|
||||
self._current_timestamp = max(results.get("timestamps"))
|
||||
self._current_reach_id = reach_id
|
||||
self._current_profile_id = profile_id
|
||||
|
||||
@property
|
||||
def results(self):
|
||||
return self.data
|
||||
|
||||
@timer
|
||||
def draw(self, highlight=None):
|
||||
self.canvas.axes.cla()
|
||||
self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
|
||||
|
||||
if self.results is None:
|
||||
return
|
||||
|
||||
reach = self.results.river.reach(self._current_reach_id)
|
||||
|
||||
if reach.geometry.number_profiles == 0:
|
||||
self._init = False
|
||||
return
|
||||
|
||||
kp_min, kp_max = (-1, -1)
|
||||
if highlight is not None:
|
||||
kp_min, kp_max = highlight
|
||||
|
||||
# Axes
|
||||
self.canvas.axes.set_xlabel(
|
||||
_translate("Results", "X (m)"),
|
||||
color='green', fontsize=12
|
||||
)
|
||||
self.canvas.axes.set_ylabel(
|
||||
_translate("Results", "Y (m)"),
|
||||
color='green', fontsize=12
|
||||
)
|
||||
self.canvas.axes.axis("equal")
|
||||
|
||||
kp = reach.geometry.get_kp()
|
||||
self.canvas.axes.set_xlim(
|
||||
left = min(kp), right = max(kp)
|
||||
)
|
||||
|
||||
# Draw line for each profile
|
||||
self.line_xy = [
|
||||
self.canvas.axes.plot(
|
||||
x, y, lw=1.,
|
||||
color='b' if kp_min <= kp <= kp_max else 'grey',
|
||||
markersize=3, marker='+'
|
||||
)
|
||||
for x, y, kp in zip(
|
||||
reach.geometry.get_x(),
|
||||
reach.geometry.get_y(),
|
||||
kp
|
||||
)
|
||||
]
|
||||
|
||||
# Guide lines
|
||||
x_complete = reach.geometry.get_guidelines_x()
|
||||
y_complete = reach.geometry.get_guidelines_y()
|
||||
|
||||
self.line_gl = [
|
||||
self.canvas.axes.plot(
|
||||
x, y,
|
||||
)
|
||||
for x, y in zip(x_complete, y_complete)
|
||||
]
|
||||
|
||||
if self.display_current:
|
||||
# Current profile
|
||||
profile = reach.profile(self._current_profile_id).geometry
|
||||
|
||||
self.plot_selected, = self.canvas.axes.plot(
|
||||
profile.x(),
|
||||
profile.y(),
|
||||
lw=1., markersize=3,
|
||||
marker='+', color="b"
|
||||
)
|
||||
self.plot_selected.set_visible(False)
|
||||
|
||||
# Display point under water
|
||||
poly_l_x = []
|
||||
poly_l_y = []
|
||||
poly_r_x = []
|
||||
poly_r_y = []
|
||||
for profile in reach.profiles:
|
||||
water_z = profile.get_ts_key(
|
||||
self._current_timestamp, "Z"
|
||||
)
|
||||
pgeo = profile.geometry
|
||||
|
||||
x, y = reduce(
|
||||
lambda acc, pts: (acc[0] + [pts.x], acc[1] + [pts.y]),
|
||||
filter(
|
||||
lambda pts: pts.z < water_z,
|
||||
pgeo.points
|
||||
),
|
||||
([], [])
|
||||
)
|
||||
|
||||
poly_l_x.append(x[0])
|
||||
poly_l_y.append(y[0])
|
||||
poly_r_x.append(x[-1])
|
||||
poly_r_y.append(y[-1])
|
||||
|
||||
self.canvas.axes.plot(
|
||||
x, y, lw=1.,
|
||||
color='b',
|
||||
markersize=1,
|
||||
marker='o'
|
||||
)
|
||||
|
||||
poly_x = poly_l_x + list(reversed(poly_r_x)) + [poly_l_x[0]]
|
||||
poly_y = poly_l_y + list(reversed(poly_r_y)) + [poly_l_y[0]]
|
||||
|
||||
self.canvas.axes.fill(poly_x, poly_y, color='blue', alpha=1)
|
||||
|
||||
self.canvas.axes.autoscale_view(True, True, True)
|
||||
self.canvas.axes.autoscale()
|
||||
self.canvas.figure.tight_layout()
|
||||
self.canvas.figure.canvas.draw_idle()
|
||||
if self.toolbar is not None:
|
||||
self.toolbar.update()
|
||||
|
||||
def set_reach(self, reach_id):
|
||||
self._current_reach_id = reach_id
|
||||
self._current_profile_id = 0
|
||||
self.draw()
|
||||
|
||||
def set_profile(self, profile_id):
|
||||
self._current_profile_id = profile_id
|
||||
self.draw()
|
||||
|
||||
def set_timestamp(self, timestamp):
|
||||
self._current_timestamp = timestamp
|
||||
self.draw()
|
||||
|
||||
def update(self):
|
||||
self.draw()
|
||||
@@ -0,0 +1,107 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 timer, trace
|
||||
|
||||
from PyQt5.QtGui import (
|
||||
QKeySequence, QColor
|
||||
)
|
||||
from PyQt5.QtCore import (
|
||||
Qt, QAbstractTableModel, QModelIndex,
|
||||
QVariant, pyqtSlot, QCoreApplication,
|
||||
)
|
||||
from PyQt5.QtWidgets import (
|
||||
QMessageBox, QUndoCommand, QUndoStack,
|
||||
QStyledItemDelegate, QLineEdit, QAbstractItemView,
|
||||
QComboBox,
|
||||
)
|
||||
|
||||
from View.Results.translate import *
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class TableModel(QAbstractTableModel):
|
||||
def __init__(self, results = None, study = None, mode = None, undo=None):
|
||||
super(QAbstractTableModel, self).__init__()
|
||||
|
||||
self._results = results
|
||||
self._study = study
|
||||
self._mode = mode
|
||||
self._undo_stack = undo
|
||||
|
||||
self._table_headers = table_headers_reach
|
||||
if mode != "reach":
|
||||
self._table_headers = table_headers_profile
|
||||
|
||||
self._headers = list(self._table_headers.keys())
|
||||
|
||||
self._selected = 0
|
||||
self._timestamp = 0
|
||||
|
||||
def rowCount(self, parent=QModelIndex()):
|
||||
if self._mode == "reach":
|
||||
return len(self._results.river.reachs)
|
||||
|
||||
current_reach = self._results.river.reach(self._selected)
|
||||
return len(current_reach.profiles)
|
||||
|
||||
def columnCount(self, parent=QModelIndex()):
|
||||
return len(self._headers)
|
||||
|
||||
def data(self, index, role=Qt.DisplayRole):
|
||||
if role != Qt.ItemDataRole.DisplayRole:
|
||||
return QVariant()
|
||||
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
if self._mode == "reach":
|
||||
if self._headers[column] == "name":
|
||||
v = self._results.river.reach(row).name
|
||||
return str(v)
|
||||
else:
|
||||
current_reach = self._results.river.reach(self._selected)
|
||||
if self._headers[column] == "name":
|
||||
v = current_reach.profile(row).name
|
||||
return str(v)
|
||||
elif self._headers[column] == "kp":
|
||||
v = current_reach.profile(row).kp
|
||||
return f"{v:.4f}"
|
||||
|
||||
return QVariant()
|
||||
|
||||
def headerData(self, section, orientation, role=Qt.DisplayRole):
|
||||
if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
|
||||
return self._table_headers[self._headers[section]]
|
||||
|
||||
return QVariant()
|
||||
|
||||
def index(self, row, column, parent=QModelIndex()):
|
||||
if not self.hasIndex(row, column, parent):
|
||||
return QModelIndex()
|
||||
|
||||
return self.createIndex(row, column, QModelIndex())
|
||||
|
||||
def flags(self, index):
|
||||
return Qt.ItemIsEnabled | Qt.ItemIsSelectable
|
||||
@@ -0,0 +1,17 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 -*-
|
||||
@@ -0,0 +1,268 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
from View.ASubWindow import ASubMainWindow
|
||||
from View.ListedSubWindow import ListedSubWindow
|
||||
|
||||
from PyQt5.QtGui import (
|
||||
QKeySequence,
|
||||
)
|
||||
|
||||
from PyQt5.QtCore import (
|
||||
Qt, QVariant, QAbstractTableModel,
|
||||
QCoreApplication, QModelIndex, pyqtSlot,
|
||||
)
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialogButtonBox, QPushButton, QLineEdit,
|
||||
QFileDialog, QTableView, QAbstractItemView,
|
||||
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
||||
QSlider,
|
||||
)
|
||||
|
||||
from View.Plot.MplCanvas import MplCanvas
|
||||
|
||||
from View.Results.PlotXY import PlotXY
|
||||
from View.Results.PlotAC import PlotAC
|
||||
from View.Results.PlotKPC import PlotKPC
|
||||
from View.Results.PlotH import PlotH
|
||||
|
||||
from View.Results.Table import TableModel
|
||||
from View.Results.translate import *
|
||||
from View.Stricklers.Window import StricklersWindow
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
class ResultsWindow(ASubMainWindow, ListedSubWindow):
|
||||
def __init__(self, title="Results",
|
||||
study=None, solver=None, results=None,
|
||||
parent=None):
|
||||
self._study = study
|
||||
self._solver = solver
|
||||
self._results = results
|
||||
|
||||
self._timestamps = sorted(list(self._results.get("timestamps")))
|
||||
|
||||
self.setup_title(title)
|
||||
|
||||
super(ResultsWindow, self).__init__(
|
||||
name=title, ui="Results", parent=parent
|
||||
)
|
||||
|
||||
self.setup_sc()
|
||||
self.setup_table()
|
||||
self.setup_graph()
|
||||
self.setup_slider()
|
||||
self.setup_connections()
|
||||
|
||||
self.ui.setWindowTitle(self._title)
|
||||
|
||||
def setup_title(self, title):
|
||||
self._title = (
|
||||
title + " - "
|
||||
+ self._study.name + " - "
|
||||
+ self._solver.name + " - "
|
||||
+ self._results.date
|
||||
)
|
||||
|
||||
def setup_sc(self):
|
||||
self._undo_stack = QUndoStack()
|
||||
|
||||
self.undo_sc = QShortcut(QKeySequence.Undo, self)
|
||||
self.redo_sc = QShortcut(QKeySequence.Redo, self)
|
||||
self.copy_sc = QShortcut(QKeySequence.Copy, self)
|
||||
self.paste_sc = QShortcut(QKeySequence.Paste, self)
|
||||
|
||||
def setup_table(self):
|
||||
self._table = {}
|
||||
|
||||
for t in ["reach", "profile"]:
|
||||
table = self.find(QTableView, f"tableView_{t}")
|
||||
self._table[t] = TableModel(
|
||||
results = self._results,
|
||||
study = self._study,
|
||||
mode = t,
|
||||
undo = self._undo_stack,
|
||||
)
|
||||
table.setModel(self._table[t])
|
||||
|
||||
table.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||
table.setAlternatingRowColors(True)
|
||||
|
||||
def setup_slider(self):
|
||||
self._slider_profile = self.find(QSlider, f"verticalSlider_profile")
|
||||
default_reach = self._results.river.reach(0)
|
||||
self._slider_profile.setMaximum(len(default_reach.profiles) - 1)
|
||||
self._slider_profile.setValue(0)
|
||||
|
||||
self._slider_time = self.find(QSlider, f"horizontalSlider_time")
|
||||
self._slider_time.setMaximum(len(self._timestamps) - 1)
|
||||
self._slider_time.setValue(len(self._timestamps) - 1)
|
||||
|
||||
def setup_graph(self):
|
||||
self.canvas = MplCanvas(width=5, height=4, dpi=100)
|
||||
self.canvas.setObjectName("canvas")
|
||||
self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
|
||||
self.plot_layout.addWidget(self.canvas)
|
||||
|
||||
self.plot_xy = PlotXY(
|
||||
canvas = self.canvas,
|
||||
results = self._results,
|
||||
reach_id = 0,
|
||||
profile_id = 0,
|
||||
toolbar = None,
|
||||
display_current = False
|
||||
)
|
||||
self.plot_xy.draw()
|
||||
|
||||
self.canvas_2 = MplCanvas(width=5, height=4, dpi=100)
|
||||
self.canvas_2.setObjectName("canvas_2")
|
||||
self.plot_layout_2 = self.find(QVBoxLayout, "verticalLayout_2")
|
||||
self.plot_layout_2.addWidget(self.canvas_2)
|
||||
|
||||
self.plot_kpc = PlotKPC(
|
||||
canvas = self.canvas_2,
|
||||
results = self._results,
|
||||
reach_id = 0,
|
||||
profile_id = 0,
|
||||
toolbar = None
|
||||
)
|
||||
self.plot_kpc.draw()
|
||||
|
||||
self.canvas_3 = MplCanvas(width=5, height=4, dpi=100)
|
||||
self.canvas_3.setObjectName("canvas_3")
|
||||
self.plot_layout_3 = self.find(QVBoxLayout, "verticalLayout_3")
|
||||
self.plot_layout_3.addWidget(self.canvas_3)
|
||||
|
||||
self.plot_ac = PlotAC(
|
||||
canvas = self.canvas_3,
|
||||
results = self._results,
|
||||
reach_id = 0,
|
||||
profile_id = 0,
|
||||
toolbar = None
|
||||
)
|
||||
self.plot_ac.draw()
|
||||
|
||||
self.canvas_4 = MplCanvas(width=5, height=4, dpi=100)
|
||||
self.canvas_4.setObjectName("canvas_4")
|
||||
self.plot_layout_4 = self.find(QVBoxLayout, "verticalLayout_hydrograph")
|
||||
self.plot_layout_4.addWidget(self.canvas_4)
|
||||
|
||||
self.plot_h = PlotH(
|
||||
canvas = self.canvas_4,
|
||||
results = self._results,
|
||||
reach_id = 0,
|
||||
profile_id = 0,
|
||||
toolbar = None
|
||||
)
|
||||
self.plot_h.draw()
|
||||
|
||||
def setup_connections(self):
|
||||
self.undo_sc.activated.connect(self.undo)
|
||||
self.redo_sc.activated.connect(self.redo)
|
||||
self.copy_sc.activated.connect(self.copy)
|
||||
self.paste_sc.activated.connect(self.paste)
|
||||
|
||||
fun = {
|
||||
"reach": self._set_current_reach,
|
||||
"profile": self._set_current_profile,
|
||||
}
|
||||
|
||||
for t in ["reach", "profile"]:
|
||||
table = self.find(QTableView, f"tableView_{t}")
|
||||
|
||||
table.selectionModel()\
|
||||
.selectionChanged\
|
||||
.connect(fun[t])
|
||||
|
||||
self._table[t].dataChanged.connect(fun[t])
|
||||
|
||||
self._slider_profile.valueChanged.connect(self._set_current_profile_slider)
|
||||
self._slider_time.valueChanged.connect(self._set_current_timestamp)
|
||||
|
||||
|
||||
def update(self, reach_id = None, profile_id = None, timestamp = None):
|
||||
if reach_id is not None:
|
||||
self.plot_xy.set_reach(reach_id)
|
||||
self.plot_ac.set_reach(reach_id)
|
||||
self.plot_kpc.set_reach(reach_id)
|
||||
self.plot_h.set_reach(reach_id)
|
||||
if profile_id is not None:
|
||||
self.plot_xy.set_profile(profile_id)
|
||||
self.plot_ac.set_profile(profile_id)
|
||||
self.plot_kpc.set_profile(profile_id)
|
||||
self.plot_h.set_profile(profile_id)
|
||||
if timestamp is not None:
|
||||
self.plot_xy.set_timestamp(timestamp)
|
||||
self.plot_ac.set_timestamp(timestamp)
|
||||
self.plot_kpc.set_timestamp(timestamp)
|
||||
self.plot_h.set_timestamp(timestamp)
|
||||
|
||||
self.plot_xy.draw()
|
||||
self.plot_ac.draw()
|
||||
self.plot_kpc.draw()
|
||||
self.plot_h.draw()
|
||||
|
||||
|
||||
def _set_current_reach(self):
|
||||
table = self.find(QTableView, f"tableView_reach")
|
||||
indexes = table.selectedIndexes()
|
||||
if len(indexes) == 0:
|
||||
return
|
||||
|
||||
self.update(reach_id = indexes[0].row())
|
||||
|
||||
def _set_current_profile(self):
|
||||
table = self.find(QTableView, f"tableView_profile")
|
||||
indexes = table.selectedIndexes()
|
||||
if len(indexes) == 0:
|
||||
return
|
||||
|
||||
ind = indexes[0].row()
|
||||
self.update(profile_id = ind)
|
||||
self._slider_profile.setValue(ind)
|
||||
|
||||
def _set_current_profile_slider(self):
|
||||
pid = self._slider_profile.value()
|
||||
self.update(profile_id = pid)
|
||||
|
||||
return
|
||||
|
||||
def _set_current_timestamp(self):
|
||||
timestamp = self._timestamps[self._slider_time.value()]
|
||||
self.update(timestamp = timestamp)
|
||||
|
||||
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()
|
||||
@@ -0,0 +1,30 @@
|
||||
# translate.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
table_headers_reach = {
|
||||
"name": _translate("Results", "Reach name"),
|
||||
}
|
||||
|
||||
table_headers_profile = {
|
||||
"name": _translate("Results", "Name"),
|
||||
"kp": _translate("Results", "KP (m)"),
|
||||
}
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 tempfile
|
||||
|
||||
@@ -1,7 +1,24 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 tempfile
|
||||
import os
|
||||
import logging
|
||||
import tempfile
|
||||
|
||||
from queue import Queue
|
||||
from tools import trace, timer
|
||||
@@ -37,6 +54,8 @@ except:
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
class SelectSolverWindow(ASubWindow, ListedSubWindow):
|
||||
def __init__(self, title="Select solver",
|
||||
study=None, config=None,
|
||||
@@ -94,6 +113,8 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
|
||||
self._config = config
|
||||
self._solver = solver
|
||||
|
||||
self._results = None
|
||||
|
||||
super(SolverLogWindow, self).__init__(
|
||||
name=self._title, ui="SolverLog", parent=parent
|
||||
)
|
||||
@@ -153,6 +174,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
|
||||
self.find(QAction, "action_pause").triggered.connect(self.pause)
|
||||
self.find(QAction, "action_stop").triggered.connect(self.stop)
|
||||
self.find(QAction, "action_log_file").triggered.connect(self.log_file)
|
||||
self.find(QAction, "action_results").triggered.connect(self.results)
|
||||
|
||||
self._alarm.timeout.connect(self.update)
|
||||
|
||||
@@ -177,12 +199,16 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
|
||||
self.find(QAction, "action_start").setEnabled(True)
|
||||
self.find(QAction, "action_pause").setEnabled(False)
|
||||
self.find(QAction, "action_stop").setEnabled(False)
|
||||
self.find(QAction, "action_results").setEnabled(True)
|
||||
if self._solver.log_file() != "":
|
||||
self.find(QAction, "action_log_file").setEnabled(True)
|
||||
|
||||
while self._output.qsize() != 0:
|
||||
s = self._output.get()
|
||||
self._log(s)
|
||||
if type(s) is str and "[ERROR]" in s:
|
||||
self._log(s, color="red")
|
||||
else:
|
||||
self._log(s)
|
||||
|
||||
def start(self):
|
||||
if self._solver.is_stoped():
|
||||
@@ -193,6 +219,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
|
||||
self._process = self.new_process(self._parent)
|
||||
|
||||
self._log(" *** Start", color="blue")
|
||||
self._results = None
|
||||
self._solver.start(self._process)
|
||||
|
||||
self.find(QAction, "action_start").setEnabled(False)
|
||||
@@ -202,6 +229,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
|
||||
self.find(QAction, "action_pause").setEnabled(False)
|
||||
self.find(QAction, "action_stop").setEnabled(True)
|
||||
self.find(QAction, "action_log_file").setEnabled(False)
|
||||
self.find(QAction, "action_results").setEnabled(False)
|
||||
|
||||
def pause(self):
|
||||
self._log(" *** Pause", color="blue")
|
||||
@@ -210,6 +238,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
|
||||
self.find(QAction, "action_start").setEnabled(True)
|
||||
self.find(QAction, "action_pause").setEnabled(False)
|
||||
self.find(QAction, "action_stop").setEnabled(True)
|
||||
self.find(QAction, "action_results").setEnabled(False)
|
||||
|
||||
def stop(self):
|
||||
self._log(" *** Stop", color="blue")
|
||||
@@ -218,9 +247,15 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
|
||||
self.find(QAction, "action_start").setEnabled(True)
|
||||
self.find(QAction, "action_pause").setEnabled(False)
|
||||
self.find(QAction, "action_stop").setEnabled(False)
|
||||
self.find(QAction, "action_results").setEnabled(True)
|
||||
if self._solver.log_file() != "":
|
||||
self.find(QAction, "action_log_file").setEnabled(True)
|
||||
|
||||
def results(self):
|
||||
if self._results is None:
|
||||
self._results = self._solver.results(self._study, self._workdir, qlog = self._output)
|
||||
self._parent.open_solver_results(self._solver, self._results)
|
||||
|
||||
def log_file(self):
|
||||
file_name = os.path.join(self._workdir, self._solver.log_file())
|
||||
log = SolverLogFileWindow(
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 (
|
||||
@@ -81,16 +100,20 @@ class TableModel(QAbstractTableModel):
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
if self._headers[column] == "value":
|
||||
if value in tr.r_yes_no:
|
||||
value = tr.r_yes_no[value].lower()
|
||||
try:
|
||||
if self._headers[column] == "value":
|
||||
if value in tr.r_yes_no:
|
||||
value = tr.r_yes_no[value].lower()
|
||||
|
||||
self._undo.push(
|
||||
SetCommand(
|
||||
self._params, row,
|
||||
"value", value
|
||||
self._undo.push(
|
||||
SetCommand(
|
||||
self._params, row,
|
||||
"value", value
|
||||
)
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -17,7 +33,7 @@ class SetCommand(QUndoCommand):
|
||||
self._index = index
|
||||
self._column = column
|
||||
self._old = self._data.get(self._index)[column]
|
||||
self._new = new_value
|
||||
self._new = str(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._data.get(self._index)[self._column] = self._old
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -40,7 +56,7 @@ class SolverParametersWindow(ASubMainWindow, ListedSubWindow):
|
||||
# Init tanslate dictionary
|
||||
tr.init()
|
||||
|
||||
title = title + " - " + study.name
|
||||
self._title = title + " - " + study.name
|
||||
|
||||
super(SolverParametersWindow, self).__init__(
|
||||
name=title, ui="SolverParameters", parent=parent
|
||||
@@ -53,7 +69,7 @@ class SolverParametersWindow(ASubMainWindow, ListedSubWindow):
|
||||
self.setup_table()
|
||||
self.setup_connections()
|
||||
|
||||
self.ui.setWindowTitle(title)
|
||||
self.ui.setWindowTitle(self._title)
|
||||
|
||||
def setup_sc(self):
|
||||
self._undo_stack = {}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# translate.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# Table.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 (
|
||||
@@ -23,8 +42,9 @@ from View.Stricklers.UndoCommand import (
|
||||
|
||||
from View.Stricklers.translate import *
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
logger = logging.getLogger()
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
class TableModel(QAbstractTableModel):
|
||||
def __init__(self, data=None, undo=None, tab=""):
|
||||
@@ -76,30 +96,34 @@ class TableModel(QAbstractTableModel):
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
||||
if self._headers[column] == "name":
|
||||
self._undo.push(
|
||||
SetNameCommand(
|
||||
self._data, row, value
|
||||
try:
|
||||
if self._headers[column] == "name":
|
||||
self._undo.push(
|
||||
SetNameCommand(
|
||||
self._data, row, value
|
||||
)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "comment":
|
||||
self._undo.push(
|
||||
SetCommentCommand(
|
||||
self._data, row, value
|
||||
elif self._headers[column] == "comment":
|
||||
self._undo.push(
|
||||
SetCommentCommand(
|
||||
self._data, row, value
|
||||
)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "minor":
|
||||
self._undo.push(
|
||||
SetMinorCommand(
|
||||
self._data, row, value
|
||||
elif self._headers[column] == "minor":
|
||||
self._undo.push(
|
||||
SetMinorCommand(
|
||||
self._data, row, value
|
||||
)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "medium":
|
||||
self._undo.push(
|
||||
SetMediumCommand(
|
||||
self._data, row, value
|
||||
elif self._headers[column] == "medium":
|
||||
self._undo.push(
|
||||
SetMediumCommand(
|
||||
self._data, row, value
|
||||
)
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# UndoCommand.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -17,7 +33,7 @@ class SetNameCommand(QUndoCommand):
|
||||
self._data = data
|
||||
self._index = index
|
||||
self._old = self._data.get(self._index).name
|
||||
self._new = new_value
|
||||
self._new = str(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._data.get(self._index).name = self._old
|
||||
@@ -32,7 +48,7 @@ class SetCommentCommand(QUndoCommand):
|
||||
self._data = data
|
||||
self._index = index
|
||||
self._old = self._data.get(self._index).comment
|
||||
self._new = new_value
|
||||
self._new = str(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._data.get(self._index).comment = self._old
|
||||
@@ -47,7 +63,7 @@ class SetMinorCommand(QUndoCommand):
|
||||
self._data = data
|
||||
self._index = index
|
||||
self._old = self._data.get(self._index).minor
|
||||
self._new = new_value
|
||||
self._new = float(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._data.get(self._index).minor = self._old
|
||||
@@ -62,7 +78,7 @@ class SetMediumCommand(QUndoCommand):
|
||||
self._data = data
|
||||
self._index = index
|
||||
self._old = self._data.get(self._index).medium
|
||||
self._new = new_value
|
||||
self._new = float(new_value)
|
||||
|
||||
def undo(self):
|
||||
self._data.get(self._index).medium = self._old
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
@@ -35,7 +51,7 @@ logger = logging.getLogger()
|
||||
|
||||
class StricklersWindow(ASubMainWindow, ListedSubWindow):
|
||||
def __init__(self, title="Stricklers", study=None, config=None, parent=None):
|
||||
title = title + " - " + study.name
|
||||
self._title = title + " - " + study.name
|
||||
|
||||
super(StricklersWindow, self).__init__(
|
||||
name=title, ui="Stricklers", parent=parent
|
||||
@@ -48,7 +64,7 @@ class StricklersWindow(ASubMainWindow, ListedSubWindow):
|
||||
self.setup_table()
|
||||
self.setup_connections()
|
||||
|
||||
self.ui.setWindowTitle(title)
|
||||
self.ui.setWindowTitle(self._title)
|
||||
|
||||
def setup_sc(self):
|
||||
self._undo_stack = QUndoStack()
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# translate.py -- Pamhyr
|
||||
# Copyright (C) 2023 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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Window.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 Model.Study import Study
|
||||
|
||||
+15
-46
@@ -85,17 +85,12 @@
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_menu_open"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_menu_import_mage"/>
|
||||
<addaction name="action_menu_import_rubarbe"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_menu_close"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_menu_edit"/>
|
||||
<addaction name="action_menu_save"/>
|
||||
<addaction name="action_menu_save_as"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_menu_config"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_menu_quit"/>
|
||||
@@ -117,32 +112,8 @@
|
||||
<property name="title">
|
||||
<string>&Geometry</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuCompare">
|
||||
<property name="title">
|
||||
<string>Comparer</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_cross_profile">
|
||||
<property name="title">
|
||||
<string>Profil en travers</string>
|
||||
</property>
|
||||
<addaction name="action_menu_abscisse_cote"/>
|
||||
<addaction name="action_menu_XYZ"/>
|
||||
</widget>
|
||||
<addaction name="menu_cross_profile"/>
|
||||
</widget>
|
||||
<addaction name="action_menu_edit_geometry"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_menu_import_geometry"/>
|
||||
<addaction name="action_menu_export_geometry"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_menu_run_meshing_tool"/>
|
||||
<addaction name="action_menu_view_mesh"/>
|
||||
<addaction name="action_menu_export_mesh"/>
|
||||
<addaction name="action_menu_delete_mesh_for_current_reach"/>
|
||||
<addaction name="action_menu_delete_mesh"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="menuCompare"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_run">
|
||||
<property name="locale">
|
||||
@@ -152,8 +123,8 @@
|
||||
<string>&Execute</string>
|
||||
</property>
|
||||
<addaction name="action_menu_numerical_parameter"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_menu_run_solver"/>
|
||||
<addaction name="action_simulation_directory_management"/>
|
||||
<addaction name="separator"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Hydraulics">
|
||||
@@ -166,14 +137,9 @@
|
||||
<addaction name="action_menu_boundary_conditions"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_menu_initial_conditions"/>
|
||||
<addaction name="action_initia_conditions_export"/>
|
||||
<addaction name="action_import_final_conditions_as_initial"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_menu_edit_friction"/>
|
||||
<addaction name="action_menu_edit_lateral_contribution"/>
|
||||
<addaction name="action_edit_spills"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_edi_cross_building"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_plot">
|
||||
<property name="title">
|
||||
@@ -272,8 +238,6 @@
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_toolBar_network"/>
|
||||
<addaction name="action_toolBar_geometry"/>
|
||||
<addaction name="action_toolBar_mesh"/>
|
||||
<addaction name="action_toolBar_run_meshing_tool"/>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="toolBar_2">
|
||||
<property name="font">
|
||||
@@ -298,12 +262,8 @@
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_toolBar_lateral_contrib"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_toolBar_spills"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_toolBar_frictions"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_toolBar_building"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_toolBar_initial_cond"/>
|
||||
</widget>
|
||||
<action name="action_menu_new">
|
||||
@@ -675,11 +635,17 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_menu_help_pamhyr">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Help PAMHYR</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_menu_help_mage">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Help MAGE</string>
|
||||
</property>
|
||||
@@ -737,10 +703,10 @@
|
||||
<normaloff>ressources/exit_bis.png</normaloff>ressources/exit_bis.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Quit application</string>
|
||||
<string>Quit</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Quitter l'application (Ctrl+Q)</string>
|
||||
<string>Quit the application (Ctrl+Q)</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Q</string>
|
||||
@@ -755,7 +721,7 @@
|
||||
<string>Run solver</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Run solver on current study</string>
|
||||
<string>Run a solver</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_toolBar_kill_solver">
|
||||
@@ -836,7 +802,7 @@
|
||||
<string>Mesh</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Afficher le maillage</string>
|
||||
<string>Display meshed reach</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_toolBar_boundary_cond">
|
||||
@@ -871,7 +837,7 @@
|
||||
<string>Friction</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Edit friction frictions and lateral contributions</string>
|
||||
<string>Edit friction frictions</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_toolBar_stricklers">
|
||||
@@ -916,6 +882,9 @@
|
||||
<property name="text">
|
||||
<string>Initial conditions</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Define initial conditions</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_menu_sediment_layers">
|
||||
<property name="text">
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
<?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>942</width>
|
||||
<height>655</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="English" country="Europe"/>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QSplitter" name="splitter_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QSplitter" name="splitter_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QTableView" name="tableView_reach"/>
|
||||
<widget class="QTableView" name="tableView_profile"/>
|
||||
</widget>
|
||||
<widget class="QWidget" name="">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Geometry</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QSplitter" name="splitter_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</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 class="QWidget" name="verticalLayoutWidget_3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3"/>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Hydrograph</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_hydrograph"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSlider" name="verticalSlider_profile">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="invertedControls">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QSlider" name="horizontalSlider_time">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>942</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -63,6 +63,7 @@
|
||||
<addaction name="action_pause"/>
|
||||
<addaction name="action_stop"/>
|
||||
<addaction name="action_log_file"/>
|
||||
<addaction name="action_results"/>
|
||||
</widget>
|
||||
<action name="action_stop">
|
||||
<property name="icon">
|
||||
@@ -100,6 +101,11 @@
|
||||
<string>LogFile</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_results">
|
||||
<property name="text">
|
||||
<string>results</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
+64
-31
@@ -6,53 +6,86 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>362</width>
|
||||
<height>98</height>
|
||||
<width>553</width>
|
||||
<height>262</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="English" country="Europe"/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<widget class="QLabel" name="label_logo">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap>ressources/logoCemagref.gif</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
<pixmap>ressources/Logo-INRAE.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PamHyr</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Version en developpement:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QLabel" name="label_title">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>About PAMHYR</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_copyright">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_version">
|
||||
<property name="text">
|
||||
<string>Version: @version</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_license">
|
||||
<property name="text">
|
||||
<string>License: GPLv3+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string><a href="https://gitlab.irstea.fr/theophile.terraz/pamhyr">Source code</a></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.4 KiB |
@@ -1,5 +1,21 @@
|
||||
#! /bin/sh
|
||||
|
||||
# ui_to_py.sh -- Pamhyr
|
||||
# Copyright (C) 2023 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/>.
|
||||
|
||||
for ui in $(ls *.ui)
|
||||
do
|
||||
python3 -m PyQt5.uic.pyuic -x $ui -o ${ui%.*}.py
|
||||
|
||||
Reference in new issue
Block a user