Merge branch 'doc-dev' with refactoring and user/dev documentation.

This commit is contained in:
Pierre-Antoine Rouby committed 2023-10-09 11:17:13 +02:00
commit 44b057c522
117 files changed
+3813 -3160

No files matched your search

+14
View File
@@ -98,6 +98,8 @@ build-users-doc:
artifacts:
paths:
- doc/users/documentation.pdf
- doc/users/documentation.html
- doc/users/images/
build-developers-doc:
stage: build
@@ -109,9 +111,19 @@ build-developers-doc:
script:
- cd ./doc/dev/
- ./build.sh
# Create html documentation
- cd ../../src
- pdoc --html .
# Create archive
- tar cf html.tar ./html
- cd ../doc/dev
- mv ../../src/html.tar ./
artifacts:
paths:
- doc/dev/documentation.pdf
- doc/dev/documentation.html
- doc/dev/html.tar
- doc/dev/images/
build-linux:
stage: build
@@ -167,8 +179,10 @@ build-linux:
- cp ../tests_cases/Saar/Saar.pamhyr pamhyr/tests_cases/Saar/
# Copy documentations
- mkdir -p pamhyr/doc/
- mkdir -p pamhyr/doc/html/
- cp ../doc/users/documentation.pdf pamhyr/doc/Pamhyr2-users.pdf
- cp ../doc/dev/documentation.pdf pamhyr/doc/Pamhyr2-dev.pdf
- cp ../doc/dev/documentation.html pamhyr/doc/html/dev.html
# Create running script
- echo "#!/bin/sh" > pamhyr/Pamhyr2
- echo "./pamhyr/pamhyr $@" >> pamhyr/Pamhyr2
+11 -3
View File
@@ -1,10 +1,18 @@
#! /bin/sh
# Build the PDF
emacs -Q -q -nw --batch \
echo " PDF documentation.org"
emacs -nw --batch \
--eval "(require 'org)" \
--eval "(require 'ox-latex)" \
--eval "(load-file \"../tools/setup.el\")" \
--file ./documentation.org \
-f org-latex-export-to-pdf
echo " HTML documentation.org"
emacs -nw --batch \
--eval "(require 'org)" \
--eval "(require 'ox-latex)" \
--eval "(require 'ox-html)" \
--eval "(load-file \"../tools/setup.el\")" \
--file ./documentation.org \
-f org-html-export-to-html
+846 -117
View File
File diff suppressed because it is too large. Load diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

+11 -3
View File
@@ -1,10 +1,18 @@
#! /bin/sh
# Build the PDF
emacs -Q -q -nw --batch \
echo " PDF documentation.org"
emacs -nw --batch \
--eval "(require 'org)" \
--eval "(require 'ox-latex)" \
--eval "(load-file \"../tools/setup.el\")" \
--file ./documentation.org \
-f org-latex-export-to-pdf
echo " HTML documentation.org"
emacs -nw --batch \
--eval "(require 'org)" \
--eval "(require 'ox-latex)" \
--eval "(require 'ox-html)" \
--eval "(load-file \"../tools/setup.el\")" \
--file ./documentation.org \
-f org-html-export-to-html
View File
Whitespace-only changes.
+28 -13
View File
@@ -43,18 +43,21 @@ cd $OLD_PWD
echo " *** COPY DATA"
mkdir -p dist/pamhyr/View/ui
mkdir -p dist/pamhyr/View/ui/Widgets
cp -r ../src/View/ui/ressources/ dist/pamhyr/View/ui/
cp -r ../src/View/ui/Widgets/*.ui dist/pamhyr/View/ui/Widgets/
cp -r ../src/View/ui/*.ui dist/pamhyr/View/ui/
mkdir -p dist/pamhyr/_internal/View/ui
mkdir -p dist/pamhyr/_internal/View/ui/Widgets
cp -r ../src/View/ui/ressources/ dist/pamhyr/_internal/View/ui/
cp -r ../src/View/ui/Widgets/*.ui dist/pamhyr/_internal/View/ui/Widgets/
cp -r ../src/View/ui/*.ui dist/pamhyr/_internal/View/ui/
mkdir -p dist/pamhyr/lang
cp -r ../src/lang/*.qm dist/pamhyr/lang/
cp ../VERSION dist/pamhyr/
cp ../AUTHORS dist/pamhyr/
cp ../LICENSE dist/pamhyr/
mkdir dist/pamhyr/_internal/
#cp ../VERSION dist/pamhyr/_internal/
VERSION=$(cat ../VERSION)
echo "local-build-$VERSION" > dist/pamhyr/_internal/VERSION
cp ../AUTHORS dist/pamhyr/_internal/
cp ../LICENSE dist/pamhyr/_internal/
mkdir -p dist/pamhyr/mage/
cp ../mage/mage dist/pamhyr/mage/
@@ -65,6 +68,18 @@ mkdir -p dist/pamhyr/tests_cases/
mkdir -p dist/pamhyr/tests_cases/Saar
cp ../tests_cases/Saar/Saar.pamhyr dist/pamhyr/tests_cases/Saar/
mkdir -p dist/pamhyr/doc/
cp ../doc/dev/documentation.pdf dist/pamhyr/doc/Pamhyr2-dev.pdf
cp ../doc/dev/documentation.html dist/pamhyr/doc/Pamhyr2-dev.html
cp ../doc/users/documentation.pdf dist/pamhyr/doc/Pamhyr2-users.pdf
cp ../doc/users/documentation.html dist/pamhyr/doc/Pamhyr2-users.html
mkdir -p dist/pamhyr/doc/images
cp ../doc/users/images/* dist/pamhyr/doc/images/
cp ../doc/dev/images/* dist/pamhyr/doc/images/
cp ../doc/images/* dist/pamhyr/doc/images/
echo " *** MAKE SRC PACKAGE"
OLD_PWD=$PWD
@@ -76,11 +91,11 @@ mv ../pamhyr-src.tar.gz ./
echo " *** MAKE BIN PACKAGE"
OLD_PWD=$PWD
cd dist/
tar --xz -cf pamhyr-gnulinux-amd64.tar.xz pamhyr --checkpoint=.100
cd $OLD_PWD
# OLD_PWD=$PWD
# cd dist/
# tar --xz -cf pamhyr-gnulinux-amd64.tar.xz pamhyr --checkpoint=.100
# cd $OLD_PWD
mv dist/pamhyr-gnulinux-amd64.tar.xz ./
# mv dist/pamhyr-gnulinux-amd64.tar.xz ./
echo " *** DONE"
+2 -1
View File
@@ -1,6 +1,7 @@
PyQt5==5.15.4
PyQt5-Qt5==5.15.2
PyQt5-sip==12.8.1
PyQt5-sip==12.12.2
PyQtWebEngine==5.15.6
pyqtgraph>=0.12.1
matplotlib>=3.4.1
numpy>=1.24.2
+3
View File
@@ -56,6 +56,9 @@ class Profile(object):
self._profile_type = _type
def __len__(self):
return len(self._points)
@property
def number_points(self):
return len(self._points)
+4 -1
View File
@@ -42,7 +42,7 @@ class Reach(SQLSubModel):
]
def __init__(self, status=None, parent=None):
self.id = parent.id
self.id = parent.id if parent is not None else 0
self._status = status
self._parent = parent
self._profiles: List[Profile] = []
@@ -106,6 +106,9 @@ class Reach(SQLSubModel):
return self._parent.name
def __len__(self):
return len(self._profiles)
@property
def profiles(self):
return self._profiles.copy()
+4
View File
@@ -43,6 +43,10 @@ class Results(object):
def river(self):
return self._river
@property
def study(self):
return self._study
def set(self, key, value):
self._meta_data[key] = value
+9
View File
@@ -26,6 +26,9 @@ class Profile(object):
self._profile = profile # Source profile in the study
self._data = {} # Dict of dict {<ts>: {<key>: <value>, ...}, ...}
def __len__(self):
return len(self._data)
@property
def name(self):
return self._profile.name
@@ -66,6 +69,9 @@ class Reach(object):
)
)
def __len__(self):
return len(self._profiles)
@property
def name(self):
return self._reach.name
@@ -91,6 +97,9 @@ class River(object):
# Dict with timestamps as key
self._reachs = []
def __len__(self):
return len(self._reachs)
@property
def reachs(self):
return self._reachs.copy()
+1 -1
View File
@@ -1,4 +1,4 @@
# help.py -- Pamhyr
# Hello.py -- Pamhyr
# Copyright (C) 2023 INRAE
#
# This program is free software: you can redistribute it and/or modify
+115
View File
@@ -0,0 +1,115 @@
# P3DST.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
import logging
from matplotlib import pyplot as plt
from numpy import mean
from Scripts.AScript import AScript
from Model.Saved import SavedStatus
from Model.Geometry.Reach import Reach
logger = logging.getLogger()
class Script3DST(AScript):
name = "3DST"
description = "Display a 3D plot of a river reach from ST file"
def usage(self):
logger.info(f"Usage : {self._args[0]} 3DST <INPUT_ST_FILE>")
def set_axes_equal(self, ax):
"""Make axes of 3D plot have equal scale
Make axes of 3D plot have equal scale so that spheres appear
as spheres, cubes as cubes, etc.. This is one possible
solution to Matplotlib's ax.set_aspect('equal') and
ax.axis('equal') not working for 3D.
Args:
ax: a matplotlib axis, e.g., as output from plt.gca()
Returns:
The input axis
"""
x_limits = ax.get_xlim3d()
y_limits = ax.get_ylim3d()
z_limits = ax.get_zlim3d()
x_range = abs(x_limits[1] - x_limits[0])
x_middle = mean(x_limits)
y_range = abs(y_limits[1] - y_limits[0])
y_middle = mean(y_limits)
z_range = abs(z_limits[1] - z_limits[0])
z_middle = mean(z_limits)
# The plot bounding box is a sphere in the sense of the infinity
# norm, hence I call half the max range the plot radius.
plot_radius = 0.5*max([x_range, y_range, z_range])
ax.set_xlim3d([x_middle - plot_radius, x_middle + plot_radius])
ax.set_ylim3d([y_middle - plot_radius, y_middle + plot_radius])
ax.set_zlim3d([z_middle - plot_radius, z_middle + plot_radius])
return ax
def run(self):
try:
st_file = self._args[2]
logger.info(f"Use ST file: {st_file}")
except Exception as e:
logger.error(f"Arguments parcing: {str(e)}")
return 1
try:
status = SavedStatus()
my_reach = Reach(status = status)
my_reach.import_geometry(st_file)
my_reach.compute_guidelines()
ax = plt.figure().add_subplot(projection="3d")
logger.info(my_reach.get_x())
for x, y, z in zip(
my_reach.get_x(),
my_reach.get_y(),
my_reach.get_z()
):
ax.plot(x, y, z, color='r', lw=1.)
for x, y, z in zip(
my_reach.get_guidelines_x(),
my_reach.get_guidelines_y(),
my_reach.get_guidelines_z()
):
ax.plot(x, y, z, color='b', lw=1.)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.tight_layout()
self.set_axes_equal(ax)
plt.show()
return 0
except Exception as e:
logger.error(str(e))
return 1
-68
View File
@@ -1,68 +0,0 @@
# plot_3DST.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 -*-
# a lancer depuis src
import sys
from matplotlib import pyplot as plt
from Model.Geometry.Reach import Reach
from numpy import mean
def set_axes_equal(ax):
'''Make axes of 3D plot have equal scale so that spheres appear as spheres,
cubes as cubes, etc.. This is one possible solution to Matplotlib's
ax.set_aspect('equal') and ax.axis('equal') not working for 3D.
Input
ax: a matplotlib axis, e.g., as output from plt.gca().
'''
x_limits = ax.get_xlim3d()
y_limits = ax.get_ylim3d()
z_limits = ax.get_zlim3d()
x_range = abs(x_limits[1] - x_limits[0])
x_middle = mean(x_limits)
y_range = abs(y_limits[1] - y_limits[0])
y_middle = mean(y_limits)
z_range = abs(z_limits[1] - z_limits[0])
z_middle = mean(z_limits)
# The plot bounding box is a sphere in the sense of the infinity
# norm, hence I call half the max range the plot radius.
plot_radius = 0.5*max([x_range, y_range, z_range])
ax.set_xlim3d([x_middle - plot_radius, x_middle + plot_radius])
ax.set_ylim3d([y_middle - plot_radius, y_middle + plot_radius])
ax.set_zlim3d([z_middle - plot_radius, z_middle + plot_radius])
st_file = sys.argv[1]
my_reach = Reach(None)
my_reach.import_geometry(st_file)
my_reach.compute_guidelines()
ax = plt.figure().add_subplot(projection="3d")
for x, y, z in zip(my_reach.get_x(), my_reach.get_y(), my_reach.get_z()):
ax.plot(x, y, z, color='r', lw=1.)
for x, y, z in zip(my_reach.get_guidelines_x(), my_reach.get_guidelines_y(), my_reach.get_guidelines_z()):
ax.plot(x, y, z, color='b', lw=1.)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.tight_layout()
set_axes_equal(ax)
plt.show()
+3 -3
View File
@@ -24,9 +24,9 @@ from Solver.Mage import Mage7, Mage8
_translate = QCoreApplication.translate
solver_long_name = {
"generic": _translate("Solvers", "Generic"),
# "mage7": _translate("Solvers", "Mage version 7"),
"mage8": _translate("Solvers", "Mage version 8"),
"generic": "Generic",
# "mage7": "Mage v7",
"mage8": "Mage v8",
}
solver_type_list = {
+13 -6
View File
@@ -19,14 +19,17 @@
import os
import logging
from View.ASubWindow import ASubWindow
from View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtCore import QCoreApplication
_translate = QCoreApplication.translate
logger = logging.getLogger()
class AboutWindow(ASubWindow):
class AboutWindow(PamhyrDialog):
_pamhyr_ui = "about"
_pamhyr_name = "About"
def _path_file(self, filename):
return os.path.abspath(
os.path.join(
@@ -35,10 +38,14 @@ class AboutWindow(ASubWindow):
)
)
def __init__(self, title="About", parent=None):
super(AboutWindow, self).__init__(name=title, ui="about", parent=parent)
self.ui.setWindowTitle(title)
def __init__(self, study = None, config = None, parent=None):
super(AboutWindow, self).__init__(
title = _translate("About", "About"),
study = study,
config = config,
options = [],
parent = parent
)
# Version
with open(self._path_file("VERSION"), "r") as f:
+14 -10
View File
@@ -21,27 +21,31 @@ import logging
from datetime import datetime
from tools import timer, trace
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
)
from View.BoundaryCondition.Edit.translate import *
from View.BoundaryCondition.Edit.translate import BCETranslate
_translate = QCoreApplication.translate
logger = logging.getLogger()
class Plot(APlot):
def __init__(self, canvas=None, data=None,
mode = "time", toolbar=None):
class Plot(PamhyrPlot):
def __init__(self, mode = "time", data=None,
trad=None, canvas=None, toolbar=None,
parent=None):
super(Plot, self).__init__(
canvas=canvas,
data=data,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = data,
toolbar = toolbar,
parent = parent
)
self._table_headers = self._trad.get_dict("table_headers")
self._mode = mode
def custom_ticks(self):
@@ -109,10 +113,10 @@ class Plot(APlot):
# Plot label
header = self.data.header
self.canvas.axes.set_xlabel(
table_headers[header[0]], color='black', fontsize=10
self._table_headers[header[0]], color='black', fontsize=10
)
self.canvas.axes.set_ylabel(
table_headers[header[1]], color='black', fontsize=10
self._table_headers[header[1]], color='black', fontsize=10
)
self.canvas.axes.autoscale_view(True, True, True)
-3
View File
@@ -23,8 +23,6 @@ from datetime import date, time, datetime, timedelta
from tools import trace, timer
from View.ASubWindow import ASubMainWindow, AWidget
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrTable import PamhyrTableModel
from PyQt5.QtCore import (
@@ -48,7 +46,6 @@ from View.BoundaryCondition.Edit.UndoCommand import (
SortCommand, MoveCommand, PasteCommand,
DuplicateCommand,
)
from View.BoundaryCondition.Edit.translate import *
_translate = QCoreApplication.translate
+37 -51
View File
@@ -20,8 +20,8 @@ import logging
from tools import timer, trace
from View.ASubWindow import ASubMainWindow, AWidget
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from View.Tools.PamhyrWidget import PamhyrWidget
from View.Tools.PamhyrDelegate import PamhyrExTimeDelegate
from PyQt5.QtGui import (
@@ -41,11 +41,10 @@ from PyQt5.QtWidgets import (
QHeaderView, QDoubleSpinBox, QVBoxLayout,
)
from View.Plot.MplCanvas import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.BoundaryCondition.translate import long_types
from View.BoundaryCondition.Edit.translate import table_headers, retranslate
from View.BoundaryCondition.Edit.translate import BCETranslate
from View.BoundaryCondition.Edit.UndoCommand import SetMetaDataCommand
from View.BoundaryCondition.Edit.Table import TableModel
from View.BoundaryCondition.Edit.Plot import Plot
@@ -54,16 +53,16 @@ _translate = QCoreApplication.translate
logger = logging.getLogger()
class WD50Sigma(AWidget):
class WD50Sigma(PamhyrWidget):
_pamhyr_ui = "d50sigma"
d50Changed = pyqtSignal(float)
sigmaChanged = pyqtSignal(float)
def __init__(self, parent=None):
super(WD50Sigma, self).__init__(
ui="d50sigma",
parent=parent
)
self.parent = parent
self.spinBox_d50 = self.find(QDoubleSpinBox, "doubleSpinBox_d50")
self.spinBox_sigma = self.find(QDoubleSpinBox, "doubleSpinBox_sigma")
@@ -95,46 +94,39 @@ class WD50Sigma(AWidget):
def valueChangedSigma(self, value):
self.sigmaChanged.emit(value)
class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Edit boundary condition",
data=None, study=None, parent=None):
self._data = data
self._study = study
self._title = title
class EditBoundaryConditionWindow(PamhyrWindow):
_pamhyr_ui = "EditBoundaryConditions"
_pamhyr_name = "Edit Boundary Conditions"
self.compute_title()
def __init__(self, data=None, study=None, config=None, parent=None):
self._data = data
trad = BCETranslate()
self._long_types = trad.get_dict("long_types")
name = self._pamhyr_name
if self._data is not None:
node_name = (self._data.node.name if self._data.node is not None
else _translate("BoundaryCondition", "Not associate"))
name = (
_translate("Edit boundary condition", self._pamhyr_name) +
f" - {study.name} " +
f" - {self._data.name} ({self._data.id}) " +
f"({self._long_types[self._data.bctype]} - {node_name})"
)
super(EditBoundaryConditionWindow, self).__init__(
name=self._title, ui="EditBoundaryConditions", parent=parent
title = name,
study = study,
config = config,
trad = trad,
parent = parent
)
self.ui.setWindowTitle(self._title)
self.setup_sc()
self.setup_table()
self.setup_plot()
self.setup_data()
self.setup_connections()
def compute_title(self):
if self._data is not None:
node_name = (self._data.node.name if self._data.node is not None
else _translate("BoundaryCondition", "Not associate"))
self._title = (
_translate("Edit boundary condition", self._title) +
f" - {self._study.name} " +
f" - {self._data.name} ({self._data.id}) " +
f"({long_types[self._data.bctype]} - {node_name})"
)
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_data(self):
self._is_solid = self._data.bctype == "SL"
@@ -147,8 +139,8 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
self._d50sigma.set_sigma(self._data.sigma)
def setup_table(self):
retranslate()
headers = {}
table_headers = self._trad.get_dict("table_headers")
for h in self._data.header:
headers[h] = table_headers[h]
@@ -189,21 +181,16 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
canvas = self.canvas,
data = self._data,
mode = self._study.time_system,
trad = self._trad,
toolbar = self.toolbar,
)
self.plot.draw()
def setup_connections(self):
self.find(QAction, "action_add").triggered.connect(self.add)
self.find(QAction, "action_del").triggered.connect(self.delete)
self.find(QAction, "action_sort").triggered.connect(self.sort)
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)
self._table.dataChanged.connect(self.update)
if self._is_solid:
@@ -252,7 +239,6 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
)
)
def add(self):
rows = self.index_selected_rows()
if len(self._data) == 0 or len(rows) == 0:
@@ -285,7 +271,7 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
self.plot.update()
def copy(self):
def _copy(self):
rows = self.index_selected_rows()
table = []
@@ -297,7 +283,7 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
self.copyTableIntoClipboard(table)
def paste(self):
def _paste(self):
header, data = self.parseClipboardTable()
if len(data) == 0:
@@ -311,12 +297,12 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
self._table.paste(row, header, data)
self.plot.update()
def undo(self):
def _undo(self):
self._table.undo()
self.plot.update()
self.widget_update()
def redo(self):
def _redo(self):
self._table.redo()
self.plot.update()
self.widget_update()
+16 -17
View File
@@ -18,23 +18,22 @@
from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
from View.BoundaryCondition.translate import BCTranslate
_translate = QCoreApplication.translate
table_headers = {
"x": _translate("BoundaryCondition", "X"),
"y": _translate("BoundaryCondition", "Y"),
"time": _translate("BoundaryCondition", "Time"),
"date": _translate("BoundaryCondition", "Date"),
"discharge": _translate("BoundaryCondition", "Discharge (m³/s)"),
"z": _translate("BoundaryCondition", "Z (m)"),
"solid": _translate("BoundaryCondition", "Solid (kg/s)"),
}
class BCETranslate(BCTranslate):
def __init__(self):
super(BCETranslate, self).__init__()
def retranslate():
table_headers["x"] = _translate("BoundaryCondition", "X")
table_headers["y"] = _translate("BoundaryCondition", "Y")
table_headers["time"] = _translate("BoundaryCondition", "Time")
table_headers["date"] = _translate("BoundaryCondition", "Date")
table_headers["discharge"] = _translate("BoundaryCondition", "Discharge (m³/s)")
table_headers["z"] = _translate("BoundaryCondition", "Z (m)")
table_headers["solid"] = _translate("BoundaryCondition", "Solid (kg/s)")
self._sub_dict["table_headers"] = {
"x": _translate("BoundaryCondition", "X"),
"y": _translate("BoundaryCondition", "Y"),
"time": _translate("BoundaryCondition", "Time"),
"date": _translate("BoundaryCondition", "Date"),
"discharge": _translate("BoundaryCondition", "Discharge (m³/s)"),
"z": _translate("BoundaryCondition", "Z (m)"),
"solid": _translate("BoundaryCondition", "Solid (kg/s)"),
}
+17 -5
View File
@@ -46,19 +46,24 @@ from View.BoundaryCondition.UndoCommand import (
AddCommand, DelCommand, SortCommand,
MoveCommand, PasteCommand, DuplicateCommand,
)
from View.BoundaryCondition.translate import *
from View.BoundaryCondition.translate import BC_types
logger = logging.getLogger()
_translate = QCoreApplication.translate
class ComboBoxDelegate(QItemDelegate):
def __init__(self, data=None, mode="type", tab="", parent=None):
def __init__(self, data=None, mode="type", tab="", trad=None, parent=None):
super(ComboBoxDelegate, self).__init__(parent)
self._data = data
self._mode = mode
self._tab = tab
self._trad = trad
self._long_types = {}
if self._trad is not None:
self._long_types = self._trad.get_dict("long_types")
def createEditor(self, parent, option, index):
self.editor = QComboBox(parent)
@@ -66,7 +71,7 @@ class ComboBoxDelegate(QItemDelegate):
if self._mode == "type":
lst = list(
map(
lambda k: long_types[k],
lambda k: self._long_types[k],
filter(
lambda k: self._tab in BC_types[k].compatibility(),
BC_types.keys()
@@ -107,6 +112,13 @@ class ComboBoxDelegate(QItemDelegate):
class TableModel(PamhyrTableModel):
def __init__(self, **kwargs):
super(TableModel, self).__init__(**kwargs)
self._long_types = {}
if self._trad is not None:
self._long_types = self._trad.get_dict("long_types")
def _setup_lst(self):
self._lst = self._data.boundary_condition
self._tab = self._opt_data
@@ -125,7 +137,7 @@ class TableModel(PamhyrTableModel):
return self._lst.get(self._tab, row).name
elif self._headers[column] == "type":
t = self._lst.get(self._tab, row).bctype
return long_types[t]
return self._long_types[t]
elif self._headers[column] == "node":
n = self._lst.get(self._tab, row).node
if n is None:
@@ -149,7 +161,7 @@ class TableModel(PamhyrTableModel):
)
)
elif self._headers[column] == "type":
key = next(k for k, v in long_types.items() if v == value)
key = next(k for k, v in self._long_types.items() if v == value)
self._undo.push(
SetTypeCommand(
self._lst, self._tab,row, BC_types[key]
+21 -28
View File
@@ -20,8 +20,7 @@ import logging
from tools import trace, timer
from View.ASubWindow import ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -56,51 +55,49 @@ from View.BoundaryCondition.Table import (
)
from View.Network.GraphWidget import GraphWidget
from View.BoundaryCondition.translate import table_headers, retranslate
from View.BoundaryCondition.translate import BCTranslate
from View.BoundaryCondition.Edit.Window import EditBoundaryConditionWindow
_translate = QCoreApplication.translate
logger = logging.getLogger()
class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Boundary conditions", study=None, parent=None):
self._title = title + " - " + study.name
class BoundaryConditionWindow(PamhyrWindow):
_pamhyr_ui = "BoundaryConditions"
_pamhyr_name = "Boundary conditions"
def __init__(self, study=None, config=None, parent=None):
name = self._pamhyr_name + " - " + study.name
super(BoundaryConditionWindow, self).__init__(
name=title, ui="BoundaryConditions", parent=parent
title = name,
study = study,
config = config,
trad = BCTranslate(),
parent=parent
)
self._study = study
self._bcs = self._study.river.boundary_condition
self.setup_sc()
self.setup_table()
self.setup_graph()
self.setup_connections()
self.ui.setWindowTitle(self._title)
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):
retranslate()
self._table = {}
for t in ["liquid", "solid", "suspenssion"]:
self._delegate_type = ComboBoxDelegate(
trad = self._trad,
data = self._study.river,
mode = "type",
tab = t,
parent=self
)
self._delegate_node = ComboBoxDelegate(
trad = self._trad,
data = self._study.river,
mode = "node",
tab = t,
@@ -110,12 +107,13 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
table = self.find(QTableView, f"tableView_{t}")
self._table[t] = TableModel(
table_view = table,
table_headers = table_headers,
table_headers = self._trad.get_dict("table_headers"),
editable_headers = ["name", "type", "node"],
delegates = {
"type": self._delegate_type,
"node": self._delegate_node,
},
trad = self._trad,
data = self._study.river,
undo = self._undo_stack,
opt_data = t,
@@ -141,11 +139,6 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
self.find(QAction, "action_edit").triggered.connect(self.edit)
self.find(QAction, "action_sort").triggered.connect(self.sort)
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)
def current_tab(self):
return self.find(QTabWidget, "tabWidget")\
.currentWidget()\
@@ -202,17 +195,17 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
row = self.index_selected_row()
self._table[tab].move_down(row)
def copy(self):
def _copy(self):
logger.info("TODO: copy")
def paste(self):
def _paste(self):
logger.info("TODO: paste")
def undo(self):
def _undo(self):
tab = self.current_tab()
self._table[tab].undo()
def redo(self):
def _redo(self):
tab = self.current_tab()
self._table[tab].redo()
+20 -19
View File
@@ -18,6 +18,8 @@
from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
from Model.BoundaryCondition.BoundaryConditionTypes import (
NotDefined, PonctualContribution,
TimeOverZ, TimeOverDischarge, ZOverDischarge,
@@ -26,21 +28,6 @@ from Model.BoundaryCondition.BoundaryConditionTypes import (
_translate = QCoreApplication.translate
long_types = {
"ND": _translate("BoundaryCondition", "Not defined"),
"PC": _translate("BoundaryCondition", "Ponctual contribution"),
"TZ": _translate("BoundaryCondition", "TimeZ"),
"TD": _translate("BoundaryCondition", "TimeDischarge"),
"ZD": _translate("BoundaryCondition", "ZDischarge"),
"SL": _translate("BoundaryCondition", "Solid"),
}
table_headers = {
"name": _translate("BoundaryCondition", "Name"),
"type": _translate("BoundaryCondition", "Type"),
"node": _translate("BoundaryCondition", "Node")
}
BC_types = {
"ND": NotDefined,
"PC": PonctualContribution,
@@ -50,7 +37,21 @@ BC_types = {
"SL": Solid,
}
def retranslate():
table_headers["name"] = _translate("BoundaryCondition", "Name")
table_headers["type"] = _translate("BoundaryCondition", "Type")
table_headers["node"] = _translate("BoundaryCondition", "Node")
class BCTranslate(PamhyrTranslate):
def __init__(self):
super(BCTranslate, self).__init__()
self._sub_dict["long_types"] = {
"ND": _translate("BoundaryCondition", "Not defined"),
"PC": _translate("BoundaryCondition", "Ponctual contribution"),
"TZ": _translate("BoundaryCondition", "TimeZ"),
"TD": _translate("BoundaryCondition", "TimeDischarge"),
"ZD": _translate("BoundaryCondition", "ZDischarge"),
"SL": _translate("BoundaryCondition", "Solid"),
}
self._sub_dict["table_headers"] = {
"name": _translate("BoundaryCondition", "Name"),
"type": _translate("BoundaryCondition", "Type"),
"node": _translate("BoundaryCondition", "Node")
}
+3 -25
View File
@@ -35,25 +35,12 @@ from PyQt5.QtWidgets import (
QComboBox,
)
from View.Tools.PamhyrTable import PamhyrTableModel
_translate = QCoreApplication.translate
class TableModel(QAbstractTableModel):
def __init__(self, data=None):
super(QAbstractTableModel, self).__init__()
self._headers = ["name", "status"]
self._data = data
def flags(self, index):
options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
return options
def rowCount(self, parent):
return len(self._data)
def columnCount(self, parent):
return len(self._headers)
class TableModel(PamhyrTableModel):
def data(self, index, role):
row = index.row()
column = index.column()
@@ -81,12 +68,3 @@ class TableModel(QAbstractTableModel):
return self._data[row].summary
return QVariant()
def headerData(self, section, orientation, role):
if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
return self._headers[section]
return QVariant()
def update(self):
self.layoutChanged.emit()
+32
View File
@@ -0,0 +1,32 @@
# 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
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate
class CheckListTranslate(PamhyrTranslate):
def __init__(self):
super(CheckListTranslate, self).__init__()
self._sub_dict["table_headers"] = {
"name": _translate("CheckList", "Name"),
"status": _translate("CheckList", "Status"),
}
+18 -20
View File
@@ -18,8 +18,7 @@
from tools import trace, timer
from View.ASubWindow import ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -41,33 +40,36 @@ from PyQt5.QtWidgets import (
from View.CheckList.Table import TableModel
from View.CheckList.Worker import Worker
from View.CheckList.Translate import CheckListTranslate
_translate = QCoreApplication.translate
class CheckListWindow(ASubMainWindow, ListedSubWindow):
class CheckListWindow(PamhyrWindow):
_pamhyr_ui = "CheckList"
_pamhyr_name = "Check list"
signalStatus = pyqtSignal(str)
def __init__(self, title="Check list",
autorun:bool=True,
def __init__(self, autorun:bool=True,
study=None, config=None,
solver=None, parent=None):
self._title = title + " - " + study.name
self._autorun = autorun
self._study = study
self._config = config
self._solver = solver
self._parent = parent
name = self._pamhyr_name + " - " + study.name
super(CheckListWindow, self).__init__(
name=self._title, ui="CheckList", parent=parent
title = name,
study = study,
config = config,
trad = CheckListTranslate(),
options = [],
parent = parent
)
self.ui.setWindowTitle(self._title)
self._checker_list = (
self._study.checkers() + self._solver.checkers()
self._study.checkers() +
self._solver.checkers()
)
self.setup_table()
@@ -78,16 +80,12 @@ class CheckListWindow(ASubMainWindow, ListedSubWindow):
def setup_table(self):
table = self.find(QTableView, f"tableView")
self._table = TableModel(
table_view = table,
table_headers = self._trad.get_dict("table_headers"),
data = self._checker_list,
)
table.setModel(self._table)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
def setup_progress_bar(self):
self._progress = self.find(QProgressBar, f"progressBar")
self._p = 0 # Progress current step
+18 -8
View File
@@ -16,7 +16,7 @@
# -*- coding: utf-8 -*-
from View.ASubWindow import ASubWindow
from View.Tools.PamhyrWindow import PamhyrDialog
from Solver.Solvers import solver_type_list
from Solver.GenericSolver import GenericSolver
@@ -24,12 +24,22 @@ from PyQt5.QtWidgets import (
QPushButton,
)
class ConfigureSolverWindow(ASubWindow):
def __init__(self, data=None, title="Configuration : Add Solver", parent=None):
class ConfigureSolverWindow(PamhyrDialog):
_pamhyr_ui = "ConfigureAddSolverDialog"
_pamhyr_name = "Add/Edit Solver"
def __init__(self, data=None, config=None, parent=None):
if data is not None:
name = f"Edit Solver - {data.name}"
else:
name = "Add a new Solver"
super(ConfigureSolverWindow, self).__init__(
name=title, ui="ConfigureAddSolverDialog", parent=parent
title = name,
config = config,
options = [],
parent=parent
)
self.ui.setWindowTitle(title)
# Combo box item
for solver in solver_type_list:
@@ -37,10 +47,10 @@ class ConfigureSolverWindow(ASubWindow):
# Data to return
self.data = data
if not self.data is None:
if self.data is not None:
self.copy_data()
self.connect()
self.setup_connection()
def copy_data(self):
self.set_combobox_text("comboBox_solver", self.data.type)
@@ -53,7 +63,7 @@ class ConfigureSolverWindow(ASubWindow):
self.set_line_edit_text("lineEdit_output", self.data._path_output)
self.set_line_edit_text("lineEdit_output_cmd", self.data._cmd_output)
def connect(self):
def setup_connection(self):
# File button
buttons = {
"pushButton_input": (lambda: self.file_dialog(
+58 -59
View File
@@ -21,8 +21,7 @@ import logging
from copy import deepcopy
from config import Config
from View.ASubWindow import ASubWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrDialog
from View.Stricklers.Table import TableModel
from View.Stricklers.translate import *
@@ -95,50 +94,42 @@ class SolverTableModel(QAbstractTableModel):
self.layoutChanged.emit()
class ConfigureWindow(ASubWindow, ListedSubWindow):
def __init__(self, conf=None, title="Configure", parent=None):
class ConfigureWindow(PamhyrDialog):
_pamhyr_ui = "ConfigureDialog"
_pamhyr_name = "Configure"
def __init__(self, config=None, parent=None):
if config is None:
config = Config()
super(ConfigureWindow, self).__init__(
name=title, ui="ConfigureDialog", parent=parent
title = self._pamhyr_name,
config = config,
options = [],
parent=parent
)
self.ui.setWindowTitle(title)
if conf is None:
self.conf = Config()
else:
self.conf = conf
self.setup_custom_sc()
self.setup_solver()
self.setup_stricklers()
self.setup_data()
self.setup_connection()
self.setup_sc()
# Solver
def setup_solver(self):
table = self.find(QTableView, "tableView_solver")
self.solver_table_model = SolverTableModel(
headers = ["name", "type", "description"],
rows = conf.solvers
rows = self._config.solvers
)
table.setModel(self.solver_table_model)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
table.resizeColumnsToContents()
# Meshing_Tool
self.set_line_edit_text("lineEdit_meshing_tool", self.conf.meshing_tool)
# Const
self.set_line_edit_text("lineEdit_segment", str(self.conf.segment))
self.set_line_edit_text("lineEdit_max_listing", str(self.conf.max_listing))
# Backup
self.set_check_box("checkBox_backup", self.conf.backup_enable)
self.set_line_edit_text("lineEdit_backup_path", self.conf.backup_path)
self.set_time_edit("timeEdit_backup_frequence", self.conf.backup_frequence)
self.set_spin_box("spinBox_backup_max", self.conf.backup_max)
self.find(QTableView, "tableView_solver").resizeColumnsToContents()
self.connect()
# Stricklers
def setup_stricklers(self):
table = self.find(QTableView, f"tableView_stricklers")
self._stricklers = deepcopy(self.conf.stricklers)
self._stricklers = deepcopy(self._config.stricklers)
self._stricklers_table = TableModel(
data = self._stricklers,
undo = self._undo_stack,
@@ -148,26 +139,35 @@ class ConfigureWindow(ASubWindow, ListedSubWindow):
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
def setup_data(self):
# Meshing_Tool
self.set_line_edit_text("lineEdit_meshing_tool", self._config.meshing_tool)
# Const
self.set_line_edit_text("lineEdit_segment", str(self._config.segment))
self.set_line_edit_text("lineEdit_max_listing", str(self._config.max_listing))
# Backup
self.set_check_box("checkBox_backup", self._config.backup_enable)
self.set_line_edit_text("lineEdit_backup_path", self._config.backup_path)
self.set_time_edit("timeEdit_backup_frequence", self._config.backup_frequence)
self.set_spin_box("spinBox_backup_max", self._config.backup_max)
# Editor
self.set_line_edit_text("lineEdit_editor_cmd", str(self.conf.editor))
self.set_line_edit_text("lineEdit_editor_cmd", str(self._config.editor))
# Language
languages = Config.languages()
for lang in languages:
self.combobox_add_item("comboBox_language", lang)
if self.conf.lang == languages[lang]:
if self._config.lang == languages[lang]:
self.set_combobox_text("comboBox_language", lang)
def setup_sc(self):
self._undo_stack = QUndoStack()
def setup_custom_sc(self):
self._debug_sc = QShortcut(QKeySequence("Ctrl+G"), self)
self._debug_sc.activated.connect(self.set_debug)
self.debug_sc = QShortcut(QKeySequence("Ctrl+G"), self)
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 connect(self):
def setup_connection(self):
buttons = {
# Solvers
"pushButton_solver_add": self.add_solver,
@@ -195,33 +195,31 @@ class ConfigureWindow(ASubWindow, ListedSubWindow):
for button in buttons:
self.find(QPushButton, button).clicked.connect(buttons[button])
self.debug_sc.activated.connect(self.set_debug)
def accept(self):
# Solvers
self.conf.solvers = self.solver_table_model.rows.copy()
self._config.solvers = self.solver_table_model.rows.copy()
# Meshing_Tool
self.conf.meshing_tool = self.get_line_edit_text("lineEdit_meshing_tool")
self._config.meshing_tool = self.get_line_edit_text("lineEdit_meshing_tool")
# Const
self.conf.segment = self.get_line_edit_text("lineEdit_segment")
self.conf.max_listing = self.get_line_edit_text("lineEdit_max_listing")
self._config.segment = self.get_line_edit_text("lineEdit_segment")
self._config.max_listing = self.get_line_edit_text("lineEdit_max_listing")
# Backup
self.conf.backup_enable = self.get_check_box("checkBox_backup")
self.conf.backup_path = self.get_line_edit_text("lineEdit_backup_path")
self.conf.backup_frequence = self.get_time_edit("timeEdit_backup_frequence")
self.conf.backup_max = self.get_spin_box("spinBox_backup_max")
self._config.backup_enable = self.get_check_box("checkBox_backup")
self._config.backup_path = self.get_line_edit_text("lineEdit_backup_path")
self._config.backup_frequence = self.get_time_edit("timeEdit_backup_frequence")
self._config.backup_max = self.get_spin_box("spinBox_backup_max")
# Stricklers
self.conf.stricklers = deepcopy(self._stricklers)
self._config.stricklers = deepcopy(self._stricklers)
# Editor
self.conf.editor = self.get_line_edit_text("lineEdit_editor_cmd")
self._config.editor = self.get_line_edit_text("lineEdit_editor_cmd")
# Language
self.conf.lang = Config.languages()[self.get_combobox_text("comboBox_language")]
self._config.lang = Config.languages()[self.get_combobox_text("comboBox_language")]
self.end()
@@ -230,13 +228,13 @@ class ConfigureWindow(ASubWindow, ListedSubWindow):
self.end()
def end(self):
self.conf.save()
self._config.save()
self.close()
# Debug
def set_debug(self):
self.conf.debug = not self.conf.debug
logger.info(f"Debug mode set : {self.conf.debug}")
self._config.debug = not self._config.debug
logger.info(f"Debug mode set : {self._config.debug}")
self.parent.setup_debug_mode()
# Solvers
@@ -246,6 +244,7 @@ class ConfigureWindow(ASubWindow, ListedSubWindow):
for index in indexes:
self.edit_solver = ConfigureSolverWindow(
data=self.solver_table_model.rows[index.row()],
config=self._config,
parent=self
)
if self.edit_solver.exec_():
+11 -13
View File
@@ -20,8 +20,7 @@ import logging
from tools import trace, timer
from View.ASubWindow import ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -45,20 +44,19 @@ logger = logging.getLogger()
_translate = QCoreApplication.translate
class ReplWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Debug REPL",
study=None, config=None,
class ReplWindow(PamhyrWindow):
_pamhyr_ui = "DebugRepl"
_pamhyr_name = "Debug REPL"
def __init__(self, study=None, config=None,
solver=None, parent=None):
self._title = title
self._study = study
self._config = config
self._parent = parent
super(ReplWindow, self).__init__(
name=self._title, ui="DebugRepl", parent=parent
title = self._pamhyr_name,
study = study,
config = config,
options = [],
parent = parent
)
self.ui.setWindowTitle(self._title)
self.__debug_exec_result__ = None
self._history = []
+97
View File
@@ -0,0 +1,97 @@
# 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
import subprocess
from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5.QtCore import QCoreApplication
_translate = QCoreApplication.translate
logger = logging.getLogger()
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QAction
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings
class DocWindow(PamhyrWindow):
_pamhyr_ui = "WebView"
_pamhyr_name = "Doc"
def _path_file(self, filename):
return os.path.abspath(
os.path.join(
os.path.dirname(__file__),
"..", "..", "..", "doc", filename
)
)
def __init__(self, filename=None,
study=None, config=None,
parent=None):
super(DocWindow, self).__init__(
title = self._pamhyr_name,
study = study,
config = config,
options = [],
parent = parent
)
self._path = self._path_file(filename)
self.setup_web_engine()
self.setup_url(self._path)
self.setup_connection()
def setup_connection(self):
self.findChild(QAction, "action_back").triggered.connect(self.back)
self.findChild(QAction, "action_forward").triggered.connect(self.forward)
self.findChild(QAction, "action_firefox").triggered.connect(self.open_in_firefox)
def setup_web_engine(self):
vl = self.find(QVBoxLayout, "verticalLayout")
self._web_view = QWebEngineView()
settings = self._web_view.settings()
settings.setAttribute(QWebEngineSettings.PluginsEnabled, True)
settings.setAttribute(QWebEngineSettings.JavascriptEnabled, True)
settings.setAttribute(QWebEngineSettings.PdfViewerEnabled, True)
vl.addWidget(self._web_view)
def setup_url(self, filename):
logger.info(f"Open documentation : {filename}")
self._web_view.setUrl(QUrl(f"file://{self._path_file(filename)}"))
def back(self):
self._web_view.back()
def forward(self):
self._web_view.forward()
def open_in_firefox(self):
_ = subprocess.Popen(
f"firefox {self._path}",
shell = True
)
+10 -5
View File
@@ -16,9 +16,14 @@
# -*- coding: utf-8 -*-
from View.ASubWindow import ASubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
class DummyWindow(ASubWindow):
def __init__(self, title="Dummy", parent=None):
super(DummyWindow, self).__init__(name=title, ui="dummy", parent=parent)
self.ui.setWindowTitle(title)
class DummyWindow(PamhyrWindow):
__ui = "Dummy"
__name = "Pamhyr Dummy Window"
def __init__(self, parent=None):
super(DummyWindow, self).__init__(
title = self.__name,
parent = parent,
)
+2 -9
View File
@@ -17,7 +17,7 @@
# -*- coding: utf-8 -*-
from tools import timer, flatten
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
@@ -25,14 +25,7 @@ from PyQt5.QtCore import (
_translate = QCoreApplication.translate
class PlotStricklers(APlot):
def __init__(self, canvas=None, data=None, toolbar=None):
super(PlotStricklers, self).__init__(
canvas=canvas,
data=data,
toolbar=toolbar
)
class PlotStricklers(PamhyrPlot):
def draw_frictions(self, frictions, color="r"):
lst = frictions
lst.sort(key = lambda s: s.begin_kp)
+22 -42
View File
@@ -41,6 +41,8 @@ from View.Frictions.UndoCommand import (
MoveCommand, PasteCommand, DuplicateCommand,
)
from View.Tools.PamhyrTable import PamhyrTableModel
from View.Frictions.translate import *
logger = logging.getLogger()
@@ -93,26 +95,10 @@ class ComboBoxDelegate(QItemDelegate):
self.commitData.emit(self.sender())
class TableModel(QAbstractTableModel):
def __init__(self, data=None, study=None, undo=None):
super(QAbstractTableModel, self).__init__()
self._headers = list(table_headers.keys())
self._data = data
self._study = study
self._undo = undo
self._frictions = self._data.frictions
def flags(self, index):
options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
options |= Qt.ItemIsEditable
return options
def rowCount(self, parent):
return len(self._frictions)
def columnCount(self, parent):
return len(self._headers)
class TableModel(PamhyrTableModel):
def _setup_lst(self):
self._lst = self._data.frictions
self._study = self._opt_data
def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole:
@@ -122,30 +108,24 @@ class TableModel(QAbstractTableModel):
column = index.column()
if self._headers[column] == "name":
return self._frictions.get(row).name
return self._lst.get(row).name
elif self._headers[column] == "begin_kp":
return self._frictions.get(row).begin_kp
return self._lst.get(row).begin_kp
elif self._headers[column] == "end_kp":
return self._frictions.get(row).end_kp
return self._lst.get(row).end_kp
elif self._headers[column] == "begin_strickler":
value = self._frictions.get(row).begin_strickler
value = self._lst.get(row).begin_strickler
if value == None:
return _translate("Frictions", "Not defined")
return str(value)
elif self._headers[column] == "end_strickler":
value = self._frictions.get(row).end_strickler
value = self._lst.get(row).end_strickler
if value == None:
return _translate("Frictions", "Not defined")
return str(value)
return QVariant()
def headerData(self, friction, orientation, role):
if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
return table_headers[self._headers[friction]]
return QVariant()
def setData(self, index, value, role=Qt.EditRole):
if not index.isValid() or role != Qt.EditRole:
return False
@@ -157,31 +137,31 @@ class TableModel(QAbstractTableModel):
if self._headers[column] == "name":
self._undo.push(
SetNameCommand(
self._frictions, row, value
self._lst, row, value
)
)
elif self._headers[column] == "begin_kp":
self._undo.push(
SetBeginCommand(
self._frictions, row, value
self._lst, row, value
)
)
elif self._headers[column] == "end_kp":
self._undo.push(
SetEndCommand(
self._frictions, row, value
self._lst, row, value
)
)
elif self._headers[column] == "begin_strickler":
self._undo.push(
SetBeginStricklerCommand(
self._frictions, row, self._study.river.strickler(value)
self._lst, row, self._study.river.strickler(value)
)
)
elif self._headers[column] == "end_strickler":
self._undo.push(
SetEndStricklerCommand(
self._frictions, row, self._study.river.strickler(value)
self._lst, row, self._study.river.strickler(value)
)
)
except Exception as e:
@@ -196,7 +176,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
AddCommand(
self._frictions, row, self._data
self._lst, row, self._data
)
)
@@ -208,7 +188,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
DelCommand(
self._frictions, rows
self._lst, rows
)
)
@@ -220,7 +200,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
SortCommand(
self._frictions, False
self._lst, False
)
)
@@ -237,7 +217,7 @@ class TableModel(QAbstractTableModel):
self._undo_stack.push(
MoveCommand(
self._frictions, "up", row
self._lst, "up", row
)
)
@@ -245,7 +225,7 @@ class TableModel(QAbstractTableModel):
self.layoutChanged.emit()
def move_down(self, index, parent=QModelIndex()):
if row > len(self._frictions):
if row > len(self._lst):
return
target = row
@@ -254,7 +234,7 @@ class TableModel(QAbstractTableModel):
self._undo_stack.push(
MoveCommand(
self._frictions, "down", row
self._lst, "down", row
)
)
+45 -55
View File
@@ -20,8 +20,7 @@ import logging
from tools import trace, timer
from View.ASubWindow import ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -48,63 +47,49 @@ from View.Frictions.Table import (
TableModel, ComboBoxDelegate
)
from View.Plot.MplCanvas import MplCanvas
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Geometry.PlotKPZ import PlotKPZ
from View.Frictions.PlotStricklers import PlotStricklers
from View.Frictions.translate import table_headers, retranslate
from View.Frictions.translate import FrictionsTranslate
from View.Stricklers.Window import StricklersWindow
_translate = QCoreApplication.translate
logger = logging.getLogger()
class FrictionsWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Frictions", study=None, parent=None):
self._study = study
self._reach = self._study.river.current_reach()
class FrictionsWindow(PamhyrWindow):
_pamhyr_ui = "Frictions"
_pamhyr_name = "Edit frictions"
def __init__(self, reach=None, study=None, config=None, parent=None):
if reach is not None:
self._reach = reach
else:
self._reach = study.river.current_reach()
self._frictions = self._reach.frictions
self.setup_title(title)
super(FrictionsWindow, self).__init__(
name=title, ui="Frictions", parent=parent
name = (
self._pamhyr_name + " - "
+ study.name + " - "
+ self._reach.name
)
super(FrictionsWindow, self).__init__(
title = name,
study = study,
config = config,
trad = FrictionsTranslate(),
parent = parent
)
self.setup_sc()
self.setup_table()
self.setup_graph()
self.setup_connections()
self.ui.setWindowTitle(self._title)
def setup_title(self, title):
self._title = (
title + " - "
+ self._study.name + " - "
+ self._reach.name
)
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):
retranslate()
self._table = {}
table = self.find(QTableView, f"tableView")
self._table = TableModel(
data = self._reach,
study = self._study,
undo = self._undo_stack,
)
table.setModel(self._table)
self._delegate_stricklers = ComboBoxDelegate(
data = self._reach,
study = self._study,
@@ -112,13 +97,23 @@ class FrictionsWindow(ASubMainWindow, ListedSubWindow):
parent=self
)
table.setItemDelegateForColumn(
3, self._delegate_stricklers
table = self.find(QTableView, f"tableView")
self._table = TableModel(
table_view = table,
table_headers = self._trad.get_dict("table_headers"),
editable_headers = [
"name", "begin_kp", "end_kp",
"begin_strickler", "end_strickler"
],
delegates = {
"begin_strickler": self._delegate_stricklers,
"end_strickler": self._delegate_stricklers,
},
data = self._reach,
undo = self._undo_stack,
opt_data = self._study
)
table.setItemDelegateForColumn(
4, self._delegate_stricklers
)
table.setModel(self._table)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
@@ -156,11 +151,6 @@ class FrictionsWindow(ASubMainWindow, ListedSubWindow):
self.find(QAction, "action_sort").triggered.connect(self.sort)
self.find(QAction, "action_edit_stricklers").triggered.connect(self.edit_stricklers)
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)
table = self.find(QTableView, f"tableView")
table.selectionModel()\
.selectionChanged\
@@ -234,16 +224,16 @@ class FrictionsWindow(ASubMainWindow, ListedSubWindow):
row = self.index_selected_row()
self._table.move_down(row)
def copy(self):
def _copy(self):
logger.info("TODO: copy")
def paste(self):
def _paste(self):
logger.info("TODO: paste")
def undo(self):
def _undo(self):
self._table.undo()
def redo(self):
def _redo(self):
self._table.redo()
def edit_stricklers(self):
+13 -15
View File
@@ -18,21 +18,19 @@
from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate
table_headers = {
"name": _translate("Frictions", "Name"),
# "edge": _translate("Frictions", "Reach"),
"begin_kp": _translate("Frictions", "Begin kp (m)"),
"end_kp": _translate("Frictions", "End kp (m)"),
"begin_strickler": _translate("Frictions", "Begin strickler"),
"end_strickler": _translate("Frictions", "End strickler"),
}
class FrictionsTranslate(PamhyrTranslate):
def __init__(self):
super(FrictionsTranslate, self).__init__()
def retranslate():
table_headers["name"] = _translate("Frictions", "Name")
# table_headers["edge"] = _translate("Frictions", "Reach")
table_headers["begin_kp"] = _translate("Frictions", "Begin kp (m)")
table_headers["end_kp"] = _translate("Frictions", "End kp (m)")
table_headers["begin_strickler"] = _translate("Frictions", "Begin strickler")
table_headers["end_strickler"] = _translate("Frictions", "End strickler")
self._sub_dict["table_headers"] = {
"name": _translate("Frictions", "Name"),
# "edge": _translate("Frictions", "Reach"),
"begin_kp": _translate("Frictions", "Begin kp (m)"),
"end_kp": _translate("Frictions", "End kp (m)"),
"begin_strickler": _translate("Frictions", "Begin strickler"),
"end_strickler": _translate("Frictions", "End strickler"),
}
+9 -6
View File
@@ -19,7 +19,7 @@
import logging
from tools import timer
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
@@ -29,12 +29,15 @@ _translate = QCoreApplication.translate
logger = logging.getLogger()
class PlotAC(APlot):
def __init__(self, canvas=None, data=None, toolbar=None, plot_xy=None):
class PlotAC(PamhyrPlot):
def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
plot_xy=None, parent=None):
super(PlotAC, self).__init__(
canvas=canvas,
data=data,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = data,
toolbar = toolbar,
parent = parent
)
self.plot_xy = plot_xy
+9 -7
View File
@@ -19,7 +19,7 @@
import logging
from tools import timer
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
@@ -29,13 +29,15 @@ _translate = QCoreApplication.translate
logger = logging.getLogger()
class PlotKPZ(APlot):
def __init__(self, canvas=None, data=None, toolbar=None,
display_current=True):
class PlotKPZ(PamhyrPlot):
def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
display_current=True, parent=None):
super(PlotKPZ, self).__init__(
canvas=canvas,
data=data,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = data,
toolbar = toolbar,
parent = parent
)
self.display_current = display_current
+11 -8
View File
@@ -17,7 +17,7 @@
# -*- coding: utf-8 -*-
from tools import timer, trace
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
@@ -25,12 +25,15 @@ from PyQt5.QtCore import (
_translate = QCoreApplication.translate
class PlotXY(APlot):
def __init__(self, canvas=None, data=None, toolbar=None, display_current=True):
class PlotXY(PamhyrPlot):
def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
display_current=True, parent=None):
super(PlotXY, self).__init__(
canvas=canvas,
data=data,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = data,
toolbar = toolbar,
parent = parent
)
self.display_current = display_current
@@ -60,11 +63,11 @@ class PlotXY(APlot):
# Axes
self.canvas.axes.set_xlabel(
_translate("MainWindow_reach", "X (m)"),
_translate("Geometry", "X (m)"),
color='green', fontsize=12
)
self.canvas.axes.set_ylabel(
_translate("MainWindow_reach", "Y (m)"),
_translate("Geometry", "Y (m)"),
color='green', fontsize=12
)
self.canvas.axes.axis("equal")
+10 -7
View File
@@ -19,8 +19,8 @@
import logging
from tools import timer, trace
from View.Plot.APlot import APlot
from View.Plot.mpl_canvas_onpick_event import OnpickEvent
from View.Tools.PamhyrPlot import PamhyrPlot
from View.Tools.Plot.OnPickEvent import OnpickEvent
from PyQt5.QtCore import (
QCoreApplication
@@ -30,12 +30,15 @@ _translate = QCoreApplication.translate
logger = logging.getLogger()
class Plot(APlot):
def __init__(self, canvas=None, data=None, toolbar=None, table=None):
class Plot(PamhyrPlot):
def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
table=None, parent=None):
super(Plot, self).__init__(
canvas=canvas,
data=data,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = data,
toolbar = toolbar,
parent = parent
)
self._table = table
+46 -104
View File
@@ -29,10 +29,11 @@ from PyQt5.QtWidgets import (
QMessageBox, QStyledItemDelegate, QLineEdit
)
from PyQt5.QtCore import (
QModelIndex, Qt, QAbstractTableModel,
QVariant, QCoreApplication
QModelIndex, Qt, QVariant, QCoreApplication
)
from View.Tools.PamhyrTable import PamhyrTableModel
from Model.Geometry.PointXYZ import PointXYZ
from Model.Geometry.ProfileXYZ import ProfileXYZ
@@ -43,43 +44,22 @@ logger = logging.getLogger()
_translate = QCoreApplication.translate
class TableEditableModel(QAbstractTableModel):
def __init__(self, profile: ProfileXYZ, header=None, undo=None):
QAbstractTableModel.__init__(self)
self._undo_stack = undo
self._profile = profile
if header is None:
self._header = [
"X (m)", "Y (m)", "Z (m)",
_translate("MainWindowProfile", "Nom"),
_translate("MainWindowProfile", "Abs en travers (m)")
]
else:
self._header = header
def rowCount(self, parent=QModelIndex()):
return self._profile.number_points
def columnCount(self, parent=QModelIndex()):
return len(self._header)
class GeometryProfileTableModel(PamhyrTableModel):
def data(self, index, role=Qt.DisplayRole):
if index.isValid():
if role == Qt.DisplayRole:
value = ""
if index.column() == 0:
value = self._profile.point(index.row()).x
value = self._data.point(index.row()).x
elif index.column() == 1:
value = self._profile.point(index.row()).y
value = self._data.point(index.row()).y
elif index.column() == 2:
value = self._profile.point(index.row()).z
value = self._data.point(index.row()).z
elif index.column() == 3:
value = self._profile.point(index.row()).name
value = self._data.point(index.row()).name
elif index.column() == 4:
station = self._profile.get_station()
station = self._data.get_station()
if station is None:
return "-"
else:
@@ -95,25 +75,25 @@ class TableEditableModel(QAbstractTableModel):
return Qt.AlignHCenter | Qt.AlignVCenter
if index.column() == 2:
value = self._profile.point(index.row()).z
value = self._data.point(index.row()).z
if role == Qt.ForegroundRole:
if value == self._profile.z_min():
if value == self._data.z_min():
return QColor("red")
elif value == self._profile.z_max():
elif value == self._data.z_max():
return QColor("blue")
if role == Qt.ToolTipRole:
if value == self._profile.z_min():
if value == self._data.z_min():
return _translate("MainWindowProfile",
"La cote du fond",
"Z minimale")
elif value == self._profile.z_max():
elif value == self._data.z_max():
return _translate("MainWindowProfile",
"La cote maximale",
"Z maximale")
if index.column() == 3:
value = self._profile.point(index.row()).name
value = self._data.point(index.row()).name
if value.strip().upper() in ["RG", "RD"]:
if role == Qt.FontRole:
@@ -132,21 +112,6 @@ class TableEditableModel(QAbstractTableModel):
return QVariant()
def headerData(self, section, orientation, role=Qt.DisplayRole):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self._header[section]
elif orientation == Qt.Vertical and role == Qt.DisplayRole:
return str(section + 1)
if role == Qt.ToolTipRole and section == 4:
return _translate(
"MainWindowProfile",
"Abscisse en travers calculée en projétant les points"
" \nsur le plan défini par les deux points nommés extrêmes "
)
return QVariant()
def setData(self, index, value, role=Qt.EditRole):
row = index.row()
column = index.column()
@@ -154,34 +119,34 @@ class TableEditableModel(QAbstractTableModel):
if role == Qt.EditRole:
try:
if column == 0:
self._undo_stack.push(
self._undo.push(
SetXCommand(
self._profile, row,
self._profile.point(row).x,
self._data, row,
self._data.point(row).x,
value
)
)
elif column == 1:
self._undo_stack.push(
self._undo.push(
SetYCommand(
self._profile, row,
self._profile.point(row).y,
self._data, row,
self._data.point(row).y,
value
)
)
elif column == 2:
self._undo_stack.push(
self._undo.push(
SetZCommand(
self._profile, row,
self._profile.point(row).z,
self._data, row,
self._data.point(row).z,
value
)
)
elif column == 3:
self._undo_stack.push(
self._undo.push(
SetNameCommand(
self._profile, row,
self._profile.point(row).name,
self._data, row,
self._data.point(row).name,
value
)
)
@@ -213,9 +178,9 @@ class TableEditableModel(QAbstractTableModel):
def insert_row(self, row, parent=QModelIndex()):
self.beginInsertRows(parent, row, row - 1)
self._undo_stack.push(
self._undo.push(
AddCommand(
self._profile, row
self._data, row
)
)
@@ -225,9 +190,9 @@ class TableEditableModel(QAbstractTableModel):
def remove_rows(self, rows, parent=QModelIndex()):
self.beginRemoveRows(parent, rows[0], rows[-1])
self._undo_stack.push(
self._undo.push(
DelCommand(
self._profile, rows
self._data, rows
)
)
@@ -239,15 +204,15 @@ class TableEditableModel(QAbstractTableModel):
reverse = (order != Qt.AscendingOrder)
self._undo_stack.push(
self._undo.push(
SortCommand(
self._profile, column, reverse
self._data, column, reverse
)
)
self.layoutChanged.emit()
def move_row_up(self, row, parent=QModelIndex()):
def move_up(self, row, parent=QModelIndex()):
if row <= 0:
return
@@ -255,26 +220,26 @@ class TableEditableModel(QAbstractTableModel):
self.beginMoveRows(parent, row - 1, row - 1, parent, target)
self._undo_stack.push(
self._undo.push(
MoveCommand(
self._profile, "up", row
self._data, "up", row
)
)
self.endMoveRows()
self.layoutChanged.emit()
def move_row_down(self, row_to_move, parent=QModelIndex()):
if row > self._profile.number_points:
def move_down(self, row_to_move, parent=QModelIndex()):
if row > self._data.number_points:
return
target = row
self.beginMoveRows(parent, row + 1, row + 1, parent, target)
self._undo_stack.push(
self._undo.push(
MoveCommand(
self._profile, "down", row
self._data, "down", row
)
)
@@ -282,7 +247,7 @@ class TableEditableModel(QAbstractTableModel):
self.layoutChanged.emit()
def paste(self, row, header, data):
if row > self._profile.number_points:
if row > self._data.number_points:
return
if len(data) == 0:
@@ -290,12 +255,12 @@ class TableEditableModel(QAbstractTableModel):
self.layoutAboutToBeChanged.emit()
self._undo_stack.push(
self._undo.push(
PasteCommand(
self._profile, row,
self._data, row,
list(
map(
lambda d: self._profile.point_from_data(header, d),
lambda d: self._data.point_from_data(header, d),
data
)
)
@@ -306,32 +271,9 @@ class TableEditableModel(QAbstractTableModel):
self.layoutChanged.emit()
def undo(self):
self._undo_stack.undo()
self._undo.undo()
self.layoutChanged.emit()
def redo(self):
self._undo_stack.redo()
self._undo.redo()
self.layoutChanged.emit()
class Delegate(QStyledItemDelegate):
def __init__(self, parent=None, setModelDataEvent=None):
super(Delegate, self).__init__(parent)
self.setModelDataEvent = setModelDataEvent
def createEditor(self, parent, option, index):
index.model().data(index, Qt.DisplayRole)
return QLineEdit(parent)
def setEditorData(self, editor, index):
value = index.model().data(index, Qt.DisplayRole)
editor.setText(str(value))
def setModelData(self, editor, model, index):
model.setData(index, editor.text())
if not self.setModelDataEvent is None:
self.setModelDataEvent()
def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
+36
View File
@@ -0,0 +1,36 @@
# 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
from View.Tools.PamhyrTranslate import PamhyrTranslate
from View.Geometry.Translate import GeometryTranslate
_translate = QCoreApplication.translate
class GeometryProfileTranslate(GeometryTranslate):
def __init__(self):
super(GeometryProfileTranslate, self).__init__()
self._sub_dict["table_headers"] = {
"x": _translate("Geometry", "X (m)"),
"y": _translate("Geometry", "Y (m)"),
"z": _translate("Geometry", "Z (m)"),
"name": _translate("Geometry", "Name"),
"abs": _translate("Geometry", "Traversal abs (m)"),
}
+95 -235
View File
@@ -31,205 +31,188 @@ from PyQt5.QtCore import (
)
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QFileDialog, QCheckBox,
QUndoStack, QShortcut,
QUndoStack, QShortcut, QTableView, QAbstractItemView,
QHeaderView, QVBoxLayout, QAction,
)
from Model.Geometry.Reach import Reach
from Model.Geometry.ProfileXYZ import ProfileXYZ
from View.ASubWindow import ASubMainWindow
from View.Geometry.Profile.mainwindow_ui_profile import Ui_MainWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Geometry.Profile.Plot import Plot
from View.Geometry.Profile.Table import *
from View.Geometry.Profile.Table import GeometryProfileTableModel
from View.Geometry.Profile.Translate import GeometryProfileTranslate
_translate = QCoreApplication.translate
class ProfileWindow(ASubMainWindow):
def __init__(self, profile=None, title="Profile", parent=None):
self._title = title
self.parent = parent
super(ProfileWindow, self).__init__(
name=self._title,
parent=self.parent
)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
class ProfileWindow(PamhyrWindow):
_pamhyr_ui = "GeometryCrossSection"
_pamhyr_name = "Geometry cross-section"
def __init__(self, profile=None, study=None, config=None, parent=None):
self._profile = profile
self._model = None
self.setup_window()
self.setup_sc()
self.setup_model()
self.setup_connections()
self.plot()
self._model.dataChanged.connect(self.update_plot)
self.fileName = None
# self.ui.tableView.installEventFilter(self)
# self._model.dataChanged.connect(self.tableview_is_modified)
# self.ui.btn_go_back.setEnabled(False)
# self.ui.btn_check.setEnabled(False)
# self._model.dataChanged.connect(self.set_enable_cancel_btn)
# self._model.dataChanged.connect(self.set_enable_validate_changes_btn)
# self.ui.btn_reset.setEnabled(False)
# self._model.dataChanged.connect(self.set_enable_go_back_initial_state_btn)
def setup_window(self):
header = _translate("MainWindowProfile", "Profile")
name = self._profile.name
if (name is None) or (name == ""):
name = _translate("MainWindowProfile", "(no name)")
self._title = (
header + " - " +
f"{self._profile.reach.name}" + " - " +
f"{name} ({self._profile.kp})"
name = f"{self._pamhyr_name} - {self._profile.name} {self._profile.kp}"
super(ProfileWindow, self).__init__(
title = name,
study = study,
config = config,
trad = GeometryProfileTranslate(),
parent = parent
)
self.setWindowTitle(self._title)
self.setup_table()
self.setup_plot()
self.setup_connections()
def setup_sc(self):
self._undo_stack = QUndoStack()
def setup_table(self):
table_headers = self._trad.get_dict("table_headers")
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_model(self):
self._model = TableEditableModel(
profile = self._profile,
table = self.find(QTableView, "tableView")
self._tablemodel = GeometryProfileTableModel(
table_view = table,
table_headers = table_headers,
editable_headers = ["name", "x", "y", "z"],
data = self._profile,
undo = self._undo_stack
)
table.setModel(self._tablemodel)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
self.ui.tableView.setModel(self._model)
self.ui.tableView.setItemDelegate(Delegate())
def setup_plot(self):
self._tablemodel.blockSignals(True)
def setup_connections(self):
self.ui.btn_sort_asc_x.triggered.connect(self.sort_X_ascending)
self.ui.btn_sort_desc_x.triggered.connect(self.sort_X_descending)
self.ui.btn_sort_asc_y.triggered.connect(self.sort_Y_ascending)
self.ui.btn_sort_desc_y.triggered.connect(self.sort_Y_descending)
self.ui.btn_move_up.triggered.connect(self.move_row_up)
self.ui.btn_move_down.triggered.connect(self.move_row_down)
self.ui.btn_export.triggered.connect(self.handleSave)
self.ui.btn_add.triggered.connect(self.insert_row)
self.ui.btn_delete.triggered.connect(self.delete_row)
# self.ui.btn_copy.clicked.connect(self.copyTable)
# self.ui.btn_paste.clicked.connect(self.pasteTable)
# self.ui.btn_check.clicked.connect(self.validate_changes)
# self.ui.btn_go_back.clicked.connect(self.cancel_validate_changes)
# self.ui.btn_reset.clicked.connect(self.go_back_to_initial_state)
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)
def plot(self):
self.ui.tableView.model().blockSignals(True)
self._canvas = MplCanvas(width=3, height=4, dpi=100)
self._canvas.setObjectName("canvas")
self._toolbar = PamhyrPlotToolbar(
self._canvas, self,
items = ["home", "zoom", "save", "iso", "back/forward", "move"]
)
self._plot_layout = self.find(QVBoxLayout, "verticalLayout")
self._plot_layout.addWidget(self._toolbar)
self._plot_layout.addWidget(self._canvas)
self._plot = Plot(
canvas = self.ui.canvas,
canvas = self._canvas,
data = self._profile,
toolbar = None,
table = self.ui.tableView,
toolbar = self._toolbar,
table = self.find(QTableView, "tableView")
)
self._plot.draw()
self.ui.tableView.model().blockSignals(False)
self._tablemodel.blockSignals(False)
def setup_connections(self):
actions = {
"action_sort_asc": self.sort_X_ascending,
"action_sort_des": self.sort_X_descending,
"action_up": self.move_up,
"action_down": self.move_down,
"action_add": self.add,
"action_delete": self.delete,
}
for action in actions:
self.find(QAction, action)\
.triggered.connect(actions[action])
self._tablemodel.dataChanged.connect(self.update_plot)
def update_plot(self):
self.ui.tableView.model().blockSignals(True)
self._tablemodel.blockSignals(True)
# TODO: Do not rebuild all graph
self._plot.update()
self.ui.tableView.model().blockSignals(False)
self._tablemodel.blockSignals(False)
def index_selected_row(self):
rows = self.ui.tableView\
rows = self._tablemodel\
.selectionModel()\
.selectedRows()
if len(rows) == 0:
return 0
return self.ui.tableView\
return self._tablemodel\
.selectionModel()\
.selectedRows()[0]\
.row()
def insert_row(self):
if len(self.ui.tableView.selectedIndexes()) == 0:
self._model.insert_row(self._model.rowCount())
def add(self):
table = self.find(QTableView, "tableView")
if len(table.selectedIndexes()) == 0:
self._tablemodel.insert_row(self._tablemodel.rowCount())
else:
row = self.index_selected_row()
self._model.insert_row(row + 1)
self._tablemodel.insert_row(row + 1)
self.update_plot()
def delete_row(self):
def delete(self):
table = self.find(QTableView, "tableView")
rows = sorted(
list(
set(
[index.row() for index in self.ui.tableView.selectedIndexes()]
[index.row() for index in table.selectedIndexes()]
)
)
)
if len(rows) > 0:
self._model.remove_rows(rows)
self._tablemodel.remove_rows(rows)
self.update_plot()
def sort_X_ascending(self):
self._model.sort('x', order=Qt.AscendingOrder)
self._tablemodel.sort('x', order=Qt.AscendingOrder)
self.update_plot()
def sort_X_descending(self):
self._model.sort('x', order=Qt.DescendingOrder)
self._tablemodel.sort('x', order=Qt.DescendingOrder)
self.update_plot()
def sort_Y_ascending(self):
self._model.sort('y', order=Qt.AscendingOrder)
self._tablemodel.sort('y', order=Qt.AscendingOrder)
self.update_plot()
def sort_Y_descending(self):
self._model.sort('y', order=Qt.DescendingOrder)
self._tablemodel.sort('y', order=Qt.DescendingOrder)
self.update_plot()
def move_row_down(self):
def move_down(self):
rows = list(
set(
[index.row() for index in self.ui.tableView.selectedIndexes()]
[index.row() for index in
self.find(QTableView, "tableView").selectedIndexes()]
)
)
for row in rows:
if row < self._model.rowCount() - 1:
self._model.move_row_down(row)
if row < self._tablemodel.rowCount() - 1:
self._tablemodel.move_down(row)
self.update_plot()
def move_row_up(self):
def move_up(self):
rows = list(
set(
[index.row() for index in self.ui.tableView.selectedIndexes()]
[index.row() for index in
self.find(QTableView, "tableView").selectedIndexes()]
)
)
for row in rows:
if 0 < row:
self._model.move_row_up(row)
self._tablemodel.move_up(row)
self.update_plot()
def copy(self):
rows = self.ui.tableView\
rows = self._tablemodel\
.selectionModel()\
.selectedRows()
table = []
@@ -257,136 +240,13 @@ class ProfileWindow(ASubMainWindow):
row.append(self._profile)
row = self.index_selected_row()
self._model.paste(row, header, data)
self._tablemodel.paste(row, header, data)
self.update_plot()
def undo(self):
self._model.undo()
self._tablemodel.undo()
self.update_plot()
def redo(self):
self._model.redo()
self._tablemodel.redo()
self.update_plot()
def handleSave(self):
if self.fileName is None or self.fileName == '':
self.fileName, self.filters = QFileDialog.getSaveFileName(
self, filter="CSV files (*.csv)"
)
if self.fileName != '':
with open(self.fileName, 'w') as stream:
csvout = csv.writer(stream, delimiter='\t', quotechar=' ',
escapechar=None,
quoting=csv.QUOTE_NONNUMERIC,
lineterminator='\n')
for row in range(self._model.rowCount(QModelIndex())):
rowdata = []
for column in range(self._model.columnCount(QModelIndex())):
item = self._model.index(
row, column, QModelIndex()
).data(Qt.DisplayRole)
if item is not None:
rowdata.append(item)
if item == 'nan':
rowdata.remove(item)
csvout.writerow(rowdata)
def handleOpen(self):
self.fileName, self.filterName = QFileDialog.getOpenFileName(self)
if self.fileName != '':
with open(self.fileName, 'r') as f:
reader = csv.reader(f, delimiter='\t')
header = next(reader)
buf = []
for row in reader:
row[0] = QCheckBox("-")
buf.append(row)
self._model = None
self._model = TableEditableModel(buf)
self.ui.tableView.setModel(self._model)
self.fileName = ''
def set_enable_validate_changes_btn(self):
self.ui.btn_check.setEnabled(True)
def set_enable_cancel_btn(self):
self.ui.btn_go_back.setEnabled(True)
def set_enable_go_back_initial_state_btn(self):
self.ui.btn_reset.setEnabled(True)
def delete_empty_rows(self):
if self._model.data_contains_nan():
buttonReply = QtWidgets.QMessageBox.question(
self,
_translate("MainWindowProfile",
"Suppression les lignes incomplètes"),
_translate("MainWindowProfile",
"Supprimer les lignes des cellules"
" non renseignées ?"),
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No
)
if buttonReply == QtWidgets.QMessageBox.Yes:
self._model.delete_empty_rows()
if buttonReply == QtWidgets.QMessageBox.No:
pass
def remove_duplicates_point_names(self):
counter_list = []
list_deleted_names = []
for ind, name_point in enumerate(self._model.name):
if name_point not in counter_list:
counter_list.append(name_point)
elif len(name_point.strip()) > 0 and name_point in counter_list:
if name_point not in list_deleted_names:
list_deleted_names.append(name_point)
if list_deleted_names:
self.msg_box_check_duplication_names(list_deleted_names)
def msg_box_check_duplication_names(self, list_deleted_names):
if len(list_deleted_names) == 1:
text = _translate("MainWindowProfile",
"Le nom ''{}'' est dupliqué."
" \n\nYes : Ne garder que la première occurrence. \nNo :"
" Annuler la suppression.".format(list_deleted_names[0]))
else:
text = _translate("MainWindowProfile",
"Les noms suivants : \n{} sont dupliqués"
" \n\nYes : Ne garder que la première occurrence de "
"chaque nom. \nNo :"
" Annuler la suppression.".format(list_deleted_names))
buttonReply = QtWidgets.QMessageBox.question(
self, _translate("MainWindowProfile",
"Suppression des noms répétés"),
text,
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No
)
if buttonReply == QtWidgets.QMessageBox.Yes:
self._model.remove_duplicates_names()
def ask_quit(self):
choice = QtWidgets.QMessageBox.question(
self,
_translate("MainWindowProfile", "Quittez ?"),
_translate("MainWindowProfile",
"Etes-vous sûr de vouloir quitter ?"),
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No
)
return choice == QtWidgets.QMessageBox.Yes
def initial_state_model(self, profile_initial_state):
return profile_initial_state
@@ -1,260 +0,0 @@
# 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
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtWidgets import (
QTableView, QAbstractItemView, QHeaderView,
QToolBar,
)
from View.Plot import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar
file_path = os.path.abspath(os.path.dirname(__file__))
icon_path = f"{os.path.dirname(os.path.dirname(file_path))}/../View/ui/ressources/"
class Ui_MainWindow(object):
def setupUi(self, MainWindowProfile):
MainWindowProfile.setObjectName("MainWindowProfile")
MainWindowProfile.resize(1089, 699)
self.centralwidget = QtWidgets.QWidget(MainWindowProfile)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.splitter = QtWidgets.QSplitter(self.centralwidget)
self.splitter.setOrientation(Qt.Horizontal)
self.splitter.setObjectName("splitter")
self.widget = QtWidgets.QWidget(self.splitter)
self.widget.setObjectName("widget")
self.verticalLayout_left = QtWidgets.QVBoxLayout(self.widget)
self.verticalLayout_left.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_left.setObjectName("verticalLayout_left")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.toolBar = QToolBar(MainWindowProfile)
self.toolBar.setOrientation(Qt.Vertical)
self.toolBar.setEnabled(True)
MainWindowProfile.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
btn_size = QSize(40, 28)
self.btn_add = QtWidgets.QAction(self.widget)
self.btn_add.setObjectName("btn_add")
icon_btn_add = QtGui.QIcon()
icon_btn_add.addPixmap(
QtGui.QPixmap(f"{icon_path}gtk-add.png"))
self.btn_add.setIcon(icon_btn_add)
self.toolBar.addAction(self.btn_add)
self.btn_delete = QtWidgets.QAction(self.widget)
self.btn_delete.setObjectName("btn_delete")
icon_btn_delete = QtGui.QIcon()
icon_btn_delete.addPixmap(
QtGui.QPixmap(f"{icon_path}gtk-remove.png"))
self.btn_delete.setIcon(icon_btn_delete)
self.toolBar.addAction(self.btn_delete)
self.btn_sort_asc_x = QtWidgets.QAction(self.widget)
self.btn_sort_asc_x.setObjectName("btn_sort_asc_x")
icon_btn_sort_asc_x = QtGui.QIcon()
icon_btn_sort_asc_x.addPixmap(
QtGui.QPixmap(f"{icon_path}gtk-sort-ascending.png"))
self.btn_sort_asc_x.setIcon(icon_btn_sort_asc_x)
self.toolBar.addAction(self.btn_sort_asc_x)
self.btn_sort_desc_x = QtWidgets.QAction(self.widget)
self.btn_sort_desc_x.setObjectName("btn_sort_desc_x")
icon_btn_sort_desc_x = QtGui.QIcon()
icon_btn_sort_desc_x.addPixmap(
QtGui.QPixmap(f"{icon_path}gtk-sort-descending.png"))
self.btn_sort_desc_x.setIcon(icon_btn_sort_desc_x)
self.toolBar.addAction(self.btn_sort_desc_x)
self.btn_sort_asc_y = QtWidgets.QAction(self.widget)
self.btn_sort_asc_y.setObjectName("btn_sort_asc_y")
icon_btn_sort_asc_y = QtGui.QIcon()
icon_btn_sort_asc_y.addPixmap(
QtGui.QPixmap(f"{icon_path}gtk-sort-ascending.png"))
self.btn_sort_asc_y.setIcon(icon_btn_sort_asc_y)
self.toolBar.addAction(self.btn_sort_asc_y)
self.btn_sort_desc_y = QtWidgets.QAction(self.widget)
self.btn_sort_desc_y.setObjectName("btn_sort_desc_y")
icon_btn_sort_desc_y = QtGui.QIcon()
icon_btn_sort_desc_y.addPixmap(
QtGui.QPixmap(f"{icon_path}gtk-sort-descending.png"))
self.btn_sort_desc_y.setIcon(icon_btn_sort_desc_y)
self.toolBar.addAction(self.btn_sort_desc_y)
self.btn_move_up = QtWidgets.QAction(self.widget)
self.btn_move_up.setObjectName("btn_move_up")
icon_btn_move_up = QtGui.QIcon()
icon_btn_move_up.addPixmap(
QtGui.QPixmap(f"{icon_path}up.png"))
self.btn_move_up.setIcon(icon_btn_move_up)
self.toolBar.addAction(self.btn_move_up)
self.btn_move_down = QtWidgets.QAction(self.widget)
self.btn_move_down.setObjectName("btn_move_down")
icon_btn_move_down = QtGui.QIcon()
icon_btn_move_down.addPixmap(
QtGui.QPixmap(f"{icon_path}down.png"))
self.btn_move_down.setIcon(icon_btn_move_down)
self.toolBar.addAction(self.btn_move_down)
self.btn_export = QtWidgets.QAction(self.widget)
self.btn_export.setObjectName("btn_export")
icon_btn_export = QtGui.QIcon()
icon_btn_export.addPixmap(
QtGui.QPixmap(f"{icon_path}export.png"))
self.btn_export.setIcon(icon_btn_export)
self.toolBar.addAction(self.btn_export)
self.btn_copy = QtWidgets.QAction(self.widget)
self.btn_copy.setObjectName("btn_copy")
icon_btn_copy = QtGui.QIcon()
icon_btn_copy.addPixmap(
QtGui.QPixmap(f"{icon_path}gtk-copy.png"))
self.btn_copy.setIcon(icon_btn_copy)
self.toolBar.addAction(self.btn_copy)
self.btn_paste = QtWidgets.QAction(self.widget)
self.btn_paste.setObjectName("btn_paste")
icon_btn_paste = QtGui.QIcon()
icon_btn_paste.addPixmap(
QtGui.QPixmap(f"{icon_path}gtk-paste.png"))
self.btn_paste.setIcon(icon_btn_paste)
self.toolBar.addAction(self.btn_paste)
self.btn_check = QtWidgets.QAction(self.widget)
self.btn_check.setObjectName("btn_check")
icon_btn_check = QtGui.QIcon()
icon_btn_check.addPixmap(
QtGui.QPixmap(f"{icon_path}gtk-apply.png"))
self.btn_check.setIcon(icon_btn_check)
self.toolBar.addAction(self.btn_check)
self.btn_go_back = QtWidgets.QAction(self.widget)
self.btn_go_back.setObjectName("btn_go_back")
icon_btn_go_back = QtGui.QIcon()
icon_btn_go_back.addPixmap(
QtGui.QPixmap(f"{icon_path}gtk-undo.png"))
self.btn_go_back.setIcon(icon_btn_go_back)
self.toolBar.addAction(self.btn_go_back)
self.btn_reset = QtWidgets.QAction(self.widget)
self.btn_reset.setObjectName("btn_reset")
icon_btn_reset = QtGui.QIcon()
icon_btn_reset.addPixmap(
QtGui.QPixmap(f"{icon_path}cancel.png"))
self.btn_reset.setIcon(icon_btn_reset)
self.toolBar.addAction(self.btn_reset)
self.verticalLayout_left.addLayout(self.horizontalLayout)
self.tableView = QTableView(self.widget)
self.tableView.setObjectName("tableView")
self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
self.tableView.resizeColumnsToContents()
self.tableView.resizeRowsToContents()
self.tableView.setAlternatingRowColors(True)
self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.verticalLayout_left.addWidget(self.tableView)
self.widget1 = QtWidgets.QWidget(self.splitter)
self.widget1.setObjectName("widget1")
self.verticalLayout_right = QtWidgets.QVBoxLayout(self.widget1)
self.verticalLayout_right.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_right.setObjectName("verticalLayout_right")
self.label_graphic_help = QtWidgets.QLabel(self.widget1)
self.label_graphic_help.setMaximumSize(QtCore.QSize(16777215, 25))
self.label_graphic_help.setBaseSize(QtCore.QSize(0, 30))
self.label_graphic_help.setObjectName("label_graphic_help")
self.verticalLayout_right.addWidget(self.label_graphic_help)
self.canvas = MplCanvas.MplCanvas(width=5, height=4, dpi=100)
self.canvas.setObjectName("canvas")
self.my_toolbar = PamhyrPlotToolbar(
self.canvas, self.widget1
)
self.verticalLayout_right.addWidget(self.my_toolbar)
self.verticalLayout_right.addWidget(self.canvas)
self.horizontalLayout_2.addWidget(self.splitter)
MainWindowProfile.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindowProfile)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1089, 20))
self.menubar.setObjectName("menubar")
MainWindowProfile.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindowProfile)
self.statusbar.setObjectName("statusbar")
MainWindowProfile.setStatusBar(self.statusbar)
self.retranslateUi(MainWindowProfile)
QtCore.QMetaObject.connectSlotsByName(MainWindowProfile)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindowProfile", "MainWindowProfile"))
self.btn_add.setToolTip(_translate("MainWindowProfile", "Insérer un point"))
self.btn_delete.setToolTip(
_translate("MainWindowProfile", "Supprimer le/les point(s) sélectionnés"))
self.btn_sort_asc_x.setToolTip(
_translate("MainWindowProfile", "Trier les points par ordre croissant de X"))
self.btn_sort_desc_x.setToolTip(
_translate("MainWindowProfile", "Trier les points par ordre décroissant de X"))
self.btn_sort_asc_y.setToolTip(_translate("MainWindowProfile",
"Trier les points par ordre croissant de Y"
))
self.btn_sort_desc_y.setToolTip(_translate("MainWindowProfile",
"Trier les points par ordre décroissant de Y"))
self.btn_move_up.setToolTip(_translate("MainWindowProfile",
"Décaler le point sélectionné vers le haut"))
self.btn_move_down.setToolTip(_translate("MainWindowProfile",
"Décaler le point sélectionné vers le bas"))
self.btn_export.setToolTip(_translate("MainWindowProfile",
"Exporter (dans un fichier) les points du profil au format tabulé"))
self.btn_copy.setToolTip(
_translate("MainWindowProfile", "Copier la sélection au format tabulé"))
self.btn_paste.setToolTip(_translate("MainWindowProfile",
"Coller la sélection depuis le presse-papier au format tabulé"))
self.btn_check.setToolTip(_translate("MainWindowProfile",
"Vérifier la validité de la saisie et garder ou pas les modifications "
"apportées"))
self.btn_go_back.setToolTip(_translate("MainWindowProfile",
"Annuler toutes les modifications depuis la dernière validation"))
self.btn_reset.setToolTip(_translate("MainWindowProfile",
"Annuler toutes les modifications et revenir à l\'état initial"))
self.label_graphic_help.setToolTip(_translate("MainWindowProfile",
"Ligne d'eau : \n \tZ : Cote (m) \n \tA : Aire mouillée ("
"m\u00B2) \n \tp : "
"Périmètre mouillé (m) \n \tL : Largeur au miroir (m)"))
self.label_graphic_help.setText(
_translate("MainWindowProfile", "\'Maj + Clic\' : Ligne d\'eau & \'Ctrl + Clic\' : "
"Sélectionner des points"))
+33 -150
View File
@@ -35,6 +35,8 @@ from PyQt5.QtWidgets import (
QComboBox,
)
from View.Tools.PamhyrTable import PamhyrTableModel
from Model.Geometry import Reach
from Model.Geometry.ProfileXYZ import ProfileXYZ
from View.Geometry.UndoCommand import *
@@ -44,53 +46,26 @@ logger = logging.getLogger()
_translate = QCoreApplication.translate
class TableEditableModel(QAbstractTableModel):
def __init__(self, reach, headers=None, undo=None):
QAbstractTableModel.__init__(self)
data_list = []
self._undo_stack = undo
self._reach = reach
# Hack for qtlinguist
_ = _translate("Geometry", "Name")
_ = _translate("Geometry", "Kp (m)")
_ = _translate("Geometry", "Type")
if headers is None:
self.headers = [
"Name",
"Kp (m)",
"Type"
]
else:
self.headers = headers
def rowCount(self, parent=QModelIndex()):
return self._reach.number_profiles
def columnCount(self, parent=QModelIndex()):
return len(self.headers)
class GeometryReachTableModel(PamhyrTableModel):
def data(self, index, role=Qt.DisplayRole):
if not index.isValid():
return QVariant()
if role == Qt.DisplayRole and index.column() == 0:
return self._reach.profile(index.row()).name
return self._data.profile(index.row()).name
if role == Qt.DisplayRole and index.column() == 1:
kp = self._reach.profile(index.row()).kp
kp = self._data.profile(index.row()).kp
return f"{kp:.4f}"
if role == Qt.DisplayRole and index.column() == 2:
return self._reach.profile(index.row()).profile_type
return self._data.profile(index.row()).profile_type
if role == Qt.TextAlignmentRole:
return Qt.AlignHCenter | Qt.AlignVCenter
if role == Qt.ForegroundRole and index.column() == 0:
name = self._reach.profile(index.row()).name\
name = self._data.profile(index.row()).name\
.strip()\
.lower()
if (name == "upstream" or name == "up" or
@@ -102,16 +77,6 @@ class TableEditableModel(QAbstractTableModel):
return QVariant()
def headerData(self, section, orientation, role=Qt.DisplayRole):
if role == Qt.DisplayRole:
if orientation == Qt.Horizontal:
if section < len(self.headers):
return _translate("Geometry", self.headers[section])
else:
return str(section + 1)
return QVariant()
def setData(self, index, value, role=Qt.EditRole):
row = index.row()
column = index.column()
@@ -119,19 +84,19 @@ class TableEditableModel(QAbstractTableModel):
if role == Qt.EditRole and index.column() != 2:
try:
if index.column() == 0:
self._undo_stack.push(
self._undo.push(
SetNameCommand(
self._reach, index.row(),
self._reach.profile(index.row()).name,
self._data, index.row(),
self._data.profile(index.row()).name,
value
)
)
if index.column() == 1:
self._undo_stack.push(
self._undo.push(
SetKPCommand(
self._reach, index.row(),
self._reach.profile(index.row()).kp,
self._data, index.row(),
self._data.profile(index.row()).kp,
value
)
)
@@ -149,39 +114,25 @@ class TableEditableModel(QAbstractTableModel):
return False
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):
flg = Qt.ItemIsEnabled | Qt.ItemIsSelectable
if index.column() == 2:
return flg
else:
return Qt.ItemIsEditable | flg
# @QtCore.pyqtSlot()
def insert_row(self, row, parent=QModelIndex()):
def add(self, row, parent=QModelIndex()):
self.beginInsertRows(parent, row, row - 1)
self._undo_stack.push(
self._undo.push(
AddCommand(
self._reach, row
self._data, row
)
)
self.endInsertRows()
self.layoutChanged.emit()
def remove_rows(self, rows, parent=QModelIndex()):
def delete(self, rows, parent=QModelIndex()):
self.beginRemoveRows(parent, rows[0], rows[-1])
self._undo_stack.push(
self._undo.push(
DelCommand(
self._reach, rows
self._data, rows
)
)
@@ -191,9 +142,9 @@ class TableEditableModel(QAbstractTableModel):
def sort_profiles(self, _reverse):
self.layoutAboutToBeChanged.emit()
self._undo_stack.push(
self._undo.push(
SortCommand(
self._reach, _reverse
self._data, _reverse
)
)
@@ -201,7 +152,7 @@ class TableEditableModel(QAbstractTableModel):
self.layoutChanged.emit()
def move_row_up(self, row, parent=QModelIndex()):
def move_up(self, row, parent=QModelIndex()):
if row <= 0:
return
@@ -209,26 +160,26 @@ class TableEditableModel(QAbstractTableModel):
self.beginMoveRows(parent, row - 1, row - 1, parent, target)
self._undo_stack.push(
self._undo.push(
MoveCommand(
self._reach, "up", row
self._data, "up", row
)
)
self.endMoveRows()
self.layoutChanged.emit()
def move_row_down(self, row, parent=QModelIndex()):
if row > self._reach.number_profiles:
def move_down(self, row, parent=QModelIndex()):
if row > self._data.number_profiles:
return
target = row
self.beginMoveRows(parent, row + 1, row + 1, parent, target)
self._undo_stack.push(
self._undo.push(
MoveCommand(
self._reach, "down", row
self._data, "down", row
)
)
@@ -238,9 +189,9 @@ class TableEditableModel(QAbstractTableModel):
def duplicate(self, rows, profiles):
self.layoutAboutToBeChanged.emit()
self._undo_stack.push(
self._undo.push(
DuplicateCommand(
self._reach, rows,
self._data, rows,
profiles
)
)
@@ -250,7 +201,7 @@ class TableEditableModel(QAbstractTableModel):
def paste(self, row, header, data):
if row > self._reach.number_profiles:
if row > self._data.number_profiles:
return
if len(data) == 0:
@@ -258,9 +209,9 @@ class TableEditableModel(QAbstractTableModel):
self.layoutAboutToBeChanged.emit()
self._undo_stack.push(
self._undo.push(
PasteCommand(
self._reach, row,
self._data, row,
list(
map(
lambda d: ProfileXYZ.from_data(header, d),
@@ -272,71 +223,3 @@ class TableEditableModel(QAbstractTableModel):
self.layoutAboutToBeChanged.emit()
self.layoutChanged.emit()
def undo(self):
self._undo_stack.undo()
self.layoutChanged.emit()
def redo(self):
self._undo_stack.redo()
self.layoutChanged.emit()
class Delegate(QStyledItemDelegate):
def __init__(self, parent=None, setModelDataEvent=None):
super(Delegate, self).__init__(parent)
self.setModelDataEvent = setModelDataEvent
def createEditor(self, parent, option, index):
index.model().data(index, Qt.DisplayRole)
return QLineEdit(parent)
def setEditorData(self, editor, index):
value = index.model().data(index, Qt.DisplayRole)
editor.setText(str(value))
def setModelData(self, editor, model, index):
model.setData(index, editor.text())
if not self.setModelDataEvent is None:
self.setModelDataEvent()
def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
class Delegate1(QStyledItemDelegate):
def __init__(self, owner, choices):
super().__init__(owner)
self.items = choices
def paint(self, painter, option, index):
if isinstance(self.parent(), QAbstractItemView):
self.parent().openPersistentEditor(index)
super(Delegate1, self).paint(painter, option, index)
def createEditor(self, parent, option, index):
editor = QComboBox(parent)
# editor.currentIndexChanged.connect(self.commit_editor)
editor.addItems(self.items)
return editor
def setEditorData(self, editor, index):
editor.blockSignals(True)
text = index.model().data(index, Qt.DisplayRole)
try:
i = self.items.index(text)
except ValueError:
i = 0
editor.setCurrentIndex(i)
editor.blockSignals(False)
def setModelData(self, editor, model, index):
model.setData(index, editor.currentText(), Qt.DisplayRole)
def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
@pyqtSlot()
def currentIndexChanged(self):
self.commitData.emit(self.sender())
+45
View File
@@ -0,0 +1,45 @@
# 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
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate
class GeometryTranslate(PamhyrTranslate):
def __init__(self):
super(GeometryTranslate, self).__init__()
self._dict["open_file"] = _translate("Geometry", "Open a file")
self._dict["file_st"] = _translate("Geometry", "File mage geometry (*.ST)")
self._dict["file_m"] = _translate("Geometry", "File mage meshed geometry (*.M)")
self._dict["file_all"] = _translate("Geometry", "All file (*)")
self._dict["reach"] = _translate("Geometry", "reach")
self._dict["reachs"] = _translate("Geometry", "reachs")
self._dict["cross_section"] = _translate("Geometry", "cross-section")
self._dict["cross_sections"] = _translate("Geometry", "cross-sections")
self._dict["profile"] = _translate("Geometry", "cross-section")
self._dict["profiles"] = _translate("Geometry", "cross-sections")
self._sub_dict["table_headers"] = {
"name": _translate("Geometry", "Name"),
"kp": _translate("Geometry", "KP"),
}
+156 -145
View File
@@ -34,117 +34,167 @@ from PyQt5.QtCore import (
)
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QFileDialog, QCheckBox,
QUndoStack, QShortcut,
QUndoStack, QShortcut, QTableView, QHeaderView,
QAction, QSlider, QPushButton, QVBoxLayout,
QLabel, QAbstractItemView,
)
from View.Geometry.PlotXY import PlotXY
from View.Geometry.PlotKPZ import PlotKPZ
from View.Geometry.PlotAC import PlotAC
from View.Tools.PamhyrWindow import PamhyrWindow
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.Tools.Plot.PamhyrCanvas import MplCanvas
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.Table import GeometryReachTableModel
from View.Geometry.PlotXY import PlotXY
from View.Geometry.PlotAC import PlotAC
from View.Geometry.PlotKPZ import PlotKPZ
from View.Geometry.Translate import GeometryTranslate
from View.Geometry.Profile.Window import ProfileWindow
_translate = QCoreApplication.translate
class GeometryWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, model=None, title="Geometry", parent=None):
self._title = title
self.parent = parent
class GeometryWindow(PamhyrWindow):
_pamhyr_ui = "GeometryReach"
_pamhyr_name = "Geometry"
def __init__(self, reach=None, study=None, config=None, parent=None):
if reach is None:
self._reach = study.river.current_reach().reach
else:
self._reach = reach
name = f"{self._pamhyr_name} - {self._reach.name}"
super(GeometryWindow, self).__init__(
name=self._title,
parent=parent
title = name,
study = study,
config = config,
trad = GeometryTranslate(),
parent = parent
)
self._model = model
self._reach = model.river.current_reach().reach
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.tableView = self.ui.tableView
self.tableView_header = self.ui.tableView_header
self._tablemodel = None
self._profile_window = []
self._clipboard = None
self.setup_window()
self.setup_sc()
self.setup_model()
self.setup_table()
self.setup_plots()
self.setup_statusbar()
self.setup_connections()
self.changed_slider_value()
def setup_window(self):
self._title = f"{self.ui.mainwindow_title} - {self._reach.name}"
self.setWindowTitle(self._title)
def setup_table(self):
table_headers = self._trad.get_dict("table_headers")
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_model(self):
self._tablemodel = TableEditableModel(
headers = self.ui.tableView_header,
reach = self._reach,
table = self.find(QTableView, "tableView")
self._tablemodel = GeometryReachTableModel(
table_view = table,
table_headers = table_headers,
editable_headers = ["name", "kp"],
data = self._reach,
undo = self._undo_stack
)
self.tableView.setModel(self._tablemodel)
self.tableView.setItemDelegate(Delegate())
table.setModel(self._tablemodel)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
def setup_plots(self):
self._canvas_xy = MplCanvas(width=3, height=4, dpi=100)
self._canvas_xy.setObjectName("canvas_xy")
self._toolbar_xy = PamhyrPlotToolbar(
self._canvas_xy, self,
items = ["home", "zoom", "save", "iso", "back/forward", "move"]
)
self._plot_layout_xy = self.find(QVBoxLayout, "verticalLayout")
self._plot_layout_xy.addWidget(self._toolbar_xy)
self._plot_layout_xy.addWidget(self._canvas_xy)
self.plot_xy()
self._canvas_kpc = MplCanvas(width=6, height=4, dpi=100)
self._canvas_kpc.setObjectName("canvas_kpc")
self._toolbar_kpc = PamhyrPlotToolbar(
self._canvas_kpc, self,
items = ["home", "zoom", "save", "iso", "back/forward", "move"]
)
self._plot_layout_kpc = self.find(QVBoxLayout, "verticalLayout_2")
self._plot_layout_kpc.addWidget(self._toolbar_kpc)
self._plot_layout_kpc.addWidget(self._canvas_kpc)
self.plot_kpc()
self._canvas_ac = MplCanvas(width=9, height=4, dpi=100)
self._canvas_ac.setObjectName("canvas_ac")
self._toolbar_ac = PamhyrPlotToolbar(
self._canvas_ac, self,
items = ["home", "zoom", "save", "iso", "back/forward", "move"]
)
self._plot_layout_ac = self.find(QVBoxLayout, "verticalLayout_3")
self._plot_layout_ac.addWidget(self._toolbar_ac)
self._plot_layout_ac.addWidget(self._canvas_ac)
self.plot_ac()
def _compute_status_label(self):
row = self.index_selected_row()
profile = self._reach.profile(row)
name = profile.name + " " + str(profile.kp)
return (
f"<font color=\"Grey\">{self._trad['reach']}: {self._reach.name}" + " - "
f"{self._trad['cross_section']}:</font> {name}"
)
def setup_statusbar(self):
txt = ""
self._status_label = QLabel(txt)
self.statusbar.addPermanentWidget(self._status_label)
def update_statusbar(self):
txt = self._compute_status_label()
self._status_label.setText(txt)
def setup_connections(self):
self.ui.btn_open.triggered.connect(self.open_file_dialog)
self.ui.btn_sort_asc.triggered.connect(self.sort_ascending)
self.ui.btn_sort_desc.triggered.connect(self.sort_descending)
self.ui.btn_move_up.triggered.connect(self.move_row_up)
self.ui.btn_move_down.triggered.connect(self.move_row_down)
# self.ui.btn_end_editing.triggered.connect(self.handleSave)
self.ui.btn_add.triggered.connect(self.insert_row)
self.ui.btn_delete.triggered.connect(self.delete_rows)
self.ui.btn_edit.triggered.connect(self.edit_profile)
self.ui.verticalSlider.valueChanged.connect(self.changed_slider_value)
actions = {
"action_import": self.import_from_file,
# "action_export": self.export_to_file,
"action_sort_asc": self.sort_ascending,
"action_sort_des": self.sort_descending,
"action_up": self.move_up,
"action_down": self.move_down,
"action_add": self.add,
"action_delete": self.delete,
"action_edit": self.edit_profile,
}
self.ui.btn_slider_up.clicked.connect(self.decrement_value_slider)
self.ui.btn_slider_down.clicked.connect(self.increment_value_slider)
self.ui.btn_move_up.triggered.connect(self.changed_profile_slot)
for action in actions:
self.find(QAction, action)\
.triggered.connect(actions[action])
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)
self.find(QSlider, "verticalSlider").valueChanged.connect(self.changed_slider_value)
self.find(QPushButton, "pushButton_up").clicked.connect(self.decrement_value_slider)
self.find(QPushButton, "pushButton_down").clicked.connect(self.increment_value_slider)
# Profile selection when line change in table
self.tableView.selectionModel()\
.selectionChanged\
.connect(self.select_current_profile)
self.find(QTableView, "tableView").selectionModel()\
.selectionChanged\
.connect(self.select_current_profile)
def open_file_dialog(self):
def import_from_file(self):
options = QFileDialog.Options()
settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'MyOrg', )
options |= QFileDialog.DontUseNativeDialog
file_types = [
self._trad["file_st"],
self._trad["file_m"],
self._trad["file_all"],
]
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
self,
_translate("MainWindow_reach", "Ouvrir un fichier"),
self._trad["open_file"],
"",
_translate("MainWindow_reach", "Fichiers .ST (*.ST)") +
";; " +
_translate("MainWindow_reach", "Fichiers .M (*.M)") +
";; " +
_translate("MainWindow_reach", "Tous les fichiers (*)"),
";; ".join(file_types),
options=options
)
@@ -158,20 +208,6 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self.plot_kpc()
self.plot_ac()
def messagebox_profile_editing(self):
msg_box = QtWidgets.QMessageBox()
msg_box.setIcon(QtWidgets.QMessageBox.Information)
msg_box.setWindowTitle(_translate("MainWindow_reach",
"Édition des profils sélectionnés"))
msg_box.setText(_translate("MainWindow_reach",
"Vous avez sélectionné plus de 5 profils."
" \nSeuls les 5 premiers seront édités."))
msg_box.setStandardButtons(QtWidgets.QMessageBox.Ok)
return_value = msg_box.exec()
# if return_value == QtWidgets.QMessageBox.Ok:
# print('OK clicked')
def edit_profile(self):
self.tableView.model().blockSignals(True)
@@ -214,9 +250,9 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self.tableView.model().blockSignals(True)
self._plot_xy = PlotXY(
canvas = self.ui.canvas_1,
canvas = self._canvas_xy,
data = self._reach,
toolbar = self.ui.toolbar_1
toolbar = self._toolbar_xy
)
self._plot_xy.draw()
@@ -231,9 +267,9 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self.tableView.model().blockSignals(True)
self._plot_kpc = PlotKPZ(
canvas = self.ui.canvas_2,
canvas = self._canvas_kpc,
data = self._reach,
toolbar = self.ui.toolbar_2
toolbar = self._toolbar_kpc
)
self._plot_kpc.draw()
@@ -248,9 +284,9 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self.tableView.model().blockSignals(True)
self._plot_ac = PlotAC(
canvas = self.ui.canvas_3,
canvas = self._canvas_ac,
data = self._reach,
toolbar = self.ui.toolbar_3,
toolbar = self._toolbar_ac,
plot_xy = self._plot_xy
)
self._plot_ac.draw()
@@ -303,7 +339,7 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
if len(self.tableView.selectedIndexes()) > 0:
row = self.index_selected_row()
self.ui.verticalSlider.setValue(row)
self.find(QSlider, "verticalSlider").setValue(row)
self.select_plot_xy(row)
self.select_plot_kpc(row)
self.select_plot_ac(row)
@@ -314,41 +350,37 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self.tableView.model().blockSignals(True)
if self._tablemodel.rowCount() != 0:
self.ui.verticalSlider.setMaximum(self._tablemodel.rowCount() - 1)
slider = self.find(QSlider, "verticalSlider")
slider.setMaximum(self._tablemodel.rowCount() - 1)
slider_value = self.ui.verticalSlider.value()
slider_value = slider.value()
kp = self._reach.profile(slider_value).kp
self.ui.vertical_slider_label.setText(
_translate("MainWindow_reach", "Kp : ") +
f"{kp}" + "\n" +
_translate("MainWindow_reach",
"Profil N° : ") +
f"{slider_value + 1}"
)
self.select_plot_xy(slider_value)
self.select_plot_kpc(slider_value)
self.select_row_profile_slider(slider_value)
self.update_statusbar()
self.tableView.model().blockSignals(False)
def increment_value_slider(self):
if 0 <= self.ui.verticalSlider.value() < self._tablemodel.rowCount() - 1:
self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() + 1)
slider = self.find(QSlider, "verticalSlider")
if 0 <= slider.value() < self._tablemodel.rowCount() - 1:
slider.setValue(slider.value() + 1)
def decrement_value_slider(self):
if 0 < self.ui.verticalSlider.value() < self._tablemodel.rowCount():
self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() - 1)
slider = self.find(QSlider, "verticalSlider")
if 0 < slider.value() < self._tablemodel.rowCount():
slider.setValue(slider.value() - 1)
def insert_row(self):
def add(self):
if len(self.tableView.selectedIndexes()) == 0:
self._tablemodel.insert_row(self._tablemodel.rowCount())
self._tablemodel.add(self._tablemodel.rowCount())
else:
row = self.index_selected_row()
self._tablemodel.insert_row(row + 1)
self._tablemodel.add(row + 1)
def delete_rows(self):
def delete(self):
rows = sorted(
list(
set(
@@ -358,7 +390,7 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
)
if len(rows) > 0:
self._tablemodel.remove_rows(rows)
self._tablemodel.delete(rows)
self.update_plot_xy()
self.select_current_profile()
@@ -373,24 +405,24 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
.row()
def sort_ascending(self):
self._tablemodel.sort_profiles(True)
self._tablemodel.sort_profiles(False)
self.select_current_profile()
self.changed_slider_value()
def sort_descending(self):
self._tablemodel.sort_profiles(False)
self._tablemodel.sort_profiles(True)
self.select_current_profile()
self.changed_slider_value()
def move_row_up(self):
def move_up(self):
row = self.index_selected_row()
self._tablemodel.move_row_up(row)
self._tablemodel.move_up(row)
self.select_current_profile()
def move_row_down(self):
def move_down(self):
row = self.index_selected_row()
self._tablemodel.move_row_down(row)
self._tablemodel.move_down(row)
self.select_current_profile()
def duplicate(self):
@@ -411,7 +443,7 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self._tablemodel.duplicate(rows, profiles)
self.select_current_profile()
def copy(self):
def _copy(self):
rows = self.tableView\
.selectionModel()\
.selectedRows()
@@ -427,7 +459,7 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self.copyTableIntoClipboard(table)
def paste(self):
def _paste(self):
header, data = self.parseClipboardTable()
if len(data) == 0:
@@ -442,19 +474,19 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self._tablemodel.paste(row, header, data)
self.select_current_profile()
def undo(self):
def _undo(self):
self._tablemodel.undo()
self.select_current_profile()
self.update_plot_xy()
self.update_plot_kpc()
def redo(self):
def _redo(self):
self._tablemodel.redo()
self.select_current_profile()
self.update_plot_xy()
self.update_plot_kpc()
def handleSave(self):
def export_to_file(self):
options = QFileDialog.Options()
DEFAULT_DIRECTORY = '/home/'
settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'MyOrg', )
@@ -463,32 +495,11 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
filename, filters = QFileDialog.getSaveFileName(
self,
filter=_translate("MainWindow_reach",
"Files .ST(*.ST or *.st)")
+ ";; " +
_translate("MainWindow_reach", "All files "
"(*)"),
options=options
filter = self._trad["file_st"] + ";; " + self._trad["file_all"],
options = options
)
current_dir = os.path.split(filename)[0] or DEFAULT_DIRECTORY
if filename != '':
self._tablemodel.export_reach(filename)
def handleOpen(self):
filename, filterName = QFileDialog.getOpenFileName(self)
if filename != '':
with open(filename, 'r') as f:
reader = csv.reader(f, delimiter='\t')
header = next(reader)
buf = []
for row in reader:
row[0] = QCheckBox("-")
buf.append(row)
self._tablemodel = None
self._tablemodel = TableEditableModel(buf)
self.tableView.setModel(self._tablemodel)
filename = ''
-357
View File
@@ -1,357 +0,0 @@
# 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
import os.path
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QSize, Qt
from PyQt5.QtWidgets import (
QAbstractItemView, QHeaderView, QToolBar,
)
from View.Plot import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar
file_path = os.path.abspath(os.path.dirname(__file__))
icon_path = f"{os.path.dirname(os.path.dirname(file_path))}/View/ui/ressources/"
class Ui_MainWindow(object):
def setupUi(self, MainWindow_reach):
MainWindow_reach.setObjectName("MainWindow_reach")
MainWindow_reach.resize(1400, 800)
self.centralwidget = QtWidgets.QWidget(MainWindow_reach)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.splitter_3 = QtWidgets.QSplitter(self.centralwidget)
self.splitter_3.setOrientation(Qt.Horizontal)
self.splitter_3.setObjectName("splitter_3")
self.widget = QtWidgets.QWidget(self.splitter_3)
self.widget.setObjectName("widget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
# self.label_section_order = QtWidgets.QLabel(self.widget)
# self.label_section_order.setLayoutDirection(Qt.LeftToRight)
# self.label_section_order.setObjectName("label_section_order")
# self.verticalLayout.addWidget(self.label_section_order)
self.toolBar = QToolBar(MainWindow_reach)
self.toolBar.setEnabled(True)
MainWindow_reach.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
btn_size = QSize(40, 28)
self.btn_open = QtWidgets.QAction(self.widget)
self.btn_open.setObjectName("btn_open")
icon_btn_open = QtGui.QIcon()
icon_btn_open.addPixmap(
QtGui.QPixmap(f"{icon_path}open.png"))
self.btn_open.setIcon(icon_btn_open)
self.toolBar.addAction(self.btn_open)
self.btn_add = QtWidgets.QAction(self.widget)
self.btn_add.setObjectName("btn_add")
icon_btn_add = QtGui.QIcon()
icon_btn_add.addPixmap(
QtGui.QPixmap(f"{icon_path}gtk_add.png"))
self.btn_add.setIcon(icon_btn_add)
self.toolBar.addAction(self.btn_add)
self.btn_delete = QtWidgets.QAction(self.widget)
self.btn_delete.setObjectName("btn_delete")
icon_btn_delete = QtGui.QIcon()
icon_btn_delete.addPixmap(
QtGui.QPixmap(f"{icon_path}gtk-remove.png"))
self.btn_delete.setIcon(icon_btn_delete)
self.toolBar.addAction(self.btn_delete)
self.btn_edit = QtWidgets.QAction(self.widget)
self.btn_edit.setObjectName("btn_edit")
icon_btn_edit = QtGui.QIcon()
icon_btn_edit.addPixmap(
QtGui.QPixmap(f"{icon_path}gnome-stock-edit.png"))
self.btn_edit.setIcon(icon_btn_edit)
self.toolBar.addAction(self.btn_edit)
# self.btn_copy_selected_profile = QtWidgets.QAction(self.widget)
# self.btn_copy_selected_profile.setObjectName("btn_copy_selected_profile")
# icon_btn_copy_selected_profile = QtGui.QIcon()
# icon_btn_copy_selected_profile.addPixmap(
# QtGui.QPixmap(f"{icon_path}gtk-copy.png"))
# self.btn_copy_selected_profile.setIcon(icon_btn_copy_selected_profile)
# self.toolBar.addAction(self.btn_copy_selected_profile)
# self.btn_paste_selected_profile = QtWidgets.QAction(self.widget)
# self.btn_paste_selected_profile.setObjectName("btn_paste_selected_profile")
# icon_btn_paste_selected_profile = QtGui.QIcon()
# icon_btn_paste_selected_profile.addPixmap(
# QtGui.QPixmap(f"{icon_path}gtk-paste.png"))
# self.btn_paste_selected_profile.setIcon(icon_btn_paste_selected_profile)
# self.toolBar.addAction(self.btn_paste_selected_profile)
# self.btn_duplicate_selected_profile = QtWidgets.QAction(self.widget)
# self.btn_duplicate_selected_profile.setObjectName("btn_duplicate_selected_profile")
# icon_btn_duplicate_selected_profile = QtGui.QIcon()
# icon_btn_duplicate_selected_profile.addPixmap(
# QtGui.QPixmap(f"{icon_path}gtk-dnd-multiple.png"))
# self.btn_duplicate_selected_profile.setIcon(icon_btn_duplicate_selected_profile)
# self.toolBar.addAction(self.btn_duplicate_selected_profile)
self.btn_sort_asc = QtWidgets.QAction(self.widget)
self.btn_sort_asc.setObjectName("btn_sort_asc")
icon_btn_sort_asc = QtGui.QIcon()
icon_btn_sort_asc.addPixmap(
QtGui.QPixmap(f"{icon_path}gtk-sort-ascending.png"))
self.btn_sort_asc.setIcon(icon_btn_sort_asc)
self.toolBar.addAction(self.btn_sort_asc)
self.btn_sort_desc = QtWidgets.QAction(self.widget)
self.btn_sort_desc.setObjectName("btn_sort_desc")
icon_btn_sort_desc = QtGui.QIcon()
icon_btn_sort_desc.addPixmap(
QtGui.QPixmap(f"{icon_path}gtk-sort-descending.png"))
self.btn_sort_desc.setIcon(icon_btn_sort_desc)
self.toolBar.addAction(self.btn_sort_desc)
self.btn_move_up = QtWidgets.QAction(self.widget)
self.btn_move_up.setObjectName("btn_move_up")
icon_btn_move_up = QtGui.QIcon()
icon_btn_move_up.addPixmap(
QtGui.QPixmap(f"{icon_path}up.png"))
self.btn_move_up.setIcon(icon_btn_move_up)
self.toolBar.addAction(self.btn_move_up)
self.btn_move_down = QtWidgets.QAction(self.widget)
self.btn_move_down.setObjectName("btn_move_down")
icon_btn_move_down = QtGui.QIcon()
icon_btn_move_down.addPixmap(
QtGui.QPixmap(f"{icon_path}down.png"))
self.btn_move_down.setIcon(icon_btn_move_down)
self.toolBar.addAction(self.btn_move_down)
# self.btn_end_editing = QtWidgets.QAction(self.widget)
# self.btn_end_editing.setObjectName("btn_end_editing")
# icon_btn_save = QtGui.QIcon()
# icon_btn_save.addPixmap(
# QtGui.QPixmap(f"{icon_path}gtk-apply.png"))
# self.btn_end_editing.setIcon(icon_btn_save)
# self.toolBar.addAction(self.btn_end_editing)
self.verticalLayout.addLayout(self.horizontalLayout)
self.tableView = QtWidgets.QTableView(self.widget)
self.tableView.setObjectName("tableView")
self.verticalLayout.addWidget(self.tableView)
self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.tableView.setAlternatingRowColors(True)
self.tableView.verticalHeader().hide()
self.tableView.resizeColumnsToContents()
self.tableView.resizeRowsToContents()
self.widget1 = QtWidgets.QWidget(self.splitter_3)
self.widget1.setObjectName("widget1")
self.gridLayout = QtWidgets.QGridLayout(self.widget1)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.splitter_2 = QtWidgets.QSplitter(self.widget1)
self.splitter_2.setOrientation(Qt.Vertical)
self.splitter_2.setObjectName("splitter_2")
self.splitter = QtWidgets.QSplitter(self.splitter_2)
self.splitter.setOrientation(Qt.Horizontal)
self.splitter.setObjectName("splitter")
self.verticalLayoutWidget_3 = QtWidgets.QWidget(self.splitter)
self.verticalLayoutWidget_3.setObjectName("verticalLayoutWidget_3")
self.verticalLayout_canvas_1 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_3)
self.verticalLayout_canvas_1.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_canvas_1.setObjectName("verticalLayout_canvas_1")
self.canvas_1 = MplCanvas.MplCanvas(width=5, height=4, dpi=100)
self.canvas_1.setObjectName("canvas_1")
self.toolbar_1 = PamhyrPlotToolbar(
self.canvas_1, self.centralwidget,
items = ["home", "zoom", "save", "iso", "back/forward", "move"]
)
self.verticalLayout_canvas_1.addWidget(self.toolbar_1)
self.verticalLayout_canvas_1.addWidget(self.canvas_1)
self.verticalLayoutWidget_2 = QtWidgets.QWidget(self.splitter)
self.verticalLayoutWidget_2.setObjectName("verticalLayoutWidget_2")
self.verticalLayout_canvas_2 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_2)
self.verticalLayout_canvas_2.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_canvas_2.setObjectName("verticalLayout_canvas_2")
self.canvas_2 = MplCanvas.MplCanvas(width=5, height=4, dpi=100)
self.canvas_2.setObjectName("canvas_2")
self.toolbar_2 = PamhyrPlotToolbar(
self.canvas_2, self.centralwidget,
items = ["home", "zoom", "save", "iso", "back/forward", "move"]
)
self.verticalLayout_canvas_2.addWidget(self.toolbar_2)
self.verticalLayout_canvas_2.addWidget(self.canvas_2)
self.verticalLayoutWidget = QtWidgets.QWidget(self.splitter_2)
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout_canvas_3 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout_canvas_3.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_canvas_3.setObjectName("verticalLayout_canvas_3")
self.canvas_3 = MplCanvas.MplCanvas(width=5, height=4, dpi=100)
self.canvas_3.setObjectName("canvas_3")
self.toolbar_3 = PamhyrPlotToolbar(
self.canvas_3, self.centralwidget,
items = ["home", "zoom", "save", "iso", "back/forward", "move"]
)
self.verticalLayout_canvas_3.addWidget(self.toolbar_3)
self.verticalLayout_canvas_3.addWidget(self.canvas_3)
self.gridLayout.addWidget(self.splitter_2, 0, 0, 3, 3)
self.verticalSlider = QtWidgets.QSlider(self.widget1)
self.verticalSlider.setMinimumSize(QtCore.QSize(30, 0))
self.verticalSlider.setOrientation(Qt.Vertical)
self.verticalSlider.setInvertedAppearance(True)
self.verticalSlider.setInvertedControls(False)
self.verticalSlider.setObjectName("verticalSlider")
self.gridLayout.addWidget(self.verticalSlider, 0, 3, 1, 1)
self.btn_slider_up = QtWidgets.QPushButton(self.widget1)
self.btn_slider_up.setMaximumSize(btn_size)
self.btn_slider_up.setText("")
self.btn_slider_up.setObjectName("btn_slider_up")
icon_btn_slider_up = QtGui.QIcon()
icon_btn_slider_up.addPixmap(
QtGui.QPixmap(f"{icon_path}go-up2.png"))
self.btn_slider_up.setIcon(icon_btn_slider_up)
#self.btn_slider_up.setIconSize(btn_size)
self.gridLayout.addWidget(self.btn_slider_up, 1, 3, 1, 1)
self.btn_slider_down = QtWidgets.QPushButton(self.widget1)
self.btn_slider_down.setMaximumSize(btn_size)
self.btn_slider_down.setText("")
self.btn_slider_down.setObjectName("btn_slider_down")
icon_btn_slider_down = QtGui.QIcon()
icon_btn_slider_down.addPixmap(
QtGui.QPixmap(f"{icon_path}go-down1.png"))
self.btn_slider_down.setIcon(icon_btn_slider_down)
#self.btn_slider_down.setIconSize(btn_size)
self.gridLayout.addWidget(self.btn_slider_down, 2, 3, 1, 1)
self.vertical_slider_label = QtWidgets.QLabel(self.widget1)
self.vertical_slider_label.setObjectName("vertical_slider_label")
self.gridLayout.addWidget(self.vertical_slider_label, 3, 2, 2, 1)
self.vertical_slider_label.setAlignment(Qt.AlignRight)
# self.btn_slider_go_back = QtWidgets.QPushButton(self.widget1)
# self.btn_slider_go_back.setMaximumSize(btn_size)
# self.btn_slider_go_back.setText("")
# self.btn_slider_go_back.setObjectName("btn_slider_go_back")
# icon_btn_slider_go_back = QtGui.QIcon()
# icon_btn_slider_go_back.addPixmap(
# QtGui.QPixmap(f"{icon_path}gtk-go-back.png"))
# self.btn_slider_go_back.setIcon(icon_btn_slider_go_back)
# #self.btn_slider_go_back.setIconSize(btn_size)
# self.gridLayout.addWidget(self.btn_slider_go_back, 5, 0, 1, 1)
# self.btn_slider_go_back.setEnabled(False)
# self.btn_slider_go_forward = QtWidgets.QPushButton(self.widget1)
# self.btn_slider_go_forward.setMaximumSize(btn_size)
# self.btn_slider_go_forward.setText("")
# self.btn_slider_go_forward.setObjectName("btn_slider_go_forward")
# icon_btn_slider_go_forward = QtGui.QIcon()
# icon_btn_slider_go_forward.addPixmap(
# QtGui.QPixmap(f"{icon_path}gtk-go-forward.png"))
# self.btn_slider_go_forward.setIcon(icon_btn_slider_go_forward)
# #self.btn_slider_go_forward.setIconSize(btn_size)
# self.gridLayout.addWidget(self.btn_slider_go_forward, 5, 1, 1, 1)
# self.btn_slider_go_forward.setEnabled(False)
# self.horizontalSlider = QtWidgets.QSlider(self.widget1)
# self.horizontalSlider.setMinimumSize(QtCore.QSize(0, 30))
# self.horizontalSlider.setOrientation(Qt.Horizontal)
# self.horizontalSlider.setObjectName("horizontalSlider")
# self.gridLayout.addWidget(self.horizontalSlider, 5, 2, 1, 1)
# self.horizontalSlider.setEnabled(False)
self.horizontalLayout_2.addWidget(self.splitter_3)
MainWindow_reach.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow_reach)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1123, 20))
self.menubar.setObjectName("menubar")
MainWindow_reach.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow_reach)
self.statusbar.setObjectName("statusbar")
MainWindow_reach.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow_reach)
QtCore.QMetaObject.connectSlotsByName(MainWindow_reach)
def retranslateUi(self, MainWindow_reach):
_translate = QtCore.QCoreApplication.translate
self.name_reach = ""
self.mainwindow_title = _translate("MainWindow_reach", "Geometry reach edit")
MainWindow_reach.setWindowTitle(self.mainwindow_title + f"{self.name_reach}")
# self.label_section_order.setText(f"{self.text_section_order}")
self.vertical_slider_value = ""
self.vertical_slider_label.setText(_translate("MainWindow_reach", "Kp = ") + f"{self.vertical_slider_value}")
self.btn_open.setToolTip(_translate("MainWindow_reach", " Import geometry"))
self.btn_add.setToolTip(_translate("MainWindow_reach", " New profile"))
self.btn_delete.setToolTip(_translate("MainWindow_reach", " Delete selected profile"))
self.btn_edit.setToolTip(_translate("MainWindow_reach", " Editer selected profile"))
self.btn_sort_asc.setToolTip(_translate("MainWindow_reach", " Trier les profils par ordre croissant des Pk"))
self.btn_sort_desc.setToolTip(_translate("MainWindow_reach", " Trier les profils par ordre décroissant des Pk"))
self.btn_move_up.setToolTip(_translate("MainWindow_reach", " Changer l'ordre des profils (en décalant le "
"profil sélectionné vers le haut)"))
self.btn_move_down.setToolTip(_translate("MainWindow_reach", " Changer l'ordre des profils (en décalant le "
"profil sélectionné vers le bas)"))
# self.btn_end_editing.setToolTip(_translate("MainWindow_reach", " Terminer l'édition"))
self.tableView_header = [_translate("MainWindow_reach", "Name"),
_translate("MainWindow_reach", "Kp (m)"),
_translate("MainWindow_reach", "Type")]
self.toolbar_1._actions["isometric_view"].setShortcut(_translate("MainWindow_reach", "Alt+Z"))
self.toolbar_1._actions["isometric_view"].setToolTip(_translate("MainWindow_reach", "Vue isométrique (Alt+Z)"))
self.toolbar_2._actions["isometric_view"].setShortcut(_translate("MainWindow_reach", "Alt+E"))
self.toolbar_2._actions["isometric_view"].setToolTip(_translate("MainWindow_reach", "Vue isométrique (Alt+E)"))
self.toolbar_3._actions["isometric_view"].setShortcut(_translate("MainWindow_reach", "Alt+R"))
self.toolbar_3._actions["isometric_view"].setToolTip(_translate("MainWindow_reach", "Vue isométrique (Alt+R)"))
self.toolbar_1._actions["non_isometric_view"].setShortcut("Alt+S")
self.toolbar_1._actions["non_isometric_view"].setToolTip(
_translate("MainWindow_reach", "Vue globale automatique (Alt+S)"))
self.toolbar_2._actions["non_isometric_view"].setShortcut("Alt+D")
self.toolbar_2._actions["non_isometric_view"].setToolTip(
_translate("MainWindow_reach", "Vue globale automatique (Alt+D)"))
self.toolbar_3._actions["non_isometric_view"].setShortcut("Alt+F")
self.toolbar_3._actions["non_isometric_view"].setToolTip(
_translate("MainWindow_reach", "Vue globale automatique (Alt+F)"))
@@ -16,8 +16,7 @@
# -*- coding: utf-8 -*-
from View.ASubWindow import ASubWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtGui import (
QKeySequence,
@@ -32,10 +31,15 @@ from PyQt5.QtWidgets import (
QDoubleSpinBox,
)
class DischargeDialog(ASubWindow, ListedSubWindow):
class DischargeDialog(PamhyrDialog):
_pamhyr_ui = "InitialConditions_Dialog_Generator_Discharge"
_pamhyr_name = "Discharge"
def __init__(self, title="Discharge", parent=None):
super(DischargeDialog, self).__init__(
name=title, ui="InitialConditions_Dialog_Generator_Discharge", parent=parent
title = self._pamhyr_name,
options = [],
parent = parent
)
self.value = None
+9 -5
View File
@@ -16,8 +16,7 @@
# -*- coding: utf-8 -*-
from View.ASubWindow import ASubWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtGui import (
QKeySequence,
@@ -32,10 +31,15 @@ from PyQt5.QtWidgets import (
QDoubleSpinBox,
)
class HeightDialog(ASubWindow, ListedSubWindow):
def __init__(self, title="Height", parent=None):
class HeightDialog(PamhyrDialog):
_pamhyr_ui = "InitialConditions_Dialog_Generator_Height"
_pamhyr_name = "Height"
def __init__(self, parent=None):
super(HeightDialog, self).__init__(
name=title, ui="InitialConditions_Dialog_Generator_Height", parent=parent
title = self._pamhyr_name,
options = [],
parent = parent
)
self.value = None
+4 -11
View File
@@ -17,7 +17,7 @@
# -*- coding: utf-8 -*-
from tools import timer
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
@@ -25,14 +25,7 @@ from PyQt5.QtCore import (
_translate = QCoreApplication.translate
class PlotDKP(APlot):
def __init__(self, canvas=None, data=None, toolbar=None):
super(PlotDKP, self).__init__(
canvas=canvas,
data=data,
toolbar=toolbar
)
class PlotDKP(PamhyrPlot):
@timer
def draw(self, highlight=None):
self.canvas.axes.cla()
@@ -42,11 +35,11 @@ class PlotDKP(APlot):
return
self.canvas.axes.set_ylabel(
_translate("MainWindow_reach", "Elevation (m)"),
self._trad["elevation"],
color='green', fontsize=11
)
self.canvas.axes.set_xlabel(
_translate("MainWindow_reach", "KP (m)"),
self._trad["kp"],
color='green', fontsize=11
)
+4 -17
View File
@@ -17,22 +17,9 @@
# -*- coding: utf-8 -*-
from tools import timer
from View.Plot.APlot import APlot
from PyQt5.QtCore import (
QCoreApplication
)
_translate = QCoreApplication.translate
class PlotDischarge(APlot):
def __init__(self, canvas=None, data=None, toolbar=None):
super(PlotDischarge, self).__init__(
canvas=canvas,
data=data,
toolbar=toolbar
)
from View.Tools.PamhyrPlot import PamhyrPlot
class PlotDischarge(PamhyrPlot):
@timer
def draw(self, highlight=None):
self.canvas.axes.cla()
@@ -42,11 +29,11 @@ class PlotDischarge(APlot):
return
self.canvas.axes.set_ylabel(
_translate("MainWindow_reach", "Discharge (m^3/s)"),
self._trad["discharge"],
color='green', fontsize=11
)
self.canvas.axes.set_xlabel(
_translate("MainWindow_reach", "KP (m)"),
self._trad["kp"],
color='green', fontsize=11
)
+17 -39
View File
@@ -33,14 +33,14 @@ from PyQt5.QtWidgets import (
QComboBox,
)
from View.Tools.PamhyrTable import PamhyrTableModel
from View.InitialConditions.UndoCommand import (
SetCommand, AddCommand, DelCommand,
SortCommand, MoveCommand, PasteCommand,
DuplicateCommand, GenerateCommand,
)
from View.InitialConditions.translate import *
logger = logging.getLogger()
_translate = QCoreApplication.translate
@@ -87,29 +87,13 @@ class ComboBoxDelegate(QItemDelegate):
self.commitData.emit(self.sender())
class TableModel(QAbstractTableModel):
def __init__(self, river=None, reach=None, undo=None):
super(QAbstractTableModel, self).__init__()
self._headers = list(table_headers.keys())
self._river = river
class InitialConditionTableModel(PamhyrTableModel):
def __init__(self, reach=None, **kwargs):
self._reach = reach
self._undo = undo
self._ics = self._river.initial_conditions.get(reach)
super(InitialConditionTableModel, self).__init__(**kwargs)
def flags(self, index):
column = index.column()
options = Qt.ItemIsSelectable
if self._headers[column] != "speed":
options |= Qt.ItemIsEnabled | Qt.ItemIsEditable
return options
def rowCount(self, parent):
return len(self._ics)
def columnCount(self, parent):
return len(self._headers)
def _setup_lst(self):
self._lst = self._data.river.initial_conditions.get(self._reach)
def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole:
@@ -119,16 +103,10 @@ class TableModel(QAbstractTableModel):
column = index.column()
if self._headers[column] not in ["name", "comment"]:
v = self._ics.get(row)[self._headers[column]]
v = self._lst.get(row)[self._headers[column]]
return f"{v:.4f}"
else:
return self._ics.get(row)[self._headers[column]]
return QVariant()
def headerData(self, section, orientation, role):
if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
return table_headers[self._headers[section]]
return self._lst.get(row)[self._headers[column]]
return QVariant()
@@ -143,7 +121,7 @@ class TableModel(QAbstractTableModel):
if self._headers[column] is not None:
self._undo.push(
SetCommand(
self._ics, row, self._headers[column], value
self._lst, row, self._headers[column], value
)
)
except Exception as e:
@@ -158,7 +136,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
AddCommand(
self._ics, row
self._lst, row
)
)
@@ -170,7 +148,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
DelCommand(
self._ics, rows
self._lst, rows
)
)
@@ -182,7 +160,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
SortCommand(
self._ics, False
self._lst, False
)
)
@@ -199,7 +177,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
MoveCommand(
self._ics, "up", row
self._lst, "up", row
)
)
@@ -207,7 +185,7 @@ class TableModel(QAbstractTableModel):
self.layoutChanged.emit()
def move_down(self, index, parent=QModelIndex()):
if row > len(self._ics):
if row > len(self._lst):
return
target = row
@@ -216,7 +194,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
MoveCommand(
self._ics, "down", row
self._lst, "down", row
)
)
@@ -234,7 +212,7 @@ class TableModel(QAbstractTableModel):
def generate(self, generator, param):
self._undo.push(
GenerateCommand(
self._ics, generator, param
self._lst, generator, param
)
)
self.layoutChanged.emit()
+48 -55
View File
@@ -20,8 +20,7 @@ import logging
from tools import trace, timer
from View.ASubWindow import ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -46,14 +45,14 @@ from View.InitialConditions.UndoCommand import (
DuplicateCommand,
)
from View.InitialConditions.Table import TableModel, ComboBoxDelegate
from View.InitialConditions.Table import InitialConditionTableModel, ComboBoxDelegate
from View.Plot.MplCanvas import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.InitialConditions.PlotDKP import PlotDKP
from View.InitialConditions.PlotDischarge import PlotDischarge
from View.InitialConditions.translate import table_headers, retranslate
from View.InitialConditions.translate import ICTranslate
from View.InitialConditions.DialogHeight import HeightDialog
from View.InitialConditions.DialogDischarge import DischargeDialog
@@ -61,67 +60,62 @@ _translate = QCoreApplication.translate
logger = logging.getLogger()
class InitialConditionsWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Initial condition",
study=None, parent=None):
self._study = study
self._reach = study.river.current_reach()
self._ics = self._study.river.initial_conditions.get(self._reach)
class InitialConditionsWindow(PamhyrWindow):
_pamhyr_ui = "InitialConditions"
_pamhyr_name = "Initial condition"
self.setup_title(title)
def __init__(self, study=None, config=None, reach=None, parent=None):
if reach is not None:
self._reach = reach
else:
self._reach = study.river.current_reach()
super(InitialConditionsWindow, self).__init__(
name=self._title, ui="InitialConditions", parent=parent
name = (
self._pamhyr_name +
" - " + study.name +
" - " + self._reach.name
)
self.setup_sc()
super(InitialConditionsWindow, self).__init__(
title = name,
study = study,
config = config,
trad = ICTranslate(),
parent = parent
)
self._ics = study.river.initial_conditions.get(self._reach)
self.setup_table()
self.setup_graph()
self.setup_plot()
self.setup_connections()
self.ui.setWindowTitle(self._title)
def setup_title(self, title):
self._title = (
title + " - "
+ self._study.name + " - "
+ self._reach.name
)
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):
retranslate()
table = self.find(QTableView, f"tableView")
self._table = TableModel(
river = self._study.river,
reach = self._reach,
undo = self._undo_stack,
)
table.setModel(self._table)
self._delegate_kp = ComboBoxDelegate(
reach = self._reach,
parent=self
parent = self
)
table.setItemDelegateForColumn(
list(table_headers).index("kp"),
self._delegate_kp
self._table = InitialConditionTableModel(
reach = self._reach,
table_view = table,
table_headers = self._trad.get_dict("table_headers"),
editable_headers = ["kp", "discharge", "elevation", "height"],
delegates = {"kp": self._delegate_kp},
data = self._study,
undo = self._undo_stack,
trad = self._trad
)
table.setModel(self._table)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
def setup_graph(self):
def setup_plot(self):
self.canvas_1 = MplCanvas(width=5, height=4, dpi=100)
self.canvas_1.setObjectName("canvas_1")
self.toolbar_1 = PamhyrPlotToolbar(
@@ -134,7 +128,9 @@ class InitialConditionsWindow(ASubMainWindow, ListedSubWindow):
self.plot_1 = PlotDKP(
canvas = self.canvas_1,
data = self._ics,
trad = self._trad,
toolbar = self.toolbar_1,
parent = self
)
self.plot_1.draw()
@@ -150,7 +146,9 @@ class InitialConditionsWindow(ASubMainWindow, ListedSubWindow):
self.plot_2 = PlotDischarge(
canvas = self.canvas_2,
data = self._ics,
trad = self._trad,
toolbar = self.toolbar_2,
parent = self
)
self.plot_2.draw()
@@ -167,11 +165,6 @@ class InitialConditionsWindow(ASubMainWindow, ListedSubWindow):
self.generate_discharge
)
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)
self._table.dataChanged.connect(self._update_plot)
def index_selected_row(self):
@@ -227,19 +220,19 @@ class InitialConditionsWindow(ASubMainWindow, ListedSubWindow):
self._table.move_down(row)
self._update_plot()
def copy(self):
def _copy(self):
logger.info("TODO: copy")
self._update_plot()
def paste(self):
def _paste(self):
logger.info("TODO: paste")
self._update_plot()
def undo(self):
def _undo(self):
self._table.undo()
self._update_plot()
def redo(self):
def _redo(self):
self._table.redo()
self._update_plot()
+18 -17
View File
@@ -18,23 +18,24 @@
from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate
table_headers = {
# "name": _translate("LateralContribution", "Name"),
"kp": _translate("LateralContribution", "KP (m)"),
# "speed": _translate("LateralContribution", "Speed (m/s)"),
"discharge": _translate("LateralContribution", "Discharge (m³/s)"),
"elevation": _translate("LateralContribution", "Elevation (m)"),
"height": _translate("LateralContribution", "Height (m)"),
# "comment": _translate("LateralContribution", "Comment"),
}
class ICTranslate(PamhyrTranslate):
def __init__(self):
super(ICTranslate, self).__init__()
def retranslate():
# table_headers["name"] = _translate("LateralContribution", "Name")
table_headers["kp"] = _translate("LateralContribution", "KP (m)")
# table_headers["speed"] = _translate("LateralContribution", "Speed (m/s)")
table_headers["discharge"] = _translate("LateralContribution", "Discharge (m³/s)")
table_headers["elevation"] = _translate("LateralContribution", "Elevation (m)")
table_headers["height"] = _translate("LateralContribution", "Height (m)")
# table_headers["comment"] = _translate("LateralContribution", "Comment")
self._dict["elevation"] = _translate("InitialCondition", "Elevation (m)")
self._dict["discharge"] = _translate("InitialCondition", "Discharge (m³/s)")
self._dict["kp"] = _translate("InitialCondition", "KP (m)")
self._sub_dict["table_headers"] = {
# "name": _translate("InitialCondition", "Name"),
"kp": _translate("InitialCondition", "KP (m)"),
# "speed": _translate("InitialCondition", "Speed (m/s)"),
"discharge": _translate("InitialCondition", "Discharge (m³/s)"),
"elevation": _translate("InitialCondition", "Elevation (m)"),
"height": _translate("InitialCondition", "Height (m)"),
# "comment": _translate("InitialCondition", "Comment"),
}
+13 -9
View File
@@ -19,7 +19,7 @@
from datetime import datetime
from tools import timer, trace
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
@@ -29,15 +29,19 @@ from View.LateralContribution.Edit.translate import *
_translate = QCoreApplication.translate
class Plot(APlot):
def __init__(self, canvas=None, data=None,
mode = "time", toolbar=None):
class Plot(PamhyrPlot):
def __init__(self, mode = "time", data=None,
canvas=None, trad=None, toolbar=None,
parent=None):
super(Plot, self).__init__(
canvas=canvas,
data=data,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = data,
toolbar = toolbar,
parent = parent
)
self._table_headers = self._trad.get_dict("table_headers")
self._mode = mode
def custom_ticks(self):
@@ -105,10 +109,10 @@ class Plot(APlot):
# Plot label
header = self.data.header
self.canvas.axes.set_xlabel(
table_headers[header[0]], color='black', fontsize=10
self._table_headers[header[0]], color='black', fontsize=10
)
self.canvas.axes.set_ylabel(
table_headers[header[1]], color='black', fontsize=10
self._table_headers[header[1]], color='black', fontsize=10
)
self.canvas.axes.autoscale_view(True, True, True)
@@ -22,8 +22,6 @@ from datetime import date, time, datetime, timedelta
from tools import trace, timer
from View.ASubWindow import ASubMainWindow, AWidget
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrTable import PamhyrTableModel
from PyQt5.QtCore import (
+40 -52
View File
@@ -18,8 +18,7 @@
from tools import timer, trace
from View.ASubWindow import ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from View.Tools.PamhyrDelegate import PamhyrExTimeDelegate
from PyQt5.QtGui import (
@@ -37,67 +36,60 @@ from PyQt5.QtWidgets import (
QHeaderView,
)
from View.Plot.MplCanvas import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.LateralContribution.translate import long_types
from View.LateralContribution.Edit.translate import table_headers, retranslate
from View.LateralContribution.Edit.translate import LCETranslate
from View.LateralContribution.Edit.Table import TableModel
from View.LateralContribution.Edit.Plot import Plot
_translate = QCoreApplication.translate
class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Edit lateral contribution",
data=None, study=None, parent=None):
self._data = data
self._study = study
self._title = title
class EditLateralContributionWindow(PamhyrWindow):
_pamhyr_ui = "EditLateralContribution"
_pamhyr_name = "Edit lateral contribution"
self.compute_title()
def __init__(self, data=None,
study=None, config=None,
parent=None):
self._data = data
trad = LCETranslate()
name = self._pamhyr_name
if self._data is not None:
edge_name = (self._data.edge.name if self._data.edge is not None
else _translate("LateralContribution", "Not associate"))
name = (
_translate("Edit lateral contribution", self._pamhyr_name) +
f" - {study.name} " +
f" - {self._data.name} ({self._data.id}) " +
f"({trad.get_dict('long_types')[self._data.lctype]} - {edge_name})"
)
super(EditLateralContributionWindow, self).__init__(
name=title, ui="EditLateralContribution", parent=parent
title = name,
study = study,
config = config,
trad = trad,
parent = parent
)
self.ui.setWindowTitle(self._title)
self.setup_sc()
self.setup_table()
self.setup_plot()
self.setup_connections()
def compute_title(self):
if self._data is not None:
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) +
f" - {self._study.name} " +
f" - {self._data.name} ({self._data.id}) " +
f"({long_types[self._data.lctype]} - {edge_name})"
)
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):
retranslate()
headers = {}
for h in self._data.header:
headers[h] = table_headers[h]
self._delegate_time = PamhyrExTimeDelegate(
data = self._data,
mode = self._study.time_system,
parent = self
)
headers = {}
table_headers = self._trad.get_dict("table_headers")
for h in self._data.header:
headers[h] = table_headers[h]
table = self.find(QTableView, "tableView")
self._table = TableModel(
table_view = table,
@@ -108,6 +100,7 @@ class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow):
},
data = self._data,
undo = self._undo_stack,
trad = self._trad,
opt_data = self._study.time_system
)
@@ -130,20 +123,16 @@ class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow):
data = self._data,
mode = self._study.time_system,
toolbar = self.toolbar,
trad = self._trad,
parent = self
)
self.plot.draw()
def setup_connections(self):
self.find(QAction, "action_add").triggered.connect(self.add)
self.find(QAction, "action_del").triggered.connect(self.delete)
self.find(QAction, "action_sort").triggered.connect(self.sort)
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)
self._table.dataChanged.connect(self.update)
def update(self):
@@ -199,8 +188,7 @@ class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow):
self._table.move_down(row)
self.plot.update()
def copy(self):
def _copy(self):
rows = self.index_selected_rows()
table = []
@@ -212,7 +200,7 @@ class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow):
self.copyTableIntoClipboard(table)
def paste(self):
def _paste(self):
header, data = self.parseClipboardTable()
if len(data) == 0:
@@ -226,10 +214,10 @@ class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow):
self._table.paste(row, header, data)
self.plot.update()
def undo(self):
def _undo(self):
self._table.undo()
self.plot.update()
def redo(self):
def _redo(self):
self._table.redo()
self.plot.update()
+14 -15
View File
@@ -18,21 +18,20 @@
from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
from View.LateralContribution.translate import LCTranslate
_translate = QCoreApplication.translate
table_headers = {
"x": _translate("LateralContribution", "X"),
"y": _translate("LateralContribution", "Y"),
"time": _translate("LateralContribution", "Time"),
"date": _translate("LateralContribution", "Date"),
"discharge": _translate("LateralContribution", "Discharge (m³/s)"),
"z": _translate("LateralContribution", "Z (m)")
}
class LCETranslate(LCTranslate):
def __init__(self):
super(LCETranslate, self).__init__()
def retranslate():
table_headers["x"] = _translate("LateralContribution", "X")
table_headers["y"] = _translate("LateralContribution", "Y")
table_headers["time"] = _translate("LateralContribution", "Time")
table_headers["date"] = _translate("LateralContribution", "Date")
table_headers["discharge"] = _translate("LateralContribution", "Discharge (m³/s)")
table_headers["z"] = _translate("LateralContribution", "Z (m)")
self._sub_dict["table_headers"] = {
"x": _translate("LateralContribution", "X"),
"y": _translate("LateralContribution", "Y"),
"time": _translate("LateralContribution", "Time"),
"date": _translate("LateralContribution", "Date"),
"discharge": _translate("LateralContribution", "Discharge (m³/s)"),
"z": _translate("LateralContribution", "Z (m)")
}
+7 -4
View File
@@ -46,22 +46,24 @@ from Model.LateralContribution.LateralContributionTypes import (
)
from View.Tools.PamhyrTable import PamhyrTableModel
from View.LateralContribution.translate import *
from View.LateralContribution.translate import LC_types
logger = logging.getLogger()
_translate = QCoreApplication.translate
class ComboBoxDelegate(QItemDelegate):
def __init__(self, data=None, mode="type", tab="", parent=None):
def __init__(self, data=None, mode="type", tab="", trad = None, parent=None):
super(ComboBoxDelegate, self).__init__(parent)
self._data = data
self._mode = mode
self._tab = tab
self._trad = trad
def createEditor(self, parent, option, index):
self.editor = QComboBox(parent)
long_types = self._trad.get_dict("long_types")
if self._mode == "type":
lst = list(
@@ -108,6 +110,7 @@ class TableModel(PamhyrTableModel):
def _setup_lst(self):
self._lst = self._data.lateral_contribution
self._tab = self._opt_data
self._long_types = self._trad.get_dict("long_types")
def rowCount(self, parent):
return self._lst.len(self._tab)
@@ -123,7 +126,7 @@ class TableModel(PamhyrTableModel):
return self._lst.get(self._tab, row).name
elif self._headers[column] == "type":
t = self._lst.get(self._tab, row).lctype
return long_types[t]
return self._long_types[t]
elif self._headers[column] == "edge":
n = self._lst.get(self._tab, row).edge
if n is None:
@@ -151,7 +154,7 @@ class TableModel(PamhyrTableModel):
)
)
elif self._headers[column] == "type":
key = next(k for k, v in long_types.items() if v == value)
key = next(k for k, v in self._long_types.items() if v == value)
self._undo.push(
SetTypeCommand(
self._lst, self._tab, row, LC_types[key]
+22 -34
View File
@@ -20,8 +20,7 @@ import logging
from tools import trace, timer
from View.ASubWindow import ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -54,46 +53,37 @@ from View.LateralContribution.Table import (
TableModel, ComboBoxDelegate
)
from View.Plot.MplCanvas import MplCanvas
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Geometry.PlotXY import PlotXY
from View.LateralContribution.translate import (
long_types, table_headers, LC_types,
retranslate,
LC_types, LCTranslate,
)
from View.LateralContribution.Edit.Window import EditLateralContributionWindow
_translate = QCoreApplication.translate
logger = logging.getLogger()
class LateralContributionWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Lateral contribution", study=None, parent=None):
self._title = title + " - " + study.name
class LateralContributionWindow(PamhyrWindow):
_pamhyr_ui = "LateralContributions"
_pamhyr_name = "Lateral contribution"
def __init__(self, study=None, config=None, parent=None):
name = self._pamhyr_name + " - " + study.name
super(LateralContributionWindow, self).__init__(
name=title, ui="LateralContributions", parent=parent
title = name,
study = study,
trad = LCTranslate(),
config = config,
parent=parent
)
self._study = study
self._lcs = self._study.river.lateral_contribution
self.setup_sc()
self.setup_table()
self.setup_graph()
self.setup_connections()
self.ui.setWindowTitle(self._title)
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):
retranslate()
self._table = {}
for t in ["liquid", "solid", "suspenssion"]:
@@ -101,19 +91,21 @@ class LateralContributionWindow(ASubMainWindow, ListedSubWindow):
data = self._study.river,
mode = "type",
tab = t,
trad = self._trad,
parent=self
)
self._delegate_edge = ComboBoxDelegate(
data = self._study.river,
mode = "edge",
tab = t,
trad = self._trad,
parent=self
)
table = self.find(QTableView, f"tableView_{t}")
self._table[t] = TableModel(
table_view = table,
table_headers = table_headers,
table_headers = self._trad.get_dict("table_headers"),
editable_headers = True,
delegates = {
"type": self._delegate_type,
@@ -121,6 +113,7 @@ class LateralContributionWindow(ASubMainWindow, ListedSubWindow):
},
data = self._study.river,
undo = self._undo_stack,
trad = self._trad,
opt_data = t,
)
table.setModel(self._table[t])
@@ -146,11 +139,6 @@ class LateralContributionWindow(ASubMainWindow, ListedSubWindow):
self.find(QAction, "action_edit").triggered.connect(self.edit)
self.find(QAction, "action_sort").triggered.connect(self.sort)
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)
for t in ["liquid", "solid", "suspenssion"]:
table = self.find(QTableView, f"tableView_{t}")
table.selectionModel()\
@@ -247,20 +235,20 @@ class LateralContributionWindow(ASubMainWindow, ListedSubWindow):
self._table[tab].move_down(row)
self._set_current_reach()
def copy(self):
def _copy(self):
logger.info("TODO: copy")
self._set_current_reach()
def paste(self):
def _paste(self):
logger.info("TODO: paste")
self._set_current_reach()
def undo(self):
def _undo(self):
tab = self.current_tab()
self._table[tab].undo()
self._set_current_reach()
def redo(self):
def _redo(self):
tab = self.current_tab()
self._table[tab].redo()
self._set_current_reach()
+19 -25
View File
@@ -18,27 +18,14 @@
from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
from Model.LateralContribution.LateralContributionTypes import (
NotDefined, LateralContrib, Rain, Evaporation,
)
_translate = QCoreApplication.translate
long_types = {
"ND": _translate("LateralContribution", "Not defined"),
"LC": _translate("LateralContribution", "Lateral contribution"),
"RA": _translate("LateralContribution", "Rain"),
"EV": _translate("LateralContribution", "Evaporation"),
}
table_headers = {
"name": _translate("LateralContribution", "Name"),
"type": _translate("LateralContribution", "Type"),
"edge": _translate("LateralContribution", "Reach"),
"begin_kp": _translate("LateralContribution", "Begin kp (m)"),
"end_kp": _translate("LateralContribution", "End kp (m)")
}
LC_types = {
"ND": NotDefined,
"LC": LateralContrib,
@@ -46,14 +33,21 @@ LC_types = {
"EV": Evaporation,
}
def retranslate():
table_headers["name"] = _translate("LateralContribution", "Name")
table_headers["type"] = _translate("LateralContribution", "Type")
table_headers["edge"] = _translate("LateralContribution", "Reach")
table_headers["begin_kp"] = _translate("LateralContribution", "Begin kp (m)")
table_headers["end_kp"] = _translate("LateralContribution", "End kp (m)")
class LCTranslate(PamhyrTranslate):
def __init__(self):
super(LCTranslate, self).__init__()
long_types["ND"] = _translate("LateralContribution", "Not defined")
long_types["LC"] = _translate("LateralContribution", "Lateral contribution")
long_types["RA"] = _translate("LateralContribution", "Rain")
long_types["EV"] = _translate("LateralContribution", "Evaporation")
self._sub_dict["long_types"] = {
"ND": _translate("LateralContribution", "Not defined"),
"LC": _translate("LateralContribution", "Lateral contribution"),
"RA": _translate("LateralContribution", "Rain"),
"EV": _translate("LateralContribution", "Evaporation"),
}
self._sub_dict["table_headers"] = {
"name": _translate("LateralContribution", "Name"),
"type": _translate("LateralContribution", "Type"),
"edge": _translate("LateralContribution", "Reach"),
"begin_kp": _translate("LateralContribution", "Begin kp (m)"),
"end_kp": _translate("LateralContribution", "End kp (m)")
}
+85 -53
View File
@@ -36,8 +36,8 @@ from PyQt5.QtWidgets import (
)
from PyQt5.uic import loadUi
from View.ASubWindow import WindowToolKit
from View.ListedSubWindow import ListedSubWindow
from View.Tools.ASubWindow import WindowToolKit
from View.Tools.ListedSubWindow import ListedSubWindow
from View.DummyWindow import DummyWindow
from View.Configure.Window import ConfigureWindow
@@ -56,6 +56,7 @@ 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.Doc.Window import DocWindow
from View.Debug.Window import ReplWindow
from Model.Study import Study
@@ -108,9 +109,10 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
self.conf = conf
# Model
self.model = None
self._study = None
# Results
self._last_solver = None
self._last_results = None
# UI
@@ -133,8 +135,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def set_title(self):
title = "(dbg) " if self.conf.debug else ""
if self.model is not None:
title += f"Pamhyr2 - {self.model.name}"
if self._study is not None:
title += f"Pamhyr2 - {self._study.name}"
self.setWindowTitle(title)
else:
title += "Pamhyr2"
@@ -150,6 +152,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns:
Nothing
"""
logger.debug(f"Set {action} to {enable}")
self.findChild(QAction, action).setEnabled(enable)
def setup_sc(self):
@@ -181,7 +184,12 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
"action_menu_sediment_layers": self.open_sediment_layers,
"action_menu_edit_reach_sediment_layers": self.open_reach_sediment_layers,
"action_menu_close": self.close_model,
"action_menu_results_last": self.open_last_results,
## Help
"action_menu_pamhyr_users_pdf": lambda: self.open_doc_user(ext="pdf"),
"action_menu_pamhyr_developers_pdf": lambda: self.open_doc_dev(ext="pdf"),
"action_menu_pamhyr_users_html": lambda: self.open_doc_user(ext="html"),
"action_menu_pamhyr_developers_html": lambda: self.open_doc_dev(ext="html"),
"action_menu_about": self.open_about,
# ToolBar action
"action_toolBar_quit": self.close,
@@ -217,7 +225,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
super(ApplicationWindow, self).changeEvent(event)
def close(self):
if self.model is not None and not self.model.is_saved:
if self._study is not None and not self._study.is_saved:
self._close_question = True
if self.dialog_close():
# PAMHYR is close correctly (no crash)
@@ -234,7 +242,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def closeEvent(self, event):
if not self._close_question:
if self.model is not None and not self.model.is_saved:
if self._study is not None and not self._study.is_saved:
if self.dialog_close(cancel = False):
# PAMHYR is close correctly (no crash)
self.conf.set_close_correctly()
@@ -292,16 +300,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
#########
def get_model(self):
return self.model
return self._study
def set_model(self, model):
self.model = model
self._study = model
self.update_enable_action()
self.conf.set_last_study(self.model.filename)
self.conf.set_last_study(self._study.filename)
self.set_title()
def close_model(self):
self.model = None
self._study = None
self.update_enable_action()
self.conf.set_close_correctly()
self.set_title()
@@ -315,7 +323,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns:
Nothing
"""
no_model = self.model is None
no_model = self._study is None
for action in no_model_action:
self.enable_actions(action, no_model)
@@ -326,9 +334,12 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
for action in model_action:
self.enable_actions(action, not no_model)
def set_results(self, results):
def set_results(self, solver, results):
self._last_solver = solver
self._last_results = results
self.enable_actions("action_menu_results_last", True)
############
# FEATURES #
############
@@ -343,7 +354,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Nothing
"""
self.set_model(Study.open(filename))
logger.info(f"Open Study - {self.model.name}")
logger.info(f"Open Study - {self._study.name}")
self.set_title()
def save_study(self):
@@ -355,22 +366,22 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns:
Nothing
"""
if self.model.filename is None or self.model.filename == "":
if self._study.filename is None or self._study.filename == "":
file_name, _ = QFileDialog.getSaveFileName(
self, "Save File",
"", "Pamhyr(*.pamhyr)"
)
if file_name.rsplit(".", 1)[-1] == "pamhyr":
self.model.filename = file_name
self._study.filename = file_name
else:
self.model.filename = file_name + ".pamhyr"
self._study.filename = file_name + ".pamhyr"
if self.model.is_saved:
if self._study.is_saved:
return
logger.info("Save...")
self.model.save()
self._study.save()
def save_as_study(self):
"""Save current study as new file
@@ -387,11 +398,11 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
)
if file_name[-4:] == ".pamhyr":
self.model.filename = file_name
self._study.filename = file_name
else:
self.model.filename = file_name + ".pamhyr"
self._study.filename = file_name + ".pamhyr"
self.model.save()
self._study.save()
##################
# MSG AND DIALOG #
@@ -457,7 +468,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns:
Nothing
"""
self.config = ConfigureWindow(conf=self.conf, parent=self)
self.config = ConfigureWindow(config=self.conf, parent=self)
self.config.show()
def open_about(self):
@@ -477,7 +488,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns:
Nothing
"""
if self.model is None:
if self._study is None:
dialog = QFileDialog(self)
dialog.setFileMode(QFileDialog.FileMode.ExistingFile)
dialog.setDefaultSuffix(".pamhyr")
@@ -495,7 +506,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns:
Nothing
"""
if self.model is None:
if self._study is None:
self.new_study = NewStudyWindow(parent=self)
self.new_study.show()
@@ -505,8 +516,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns:
Nothing
"""
if not self.model is None:
self.new_study = NewStudyWindow(study=self.model, parent=self)
if not self._study is None:
self.new_study = NewStudyWindow(study=self._study, parent=self)
self.new_study.show()
def open_network(self):
@@ -515,9 +526,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns:
Nothing
"""
if self.model is not None:
if self._study is not None:
if not self.sub_win_exists("River network"):
self.network = NetworkWindow(model=self.model, parent=self)
self.network = NetworkWindow(study=self._study, parent=self)
self.network.show()
else:
self.network.activateWindow()
@@ -528,14 +539,14 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns:
Nothing
"""
if (self.model is not None and self.model.river.has_current_reach()):
if (self._study is not None and self._study.river.has_current_reach()):
geometry = self.sub_win_filter_first(
"Geometry",
contain = [self.model.river.current_reach().name]
contain = [self._study.river.current_reach().name]
)
if geometry is None:
geometry = GeometryWindow(model=self.model, parent=self)
geometry = GeometryWindow(study=self._study, config=self.conf, parent=self)
geometry.show()
else:
geometry.activateWindow()
@@ -549,7 +560,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
)
if bound is None:
bound = BoundaryConditionWindow(study = self.model, parent = self)
bound = BoundaryConditionWindow(study = self._study, parent = self)
bound.show()
else:
bound.activateWindow()
@@ -561,7 +572,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
)
if lateral is None:
lateral = LateralContributionWindow(study = self.model, parent = self)
lateral = LateralContributionWindow(study = self._study, parent = self)
lateral.show()
else:
lateral.activateWindow()
@@ -574,7 +585,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if strick is None:
strick = StricklersWindow(
study = self.model,
study = self._study,
config = self.conf,
parent = self
)
@@ -583,17 +594,17 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
strick.activateWindow()
def open_frictions(self):
if (self.model is not None and
self.model.river.has_current_reach()):
if (self._study is not None and
self._study.river.has_current_reach()):
frictions = self.sub_win_filter_first(
"Frictions",
contain = [self.model.river.current_reach().name]
contain = [self._study.river.current_reach().name]
)
if frictions is None:
frictions = FrictionsWindow(
study = self.model,
study = self._study,
parent = self
)
frictions.show()
@@ -603,15 +614,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
self.msg_select_reach()
def open_initial_conditions(self):
if self.model.river.has_current_reach():
if self._study.river.has_current_reach():
initial = self.sub_win_filter_first(
"Initial condition",
contain = [self.model.river.current_reach().name]
contain = [self._study.river.current_reach().name]
)
if initial is None:
initial = InitialConditionsWindow(
study = self.model,
study = self._study,
config = self.conf,
parent = self
)
initial.show()
@@ -628,7 +640,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if params is None:
params = SolverParametersWindow(
study = self.model,
study = self._study,
parent = self
)
params.show()
@@ -637,31 +649,31 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def open_sediment_layers(self):
sl = SedimentLayersWindow(
study = self.model,
study = self._study,
parent = self
)
sl.show()
def open_reach_sediment_layers(self):
sl = ReachSedimentLayersWindow(
study = self.model,
study = self._study,
parent = self
)
sl.show()
def run_solver(self):
if self.model is None:
if self._study is None:
return
run = SelectSolverWindow(
study = self.model,
study = self._study,
config = self.conf,
parent = self
)
if run.exec():
solver = run.solver
check = CheckListWindow(
study = self.model,
study = self._study,
config = self.conf,
solver = solver,
parent = self
@@ -670,7 +682,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def solver_log(self, solver):
sol = SolverLogWindow(
study = self.model,
study = self._study,
config = self.conf,
solver = solver,
parent = self
@@ -694,7 +706,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if res is None:
res = ResultsWindow(
study = self.model,
study = self._study,
solver = solver,
results = results,
parent = self
@@ -703,24 +715,44 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
else:
res.activateWindow()
def open_last_results(self):
if self._last_solver is None or self._last_results is None:
return
self.open_solver_results(self._last_solver, self._last_results)
def open_doc(self, filename):
doc = DocWindow(
filename = filename,
parent = self
)
doc.show()
def open_doc_user(self, ext="pdf"):
self.open_doc(f"Pamhyr2-users.{ext}")
def open_doc_dev(self, ext="pdf"):
self.open_doc(f"Pamhyr2-dev.{ext}")
#########
# DEBUG #
#########
def open_debug(self):
repl = ReplWindow(
study = self.model,
study = self._study,
config = self.conf,
parent = self
)
repl.show()
def open_sqlite(self):
if self.model is None:
if self._study is None:
logger.debug("No study open for sql debuging...")
return
file = self.model.filename
file = self._study.filename
_ = subprocess.Popen(
f"sqlitebrowser {file}",
shell=True
-1
View File
@@ -22,7 +22,6 @@ import traceback
from Model.Network.Node import Node
from Model.Network.Edge import Edge
from Model.Network.Graph import Graph
from View.ASubWindow import ASubWindow
from View.Network.GraphWidget import GraphWidget
from View.Network.UndoCommand import *
from View.Tools.PamhyrTable import PamhyrTableModel
+26 -33
View File
@@ -16,6 +16,8 @@
# -*- coding: utf-8 -*-
import logging
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import (
@@ -36,55 +38,47 @@ from PyQt5.QtWidgets import (
from Model.River import RiverNode, RiverReach, River
from View.ASubWindow import ASubMainWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from View.Network.GraphWidget import GraphWidget
from View.Network.UndoCommand import *
from View.Network.translate import (
table_headers_node, table_headers_edge,
retranslate,
)
from View.Network.translate import NetworkTranslate
from View.Network.Table import (
ComboBoxDelegate, NodeTableModel, EdgeTableModel,
)
logger = logging.getLogger()
_translate = QCoreApplication.translate
class NetworkWindow(ASubMainWindow):
def __init__(self, model=None, title="River network", parent=None):
self._title = title
self._model = model
self._graph = self._model.river
self.setup_title()
class NetworkWindow(PamhyrWindow):
_pamhyr_ui = "Network"
_pamhyr_name = "River network"
def __init__(self, study=None, config=None, parent=None):
super(NetworkWindow, self).__init__(
name=title, ui="Network", parent=parent
title = self._pamhyr_name + " - " + study.name,
study = study,
config = config,
trad = NetworkTranslate(),
options = ['undo'],
parent=parent,
)
self.ui.setWindowTitle(self._title)
self.setup_sc()
self._graph = study.river
self._table_headers_node = self._trad.get_dict("table_headers_node")
self._table_headers_edge = self._trad.get_dict("table_headers_edge")
self.setup_graph()
self.setup_table()
self.setup_connections()
def setup_title(self):
self._title = self._title + " - " + self._model.name
def setup_sc(self):
self._undo_stack = QUndoStack()
self.undo_sc = QShortcut(QKeySequence.Undo, self)
self.redo_sc = QShortcut(QKeySequence.Redo, self)
def setup_table(self):
retranslate()
# Nodes table
table = self.find(QTableView, "tableView_nodes")
self._nodes_model = NodeTableModel(
table_view = table,
table_headers = table_headers_node,
table_headers = self._table_headers_node,
editable_headers = ["name"],
data = self._graph,
undo = self._undo_stack,
@@ -103,7 +97,7 @@ class NetworkWindow(ASubMainWindow):
self._reachs_model = EdgeTableModel(
table_view = table,
table_headers = table_headers_edge,
table_headers = self._table_headers_edge,
editable_headers = ["name", "node1", "node2"],
delegates = {
"node1": self.delegate_combobox,
@@ -143,9 +137,6 @@ class NetworkWindow(ASubMainWindow):
self.clicked_del
)
self.undo_sc.activated.connect(self.undo)
self.redo_sc.activated.connect(self.redo)
def clicked_add(self):
if self.get_action_checkable("action_toolBar_add"):
self.set_action_checkable("action_toolBar_del", False)
@@ -166,13 +157,15 @@ class NetworkWindow(ASubMainWindow):
if key == Qt.Key_Escape:
self._graph_widget.reset_selection
def undo(self):
# Redefine undo/redo method
def _undo(self):
self._undo_stack.undo()
self._reachs_model.update()
self._nodes_model.update()
self._graph_widget.display_update()
def redo(self):
def _redo(self):
self._undo_stack.redo()
self._reachs_model.update()
self._nodes_model.update()
+14 -16
View File
@@ -18,23 +18,21 @@
from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate
table_headers_node = {
"name": _translate("Network", "Name"),
"type": _translate("Network", "Type"),
}
class NetworkTranslate(PamhyrTranslate):
def __init__(self):
super(NetworkTranslate, self).__init__()
table_headers_edge = {
"name": _translate("Network", "Name"),
"node1": _translate("Network", "Source node"),
"node2": _translate("Network", "Destination node"),
}
self._sub_dict["table_headers_node"] = {
"name": _translate("Network", "Name"),
"type": _translate("Network", "Type"),
}
def retranslate():
table_headers_node["name"] = _translate("Network", "Name")
table_headers_node["type"] = _translate("Network", "Type")
table_headers_edge["name"] = _translate("Network", "Name")
table_headers_edge["node1"] = _translate("Network", "Source node")
table_headers_edge["node2"] = _translate("Network", "Destination node")
self._sub_dict["table_headers_edge"] = {
"name": _translate("Network", "Name"),
"node1": _translate("Network", "Source node"),
"node2": _translate("Network", "Destination node"),
}
+10 -8
View File
@@ -17,7 +17,7 @@
# -*- coding: utf-8 -*-
from tools import timer
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
@@ -25,14 +25,16 @@ from PyQt5.QtCore import (
_translate = QCoreApplication.translate
class PlotAC(APlot):
def __init__(self, canvas=None, results=None,
reach_id=0, profile_id=0,
toolbar=None):
class PlotAC(PamhyrPlot):
def __init__(self, canvas=None, trad=None, toolbar=None,
results=None, reach_id=0, profile_id=0,
parent=None):
super(PlotAC, self).__init__(
canvas=canvas,
data=results,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = results,
toolbar = toolbar,
parent = parent
)
self._current_timestamp = max(results.get("timestamps"))
+10 -8
View File
@@ -22,7 +22,7 @@ from functools import reduce
from datetime import datetime
from tools import timer, trace
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
@@ -32,14 +32,16 @@ _translate = QCoreApplication.translate
logger = logging.getLogger()
class PlotH(APlot):
def __init__(self, canvas=None, results=None,
reach_id=0, profile_id=0,
toolbar=None):
class PlotH(PamhyrPlot):
def __init__(self, canvas=None, trad=None, toolbar=None,
results=None, reach_id=0, profile_id=0,
parent=None):
super(PlotH, self).__init__(
canvas=canvas,
data=results,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = results,
toolbar = toolbar,
parent = parent
)
self._mode = "time"
+10 -8
View File
@@ -17,7 +17,7 @@
# -*- coding: utf-8 -*-
from tools import timer
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
@@ -25,14 +25,16 @@ from PyQt5.QtCore import (
_translate = QCoreApplication.translate
class PlotKPC(APlot):
def __init__(self, canvas=None, results=None,
reach_id=0, profile_id=0,
toolbar=None):
class PlotKPC(PamhyrPlot):
def __init__(self, canvas=None, trad=None, toolbar=None,
results=None, reach_id=0, profile_id=0,
parent=None):
super(PlotKPC, self).__init__(
canvas=canvas,
data=results,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = results,
toolbar = toolbar,
parent = parent
)
self._current_timestamp = max(results.get("timestamps"))
+10 -8
View File
@@ -5,7 +5,7 @@ import logging
from functools import reduce
from tools import timer
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
@@ -15,14 +15,16 @@ _translate = QCoreApplication.translate
logger = logging.getLogger()
class PlotSedProfile(APlot):
def __init__(self, canvas=None, study=None, results=None,
reach_id=0, profile_id=0,
toolbar=None):
class PlotSedProfile(PamhyrPlot):
def __init__(self, canvas=None, trad=None, toolbar=None,
results=None, reach_id=0, profile_id=0,
parent=None):
super(PlotSedProfile, self).__init__(
canvas=canvas,
data=study,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = results,
toolbar = toolbar,
parent = parent
)
self._results = results
+10 -8
View File
@@ -5,7 +5,7 @@ import logging
from functools import reduce
from tools import timer
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
@@ -15,14 +15,16 @@ _translate = QCoreApplication.translate
logger = logging.getLogger()
class PlotSedReach(APlot):
def __init__(self, canvas=None, study=None, results=None,
reach_id=0, profile_id=0,
toolbar=None):
class PlotSedReach(PamhyrPlot):
def __init__(self, canvas=None, trad=None, toolbar=None,
results=None, reach_id=0, profile_id=0,
parent=None):
super(PlotSedReach, self).__init__(
canvas=canvas,
data=study,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = results,
toolbar = toolbar,
parent = parent
)
self._results = results
+10 -8
View File
@@ -21,7 +21,7 @@ import logging
from functools import reduce
from tools import timer, trace
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
@@ -31,14 +31,16 @@ _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):
class PlotXY(PamhyrPlot):
def __init__(self, canvas=None, trad=None, toolbar=None,
results=None, reach_id=0, profile_id=0,
display_current=True, parent=None):
super(PlotXY, self).__init__(
canvas=canvas,
data=results,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = results,
toolbar = toolbar,
parent = parent
)
self.display_current = display_current
+20 -45
View File
@@ -34,6 +34,7 @@ from PyQt5.QtWidgets import (
QComboBox,
)
from View.Tools.PamhyrTable import PamhyrTableModel
from View.Results.translate import *
logger = logging.getLogger()
@@ -41,33 +42,16 @@ logger = logging.getLogger()
_translate = QCoreApplication.translate
class TableModel(QAbstractTableModel):
def __init__(self, results = None, study = None, mode = None, undo=None):
super(QAbstractTableModel, self).__init__()
class TableModel(PamhyrTableModel):
def _setup_lst(self):
_river = self._data.river
if self._opt_data == "reach":
self._lst = _river.reachs
else:
self._lst = _river.reach(0).profiles
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 __init__(self, **kwargs):
super(TableModel, self).__init__(**kwargs)
def data(self, index, role=Qt.DisplayRole):
if role != Qt.ItemDataRole.DisplayRole:
@@ -76,32 +60,23 @@ class TableModel(QAbstractTableModel):
row = index.row()
column = index.column()
if self._mode == "reach":
if self._opt_data == "reach":
if self._headers[column] == "name":
v = self._results.river.reach(row).name
v = self._lst[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
v = self._lst[row].name
return str(v)
elif self._headers[column] == "kp":
v = current_reach.profile(row).kp
v = self._lst[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
def update(self, reach):
_river = self._data.river
if self._opt_data == "reach":
self._lst = _river.reachs
else:
self._lst = _river.reach(reach).profiles
+34 -59
View File
@@ -21,8 +21,7 @@ from datetime import datetime
from tools import trace, timer
from View.ASubWindow import ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -42,8 +41,8 @@ from PyQt5.QtWidgets import (
QSlider, QLabel,
)
from View.Plot.MplCanvas import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.Results.PlotXY import PlotXY
from View.Results.PlotAC import PlotAC
@@ -53,74 +52,57 @@ from View.Results.PlotSedReach import PlotSedReach
from View.Results.PlotSedProfile import PlotSedProfile
from View.Results.Table import TableModel
from View.Results.translate import (
table_headers_reach, table_headers_profile,
retranslate,
)
from View.Results.translate import ResultsTranslate
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,
class ResultsWindow(PamhyrWindow):
_pamhyr_ui = "Results"
_pamhyr_name = "Results"
def __init__(self, study=None, config=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_statusbar()
self.setup_connections()
self.ui.setWindowTitle(self._title)
def setup_title(self, title):
self._title = (
title + " - "
+ self._study.name + " - "
name = (
self._pamhyr_name + " - "
+ study.name + " - "
+ self._solver.name + " - "
+ self._results.date
)
def setup_sc(self):
self._undo_stack = QUndoStack()
super(ResultsWindow, self).__init__(
title = name,
study = study,
config = config,
trad = ResultsTranslate(),
parent=parent
)
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)
self.setup_table()
self.setup_plot()
self.setup_slider()
self.setup_statusbar()
self.setup_connections()
def setup_table(self):
retranslate()
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,
table_view = table,
table_headers = self._trad.get_dict(f"table_headers_{t}"),
data = self._results,
undo = self._undo_stack,
opt_data = t
)
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")
@@ -132,7 +114,7 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
self._slider_time.setMaximum(len(self._timestamps) - 1)
self._slider_time.setValue(len(self._timestamps) - 1)
def setup_graph(self):
def setup_plot(self):
self.canvas = MplCanvas(width=5, height=4, dpi=100)
self.canvas.setObjectName("canvas")
self.toolbar = PamhyrPlotToolbar(
@@ -219,7 +201,6 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
self.plot_sed_reach = PlotSedReach(
canvas = self.canvas_5,
results = self._results,
study = self._study,
reach_id = 0,
profile_id = 0,
toolbar = self.toolbar_5
@@ -239,7 +220,6 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
self.plot_sed_profile = PlotSedProfile(
canvas = self.canvas_6,
results = self._results,
study = self._study,
reach_id = 0,
profile_id = 0,
toolbar = self.toolbar_6
@@ -289,11 +269,6 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
self._status_label.setText(txt)
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,
@@ -411,14 +386,14 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
timestamp = self._timestamps[self._slider_time.value()]
self.update(timestamp = timestamp)
def copy(self):
def _copy(self):
logger.info("TODO: copy")
def paste(self):
def _paste(self):
logger.info("TODO: paste")
def undo(self):
def _undo(self):
self._table.undo()
def redo(self):
def _redo(self):
self._table.redo()
+12 -12
View File
@@ -18,19 +18,19 @@
from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate
table_headers_reach = {
"name": _translate("Results", "Reach name"),
}
class ResultsTranslate(PamhyrTranslate):
def __init__(self):
super(ResultsTranslate, self).__init__()
table_headers_profile = {
"name": _translate("Results", "Name"),
"kp": _translate("Results", "KP (m)"),
}
self._sub_dict["table_headers_reach"] = {
"name": _translate("Results", "Reach name"),
}
def retranslate():
table_headers_reach["name"] = _translate("Results", "Reach name")
table_headers_profile["name"] = _translate("Results", "Name")
table_headers_profile["kp"] = _translate("Results", "KP (m)")
self._sub_dict["table_headers_profile"] = {
"name": _translate("Results", "Name"),
"kp": _translate("Results", "KP (m)"),
}
+11 -13
View File
@@ -22,8 +22,7 @@ import os
from queue import Queue
from tools import trace, timer
from View.ASubWindow import ASubWindow, ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrDialog, PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -45,24 +44,23 @@ from PyQt5.QtWidgets import (
_translate = QCoreApplication.translate
class SolverLogFileWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Solver logs",
file_name = None,
class SolverLogFileWindow(PamhyrWindow):
_pamhyr_ui = "SolverLogFile"
_pamhyr_name = "Solver logs"
def __init__(self, file_name = None,
study=None, config=None,
solver=None, parent=None):
self._title = title
self._parent = parent
self._study = study
self._config = config
self._solver = solver
self._file_name = file_name
super(SolverLogFileWindow, self).__init__(
name=self._title, ui="SolverLogFile", parent=parent
title = self._pamhyr_name,
study = study,
config = config,
options = [],
parent = parent
)
self.ui.setWindowTitle(self._title)
self.setup_action()
self.setup_connections()
+26 -23
View File
@@ -23,8 +23,7 @@ import tempfile
from queue import Queue
from tools import trace, timer
from View.ASubWindow import ASubWindow, ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrDialog, PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -56,20 +55,21 @@ _translate = QCoreApplication.translate
logger = logging.getLogger()
class SelectSolverWindow(ASubWindow, ListedSubWindow):
def __init__(self, title="Select solver",
study=None, config=None,
parent=None):
self._title = title
class SelectSolverWindow(PamhyrDialog):
_pamhyr_ui = "SelectSolver"
_pamhyr_name = "Select solver"
self._study = study
self._config = config
def __init__(self, study=None, config=None,
parent=None):
self._solver = None
super(SelectSolverWindow, self).__init__(
name=self._title, ui="SelectSolver", parent=parent
title = self._pamhyr_name,
study = study,
config = config,
options = [],
parent = parent
)
self.ui.setWindowTitle(self._title)
self.setup_combobox()
self.setup_connections()
@@ -101,24 +101,22 @@ class SelectSolverWindow(ASubWindow, ListedSubWindow):
super(SelectSolverWindow, self).accept()
class SolverLogWindow(PamhyrWindow):
_pamhyr_ui = "SolverLog"
_pamhyr_name = "Solver Log"
class SolverLogWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Solver logs",
study=None, config=None,
def __init__(self, study=None, config=None,
solver=None, parent=None):
self._title = title
self._parent = parent
self._study = study
self._config = config
self._solver = solver
self._results = None
super(SolverLogWindow, self).__init__(
name=self._title, ui="SolverLog", parent=parent
title = self._pamhyr_name,
study = study,
config = config,
options = [],
parent = parent
)
self.ui.setWindowTitle(self._title)
self.setup_action()
self.setup_alarm()
@@ -206,6 +204,11 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
if self._solver.log_file() != "":
self.find(QAction, "action_log_file").setEnabled(True)
# Get results
if self._results is None:
self._results = self._solver.results(self._study, self._workdir, qlog = self._output)
self._parent.set_results(self._solver, self._results)
while self._output.qsize() != 0:
s = self._output.get()
if type(s) is str and "[ERROR]" in s:
@@ -258,7 +261,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
if self._results is None:
self._results = self._solver.results(self._study, self._workdir, qlog = self._output)
self._parent.set_results(self._results)
self._parent.set_results(self._solver, self._results)
self._parent.open_solver_results(self._solver, self._results)
def log_file(self):
+10 -18
View File
@@ -5,23 +5,19 @@ import logging
from functools import reduce
from tools import timer
from View.Plot.APlot import APlot
from PyQt5.QtCore import (
QCoreApplication
)
_translate = QCoreApplication.translate
from View.Tools.PamhyrPlot import PamhyrPlot
logger = logging.getLogger()
class Plot(APlot):
def __init__(self, canvas=None, data=None, toolbar=None,
display_current=True):
class Plot(PamhyrPlot):
def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
display_current=True, parent=None):
super(Plot, self).__init__(
canvas=canvas,
data=data,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = data,
toolbar = toolbar,
parent = parent
)
self._display_current = display_current
@@ -34,13 +30,9 @@ class Plot(APlot):
self.canvas.axes.cla()
self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
# self.canvas.axes.set_xlabel(
# _translate("MainWindow_reach", "X (m)"),
# color='green', fontsize=12
# )
self.canvas.axes.axes.get_xaxis().set_visible(False)
self.canvas.axes.set_ylabel(
_translate("MainWindow_reach", "Height (m)"),
self._trad["height"],
color='green', fontsize=12
)
+20 -44
View File
@@ -15,32 +15,14 @@ from PyQt5.QtWidgets import (
QComboBox,
)
from View.Tools.PamhyrTable import PamhyrTableModel
from View.SedimentLayers.Edit.UndoCommand import *
from View.SedimentLayers.Edit.translate import *
_translate = QCoreApplication.translate
class TableModel(QAbstractTableModel):
def __init__(self, study=None, sl=None, undo=None):
super(QAbstractTableModel, self).__init__()
self._headers = list(table_headers.keys())
self._study = study
self._undo = undo
self._sl = sl
def flags(self, index):
options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
options |= Qt.ItemIsEditable
return options
def rowCount(self, parent):
return len(self._sl)
def columnCount(self, parent):
return len(self._headers)
class TableModel(PamhyrTableModel):
def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole:
return QVariant()
@@ -49,23 +31,17 @@ class TableModel(QAbstractTableModel):
column = index.column()
if self._headers[column] == "name":
return self._sl.get(row).name
return self._data.get(row).name
elif self._headers[column] == "type":
return self._sl.get(row).type
return self._data.get(row).type
elif self._headers[column] == "height":
return self._sl.get(row).height
return self._data.get(row).height
elif self._headers[column] == "d50":
return self._sl.get(row).d50
return self._data.get(row).d50
elif self._headers[column] == "sigma":
return self._sl.get(row).sigma
return self._data.get(row).sigma
elif self._headers[column] == "critical_constraint":
return self._sl.get(row).critical_constraint
return QVariant()
def headerData(self, friction, orientation, role):
if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
return table_headers[self._headers[friction]]
return self._data.get(row).critical_constraint
return QVariant()
@@ -79,37 +55,37 @@ class TableModel(QAbstractTableModel):
if self._headers[column] == "name":
self._undo.push(
SetNameCommand(
self._sl, row, value
self._data, row, value
)
)
if self._headers[column] == "type":
self._undo.push(
SetTypeCommand(
self._sl, row, value
self._data, row, value
)
)
if self._headers[column] == "height":
self._undo.push(
SetHeightCommand(
self._sl, row, value
self._data, row, value
)
)
if self._headers[column] == "d50":
self._undo.push(
SetD50Command(
self._sl, row, value
self._data, row, value
)
)
if self._headers[column] == "sigma":
self._undo.push(
SetSigmaCommand(
self._sl, row, value
self._data, row, value
)
)
if self._headers[column] == "critical_constraint":
self._undo.push(
SetCriticalConstraintCommand(
self._sl, row, value
self._data, row, value
)
)
@@ -121,7 +97,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
AddCommand(
self._sl, row
self._data, row
)
)
@@ -133,7 +109,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
DelCommand(
self._sl, rows
self._data, rows
)
)
@@ -150,7 +126,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
MoveCommand(
self._sl, "up", row
self._data, "up", row
)
)
@@ -158,7 +134,7 @@ class TableModel(QAbstractTableModel):
self.layoutChanged.emit()
def move_down(self, row, parent=QModelIndex()):
if row + 1 >= len(self._sl):
if row + 1 >= len(self._data):
return
target = row
@@ -167,7 +143,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
MoveCommand(
self._sl, "down", row
self._data, "down", row
)
)
+33 -46
View File
@@ -20,8 +20,7 @@ import logging
from tools import trace, timer
from View.ASubWindow import ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -40,66 +39,58 @@ from PyQt5.QtWidgets import (
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
)
from View.Plot.MplCanvas import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.SedimentLayers.Edit.UndoCommand import *
from View.SedimentLayers.Edit.Table import *
from View.SedimentLayers.Edit.Plot import Plot
from View.SedimentLayers.Edit.translate import table_headers, retranslate
from View.SedimentLayers.Edit.translate import SedimentEditTranslate
_translate = QCoreApplication.translate
logger = logging.getLogger()
class EditSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Edit Sediment Layers",
study=None, sl=None, parent=None):
self._study = study
class EditSedimentLayersWindow(PamhyrWindow):
_pamhyr_ui = "EditSedimentLayers"
_pamhyr_name = "Edit Sediment Layers"
def __init__(self, study=None, config = None,
sl=None, parent=None):
self._sl = sl
self.setup_title(title)
super(EditSedimentLayersWindow, self).__init__(
name=self._title, ui="EditSedimentLayers", parent=parent
)
self.setup_sc()
self.setup_table()
self.setup_graph()
self.setup_connections()
self.ui.setWindowTitle(self._title)
def setup_title(self, title):
name = self._sl.name
if name == "":
name = _translate("SedimentLayers", "(no name)")
self._title = (
title + " - " + self._study.name + " - " + name
name = (
self._pamhyr_name + " - " + study.name + " - " + name
)
def setup_sc(self):
self._undo_stack = QUndoStack()
super(EditSedimentLayersWindow, self).__init__(
title = name,
study = study,
config = config,
trad = SedimentEditTranslate(),
parent = parent
)
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)
self.setup_table()
self.setup_graph()
self.setup_connections()
def setup_table(self):
retranslate()
self._table = {}
table_headers = self._trad.get_dict("table_headers")
table = self.find(QTableView, f"tableView")
self._table = TableModel(
study = self._study,
sl = self._sl,
table_view = table,
table_headers = table_headers,
editable_headers = list(table_headers),
data = self._sl,
trad = self._trad,
undo = self._undo_stack,
)
table.setModel(self._table)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
@@ -120,6 +111,7 @@ class EditSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
canvas = self.canvas,
data = self._sl,
toolbar = self.toolbar,
trad = self._trad,
display_current = False
)
self.plot.draw()
@@ -131,11 +123,6 @@ class EditSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
self.find(QAction, "action_move_up").triggered.connect(self.move_up)
self.find(QAction, "action_move_down").triggered.connect(self.move_down)
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)
self._table.dataChanged.connect(self._set_plot)
self._table.layoutChanged.connect(self._set_plot)
@@ -179,14 +166,14 @@ class EditSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
self._table.move_down(rows[0])
def copy(self):
def _copy(self):
logger.info("TODO: copy")
def paste(self):
def _paste(self):
logger.info("TODO: paste")
def undo(self):
def _undo(self):
self._table.undo()
def redo(self):
def _redo(self):
self._table.redo()
+15 -15
View File
@@ -2,21 +2,21 @@
from PyQt5.QtCore import QCoreApplication
from View.SedimentLayers.translate import SedimentTranslate
_translate = QCoreApplication.translate
table_headers = {
"name": _translate("SedimentLayers", "Name"),
# "type": _translate("SedimentLayers", "Type"),
"height": _translate("SedimentLayers", "Height"),
"d50": _translate("SedimentLayers", "D50"),
"sigma": _translate("SedimentLayers", "Sigma"),
"critical_constraint": _translate("SedimentLayers", "Critical constraint"),
}
class SedimentEditTranslate(SedimentTranslate):
def __init__(self):
super(SedimentEditTranslate, self).__init__()
def retranslate():
table_headers["name"] = _translate("SedimentLayers", "Name")
# table_headers["type"] = _translate("SedimentLayers", "Type")
table_headers["height"] = _translate("SedimentLayers", "Height")
table_headers["d50"] = _translate("SedimentLayers", "D50")
table_headers["sigma"] = _translate("SedimentLayers", "Sigma")
table_headers["critical_constraint"] = _translate("SedimentLayers", "Critical constraint")
self._dict["height"] = _translate("SedimentLayers", "Height (m)"),
self._sub_dict["table_headers"] = {
"name": _translate("SedimentLayers", "Name"),
# "type": _translate("SedimentLayers", "Type"),
"height": _translate("SedimentLayers", "Height"),
"d50": _translate("SedimentLayers", "D50"),
"sigma": _translate("SedimentLayers", "Sigma"),
"critical_constraint": _translate("SedimentLayers", "Critical constraint"),
}
+12 -9
View File
@@ -5,7 +5,7 @@ import logging
from functools import reduce
from tools import timer
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
@@ -15,13 +15,16 @@ _translate = QCoreApplication.translate
logger = logging.getLogger()
class Plot(APlot):
def __init__(self, canvas=None, data=None, toolbar=None,
display_current=True):
class Plot(PamhyrPlot):
def __init__(self, data=None, display_current=True,
canvas=None, trad=None, toolbar=None,
parent=None):
super(Plot, self).__init__(
canvas=canvas,
data=data,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = data,
toolbar = toolbar,
parent = parent
)
self._display_current = display_current
@@ -41,11 +44,11 @@ class Plot(APlot):
return
self.canvas.axes.set_xlabel(
_translate("MainWindow_reach", "Kp (m)"),
self._trad["kp"],
color='green', fontsize=12
)
self.canvas.axes.set_ylabel(
_translate("MainWindow_reach", "Height (m)"),
self._trad["height"],
color='green', fontsize=12
)
+10 -7
View File
@@ -5,7 +5,7 @@ import logging
from functools import reduce
from tools import timer
from View.Plot.APlot import APlot
from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
@@ -15,13 +15,16 @@ _translate = QCoreApplication.translate
logger = logging.getLogger()
class Plot(APlot):
def __init__(self, canvas=None, data=None, toolbar=None,
display_current=True):
class Plot(PamhyrPlot):
def __init__(self, data=None, display_current=True,
canvas=None, trad=None, toolbar=None,
parent=None):
super(Plot, self).__init__(
canvas=canvas,
data=data,
toolbar=toolbar
canvas = canvas,
trad = trad,
data = data,
toolbar = toolbar,
parent = parent
)
self._display_current = display_current
+12 -34
View File
@@ -20,6 +20,8 @@ from PyQt5.QtWidgets import (
from View.SedimentLayers.Reach.Profile.UndoCommand import *
from View.SedimentLayers.Reach.Profile.translate import *
from View.Tools.PamhyrTable import PamhyrTableModel
_translate = QCoreApplication.translate
logger = logging.getLogger()
@@ -67,28 +69,10 @@ class ComboBoxDelegate(QItemDelegate):
self.commitData.emit(self.sender())
class TableModel(QAbstractTableModel):
def __init__(self, study=None, profile=None, undo=None):
super(QAbstractTableModel, self).__init__()
self._headers = list(table_headers.keys())
self._study = study
self._undo = undo
self._profile = profile
def flags(self, index):
column = index.column()
options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
if self._headers[column] == "sl":
options |= Qt.ItemIsEditable
return options
def rowCount(self, parent):
return self._profile.number_points
def columnCount(self, parent):
return len(self._headers)
class TableModel(PamhyrTableModel):
def _setup_lst(self):
self._lst = self._data
self._study = self._opt_data
def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole:
@@ -98,25 +82,19 @@ class TableModel(QAbstractTableModel):
column = index.column()
if self._headers[column] == "name":
return self._profile.point(row).name
return self._data.point(row).name
elif self._headers[column] == "sl":
value = self._profile.point(row).sl
value = self._data.point(row).sl
if value == None:
text = _translate("SedimentLayers", "Not defined")
return text
return str(value)
elif self._headers[column] == "x":
return self._profile.point(row).x
return self._data.point(row).x
elif self._headers[column] == "y":
return self._profile.point(row).y
return self._data.point(row).y
elif self._headers[column] == "z":
return self._profile.point(row).z
return QVariant()
def headerData(self, friction, orientation, role):
if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
return table_headers[self._headers[friction]]
return self._data.point(row).z
return QVariant()
@@ -139,7 +117,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
SetSLCommand(
self._profile, row, new
self._data, row, new
)
)
+41 -55
View File
@@ -4,8 +4,7 @@ import logging
from tools import trace, timer
from View.ASubWindow import ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -28,37 +27,42 @@ from View.SedimentLayers.Reach.Profile.UndoCommand import *
from View.SedimentLayers.Reach.Profile.Table import *
from View.SedimentLayers.Reach.Profile.Plot import Plot
from View.Plot.MplCanvas import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.SedimentLayers.Reach.Profile.translate import table_headers, retranslate
from View.SedimentLayers.Reach.Profile.translate import SedimentProfileTranslate
from View.SedimentLayers.Window import SedimentLayersWindow
_translate = QCoreApplication.translate
logger = logging.getLogger()
class ProfileSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Profile sediment layers", study=None, profile=None, parent=None):
self._study = study
self._sediment_layers = self._study.river.sediment_layers
self._profile = profile
self._reach = self._study.river.current_reach().reach
class ProfileSedimentLayersWindow(PamhyrWindow):
_pamhyr_ui = "ProfileSedimentLayers"
_pamhyr_name = "Profile sediment layers"
self.setup_title(title)
def __init__(self, study=None, config=None, profile=None, parent=None):
self._sediment_layers = study.river.sediment_layers
self._profile = profile
self._reach = profile.reach
name = self.compute_name(study)
super(ProfileSedimentLayersWindow, self).__init__(
name=self._title, ui="ProfileSedimentLayers", parent=parent
title = name,
study = study,
config = config,
trad = SedimentProfileTranslate(),
parent = parent
)
self.setup_sc()
self.setup_table()
self.setup_graph()
self.setup_connections()
self.ui.setWindowTitle(self._title)
def setup_title(self, title):
def compute_name(self, study):
rname = self._reach.name
if rname == "":
rname = _translate("SedimentLayers", "(no name)")
@@ -70,41 +74,32 @@ class ProfileSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
"(no name - @kp)").replace("@kp", str(self._profile.kp)
)
self._title = (
title + " - "
+ self._study.name + " - "
return (
self._pamhyr_name + " - "
+ study.name + " - "
+ rname + " - " + pname
)
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):
retranslate()
table_headers = self._trad.get_dict("table_headers")
table = self.find(QTableView, f"tableView")
self._table = TableModel(
study = self._study,
profile = self._profile,
undo = self._undo_stack,
)
table.setModel(self._table)
self._delegate_stricklers = ComboBoxDelegate(
self._delegate_sl = ComboBoxDelegate(
study = self._study,
parent=self
)
table.setItemDelegateForColumn(
list(table_headers).index("sl"),
self._delegate_stricklers
table = self.find(QTableView, f"tableView")
self._table = TableModel(
table_view = table,
data = self._profile,
opt_data = self._study,
table_headers = table_headers,
editable_headers = ["sl"],
delegates = {"sl": self._delegate_sl},
trad = self._trad,
undo = self._undo_stack,
)
table.setModel(self._table)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
@@ -130,18 +125,9 @@ class ProfileSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
)
self.plot.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)
self._table.layoutChanged\
.connect(self._update_plot)
self._table.dataChanged\
.connect(self._update_plot)
self._table.layoutChanged.connect(self._update_plot)
self._table.dataChanged.connect(self._update_plot)
def index_selected_rows(self):
table = self.find(QTableView, f"tableView")
@@ -155,14 +141,14 @@ class ProfileSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
)
)
def copy(self):
def _copy(self):
logger.info("TODO: copy")
def paste(self):
def _paste(self):
logger.info("TODO: paste")
def undo(self):
def _undo(self):
self._table.undo()
def redo(self):
def _redo(self):
self._table.redo()
@@ -2,19 +2,18 @@
from PyQt5.QtCore import QCoreApplication
from View.SedimentLayers.Reach.translate import SedimentReachTranslate
_translate = QCoreApplication.translate
table_headers = {
"x": _translate("SedimentLayers", "X (m)"),
"y": _translate("SedimentLayers", "Y (m)"),
"z": _translate("SedimentLayers", "Z (m)"),
"name": _translate("SedimentLayers", "Name"),
"sl": _translate("SedimentLayers", "Sediment layers"),
}
class SedimentProfileTranslate(SedimentReachTranslate):
def __init__(self):
super(SedimentProfileTranslate, self).__init__()
def retranslate():
table_headers["x"] = _translate("SedimentLayers", "X (m)")
table_headers["y"] = _translate("SedimentLayers", "Y (m)")
table_headers["z"] = _translate("SedimentLayers", "Z (m)")
table_headers["name"] = _translate("SedimentLayers", "Name")
table_headers["sl"] = _translate("SedimentLayers", "Sediment layers")
self._sub_dict["table_headers"] = {
"x": _translate("SedimentLayers", "X (m)"),
"y": _translate("SedimentLayers", "Y (m)"),
"z": _translate("SedimentLayers", "Z (m)"),
"name": _translate("SedimentLayers", "Name"),
"sl": _translate("SedimentLayers", "Sediment layers"),
}
+9 -6
View File
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
from View.ASubWindow import ASubWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtGui import (
QKeySequence,
@@ -20,12 +19,16 @@ from View.SedimentLayers.Reach.translate import *
_translate = QCoreApplication.translate
class SLDialog(ASubWindow, ListedSubWindow):
def __init__(self, title="SL", study=None, parent=None):
self._study = study
class SLDialog(PamhyrDialog):
_pamhyr_ui = "SLDialog"
_pamhyr_name = "SL"
def __init__(self, study=None, config=None, parent=None):
super(SLDialog, self).__init__(
name=title, ui="SLDialog", parent=parent
title = self._pamhyr_name,
study = study,
config = config,
parent=parent
)
self.setup_combobox()
+14 -36
View File
@@ -18,23 +18,25 @@ from PyQt5.QtWidgets import (
)
from View.SedimentLayers.Reach.UndoCommand import *
from View.SedimentLayers.Reach.translate import *
from View.Tools.PamhyrTable import PamhyrTableModel
_translate = QCoreApplication.translate
logger = logging.getLogger()
class ComboBoxDelegate(QItemDelegate):
def __init__(self, study=None, parent=None):
def __init__(self, study=None, trad=None, parent=None):
super(ComboBoxDelegate, self).__init__(parent)
self._study = study
self._trad = trad
def createEditor(self, parent, option, index):
self.editor = QComboBox(parent)
self.editor.addItems(
[_translate("SedimentLayers", "Not defined")] +
[self._trad["nd"]] +
list(
map(
lambda sl: str(sl),
@@ -67,28 +69,10 @@ class ComboBoxDelegate(QItemDelegate):
self.commitData.emit(self.sender())
class TableModel(QAbstractTableModel):
def __init__(self, study=None, reach=None, undo=None):
super(QAbstractTableModel, self).__init__()
self._headers = list(table_headers.keys())
self._study = study
self._undo = undo
self._reach = reach
def flags(self, index):
column = index.column()
options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
if self._headers[column] == "sl":
options |= Qt.ItemIsEditable
return options
def rowCount(self, parent):
return self._reach.number_profiles
def columnCount(self, parent):
return len(self._headers)
class TableModel(PamhyrTableModel):
def _setup_lst(self):
self._lst = self._data
self._study = self._opt_data
def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole:
@@ -98,11 +82,11 @@ class TableModel(QAbstractTableModel):
column = index.column()
if self._headers[column] == "name":
return self._reach.profile(row).name
return self._data.profile(row).name
if self._headers[column] == "kp":
return self._reach.profile(row).kp
return self._data.profile(row).kp
if self._headers[column] == "sl":
value = self._reach.profile(row).sl
value = self._data.profile(row).sl
if value == None:
text = _translate("SedimentLayers", "Not defined")
return text
@@ -110,12 +94,6 @@ class TableModel(QAbstractTableModel):
return QVariant()
def headerData(self, friction, orientation, role):
if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
return table_headers[self._headers[friction]]
return QVariant()
def setData(self, index, value, role=Qt.EditRole):
if not index.isValid() or role != Qt.EditRole:
return False
@@ -135,7 +113,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
SetSLCommand(
self._reach, row, new
self._data, row, new
)
)
@@ -145,7 +123,7 @@ class TableModel(QAbstractTableModel):
def apply_sl_each_profile(self, sl):
self._undo.push(
ApplySLCommand(
self._reach, sl
self._data, sl
)
)
self.layoutChanged.emit()
+42 -53
View File
@@ -4,8 +4,7 @@ import logging
from tools import trace, timer
from View.ASubWindow import ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -29,10 +28,10 @@ from View.SedimentLayers.Reach.Table import *
from View.SedimentLayers.Reach.Plot import Plot
from View.SedimentLayers.Reach.SLDialog import SLDialog
from View.Plot.MplCanvas import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.SedimentLayers.Reach.translate import table_headers, retranslate
from View.SedimentLayers.Reach.translate import SedimentReachTranslate
from View.SedimentLayers.Window import SedimentLayersWindow
from View.SedimentLayers.Reach.Profile.Window import ProfileSedimentLayersWindow
@@ -40,64 +39,58 @@ _translate = QCoreApplication.translate
logger = logging.getLogger()
class ReachSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Reach sediment layers", study=None, parent=None):
self._study = study
self._sediment_layers = self._study.river.sediment_layers
self._reach = self._study.river.current_reach().reach
class ReachSedimentLayersWindow(PamhyrWindow):
_pamhyr_ui = "ReachSedimentLayers"
_pamhyr_name = "Reach sediment layers"
self.setup_title(title)
def __init__(self, study=None, config=None, parent=None):
self._sediment_layers = study.river.sediment_layers
self._reach = study.river.current_reach().reach
name = (
self._pamhyr_name + " - " +
study.name + " - " +
self._reach.name
)
super(ReachSedimentLayersWindow, self).__init__(
name=self._title, ui="ReachSedimentLayers", parent=parent
title = name,
study = study,
config = config,
trad = SedimentReachTranslate(),
parent = parent
)
self.setup_sc()
self.setup_table()
self.setup_graph()
self.setup_plot()
self.setup_connections()
self.ui.setWindowTitle(self._title)
def setup_title(self, title):
self._title = (
title + " - " + self._study.name + " - " + self._reach.name
)
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):
retranslate()
table_headers = self._trad.get_dict("table_headers")
table = self.find(QTableView, f"tableView")
self._table = TableModel(
study = self._study,
reach = self._reach,
undo = self._undo_stack,
)
table.setModel(self._table)
self._delegate_stricklers = ComboBoxDelegate(
self._delegate_sl = ComboBoxDelegate(
study = self._study,
trad = self._trad,
parent=self
)
table.setItemDelegateForColumn(
list(table_headers).index("sl"),
self._delegate_stricklers
table = self.find(QTableView, f"tableView")
self._table = TableModel(
table_view = table,
data = self._reach,
opt_data = self._study,
table_headers = table_headers,
editable_headers = ["sl"],
delegates = {"sl": self._delegate_sl},
trad = self._trad,
undo = self._undo_stack,
)
table.setModel(self._table)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
def setup_graph(self):
def setup_plot(self):
self.canvas = MplCanvas(width=5, height=4, dpi=100)
self.canvas.setObjectName("canvas")
self.toolbar = PamhyrPlotToolbar(
@@ -114,6 +107,7 @@ class ReachSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
canvas = self.canvas,
data = self._reach,
toolbar = self.toolbar,
trad = self._trad,
display_current = False
)
self.plot.draw()
@@ -129,11 +123,6 @@ class ReachSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
.clicked\
.connect(self.apply_sl_each_profile)
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)
self._table.layoutChanged\
.connect(self._update_plot)
self._table.dataChanged\
@@ -152,17 +141,17 @@ class ReachSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
)
)
def copy(self):
def _copy(self):
logger.info("TODO: copy")
def paste(self):
def _paste(self):
logger.info("TODO: paste")
def undo(self):
def _undo(self):
self._table.undo()
self._update_plot()
def redo(self):
def _redo(self):
self._table.redo()
self._update_plot()
+14 -9
View File
@@ -2,15 +2,20 @@
from PyQt5.QtCore import QCoreApplication
from View.SedimentLayers.translate import SedimentTranslate
_translate = QCoreApplication.translate
table_headers = {
"name": _translate("SedimentLayers", "Name"),
"kp": _translate("SedimentLayers", "KP (m)"),
"sl": _translate("SedimentLayers", "Sediment layers"),
}
class SedimentReachTranslate(SedimentTranslate):
def __init__(self):
super(SedimentReachTranslate, self).__init__()
def retranslate():
table_headers["name"] = _translate("SedimentLayers", "Name")
table_headers["kp"] = _translate("SedimentLayers", "KP (m)")
table_headers["sl"] = _translate("SedimentLayers", "Sediment layers")
self._dict["nd"] = _translate("SedimentLayers", "Not defined")
self._dict["kp"] = _translate("SedimentLayers", "Kp (m)")
self._dict["height"] = _translate("SedimentLayers", "Height (m)")
self._sub_dict["table_headers"] = {
"name": _translate("SedimentLayers", "Name"),
"kp": _translate("SedimentLayers", "KP (m)"),
"sl": _translate("SedimentLayers", "Sediment layers"),
}
+12 -38
View File
@@ -15,32 +15,12 @@ from PyQt5.QtWidgets import (
QComboBox,
)
from View.Tools.PamhyrTable import PamhyrTableModel
from View.SedimentLayers.UndoCommand import *
from View.SedimentLayers.translate import *
_translate = QCoreApplication.translate
class TableModel(QAbstractTableModel):
def __init__(self, study=None, undo=None):
super(QAbstractTableModel, self).__init__()
self._headers = list(table_headers.keys())
self._study = study
self._undo = undo
self._sl = self._study.river.sediment_layers
def flags(self, index):
options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
options |= Qt.ItemIsEditable
return options
def rowCount(self, parent):
return len(self._sl)
def columnCount(self, parent):
return len(self._headers)
class TableModel(PamhyrTableModel):
def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole:
return QVariant()
@@ -49,15 +29,9 @@ class TableModel(QAbstractTableModel):
column = index.column()
if self._headers[column] == "name":
return self._sl.get(row).name
return self._data.get(row).name
elif self._headers[column] == "comment":
return self._sl.get(row).comment
return QVariant()
def headerData(self, friction, orientation, role):
if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
return table_headers[self._headers[friction]]
return self._data.get(row).comment
return QVariant()
@@ -71,13 +45,13 @@ class TableModel(QAbstractTableModel):
if self._headers[column] == "name":
self._undo.push(
SetNameCommand(
self._sl, row, value
self._data, row, value
)
)
if self._headers[column] == "comment":
self._undo.push(
SetCommentCommand(
self._sl, row, value
self._data, row, value
)
)
@@ -89,7 +63,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
AddCommand(
self._sl, row
self._data, row
)
)
@@ -101,7 +75,7 @@ class TableModel(QAbstractTableModel):
self._undo.push(
DelCommand(
self._sl, rows
self._data, rows
)
)
@@ -118,7 +92,7 @@ class TableModel(QAbstractTableModel):
self._undo_stack.push(
MoveCommand(
self._sl, "up", row
self._data, "up", row
)
)
@@ -126,7 +100,7 @@ class TableModel(QAbstractTableModel):
self.layoutChanged.emit()
def move_down(self, index, parent=QModelIndex()):
if row > len(self._sl):
if row > len(self._data):
return
target = row
@@ -135,7 +109,7 @@ class TableModel(QAbstractTableModel):
self._undo_stack.push(
MoveCommand(
self._sl, "down", row
self._data, "down", row
)
)
+46 -44
View File
@@ -1,11 +1,26 @@
# 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 View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -29,62 +44,53 @@ from View.SedimentLayers.Table import *
from View.SedimentLayers.Edit.Plot import Plot
from View.Plot.MplCanvas import MplCanvas
from View.SedimentLayers.translate import table_headers, retranslate
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.SedimentLayers.translate import SedimentTranslate
from View.SedimentLayers.Edit.Window import EditSedimentLayersWindow
_translate = QCoreApplication.translate
logger = logging.getLogger()
class SedimentLayersWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="SedimentLayersList", study=None, parent=None):
self._study = study
self._sediment_layers = self._study.river.sediment_layers
class SedimentLayersWindow(PamhyrWindow):
_pamhyr_ui = "SedimentLayersList"
_pamhyr_name = "Sediment Layers List"
self.setup_title(title)
def __init__(self, study=None, config=None, parent=None):
self._sediment_layers = study.river.sediment_layers
name = (
self._pamhyr_name + " - " + study.name
)
super(SedimentLayersWindow, self).__init__(
name=self._title, ui="SedimentLayersList", parent=parent
title = name,
study = study,
config = config,
trad = SedimentTranslate(),
parent=parent
)
self.setup_sc()
self.setup_table()
self.setup_graph()
self.setup_plot()
self.setup_connections()
self.ui.setWindowTitle(self._title)
def setup_title(self, title):
self._title = (
title + " - " + self._study.name
)
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):
retranslate()
table = self.find(QTableView, f"tableView")
self._table = TableModel(
study = self._study,
table_view = table,
table_headers = self._trad.get_dict("table_headers"),
editable_headers = ["name", "comment"],
data = self._study.river.sediment_layers,
trad = self._trad,
undo = self._undo_stack,
)
table.setModel(self._table)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
def setup_graph(self):
self.canvas = MplCanvas(width=5, height=4, dpi=100)
def setup_plot(self):
self.canvas = MplCanvas(width=2, height=4, dpi=100)
self.canvas.setObjectName("canvas")
self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
self.plot_layout.addWidget(self.canvas)
@@ -94,11 +100,6 @@ class SedimentLayersWindow(ASubMainWindow, ListedSubWindow):
self.find(QAction, "action_del").triggered.connect(self.delete)
self.find(QAction, "action_edit").triggered.connect(self.edit_sediment_layers)
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)
table = self.find(QTableView, f"tableView")
table.selectionModel()\
.selectionChanged\
@@ -116,6 +117,7 @@ class SedimentLayersWindow(ASubMainWindow, ListedSubWindow):
self.plot = Plot(
canvas = self.canvas,
data = self._sediment_layers.get(rows[0]),
trad = self._trad,
toolbar = None,
display_current = False
)
@@ -148,16 +150,16 @@ class SedimentLayersWindow(ASubMainWindow, ListedSubWindow):
self._table.delete(rows)
def copy(self):
def _copy(self):
logger.info("TODO: copy")
def paste(self):
def _paste(self):
logger.info("TODO: paste")
def undo(self):
def _undo(self):
self._table.undo()
def redo(self):
def _redo(self):
self._table.redo()
def edit_sediment_layers(self):
+9 -7
View File
@@ -2,13 +2,15 @@
from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate
table_headers = {
"name": _translate("SedimentLayers", "Name"),
"comment": _translate("SedimentLayers", "Comment"),
}
class SedimentTranslate(PamhyrTranslate):
def __init__(self):
super(SedimentTranslate, self).__init__()
def retranslate():
table_headers["name"] = _translate("SedimentLayers", "Name")
table_headers["comment"] = _translate("SedimentLayers", "Comment")
self._sub_dict["table_headers"] = {
"name": _translate("SedimentLayers", "Name"),
"comment": _translate("SedimentLayers", "Comment"),
}
+23 -46
View File
@@ -34,37 +34,20 @@ from PyQt5.QtWidgets import (
QComboBox,
)
from View.Tools.PamhyrTable import PamhyrTableModel
from View.SolverParameters.UndoCommand import *
from View.SolverParameters import translate as tr
from Solver.Solvers import solver_long_name, solver_type_list
logger = logging.getLogger()
_translate = QCoreApplication.translate
class TableModel(QAbstractTableModel):
def __init__(self, data=None, undo=None, tab=""):
super(QAbstractTableModel, self).__init__()
self._headers = list(tr.table_headers.keys())
self._data = data
self._undo = undo
self._tab = tab
self._params = self._data.get_params(self._tab)
def flags(self, index):
options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
column = index.column()
if self._headers[column] == "value":
options |= Qt.ItemIsEditable
return options
def rowCount(self, parent):
return len(self._params)
def columnCount(self, parent):
return len(self._headers)
class TableModel(PamhyrTableModel):
def _setup_lst(self):
self._tab = self._opt_data
self._lst = self._data.get_params(self._tab)
def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole:
@@ -75,24 +58,18 @@ class TableModel(QAbstractTableModel):
cname = self._headers[column]
if cname == "name":
value = self._params.get(row)[cname]
if value in tr.names:
value = tr.names[value]
value = self._lst.get(row)[cname]
if value in self._trad.get_dict("names"):
value = self._trad.get_dict("names")[value]
return value
elif cname == "value":
value = self._params.get(row)[cname]
if value in tr.yes_no:
value = tr.yes_no[value]
value = self._lst.get(row)[cname]
if value in self._trad.get_dict("yes_no"):
value = self._trad.get_dict("yes_no")[value]
return value
return QVariant()
def headerData(self, section, orientation, role):
if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
return tr.table_headers[self._headers[section]]
return QVariant()
def setData(self, index, value, role=Qt.EditRole):
if not index.isValid() or role != Qt.EditRole:
return False
@@ -102,12 +79,12 @@ class TableModel(QAbstractTableModel):
try:
if self._headers[column] == "value":
if value in tr.r_yes_no:
value = tr.r_yes_no[value].lower()
if value in self._trad.get_dict("r_yes_no"):
value = self._trad.get_dict("r_yes_no")[value].lower()
self._undo.push(
SetCommand(
self._params, row,
self._lst, row,
"value", value
)
)
@@ -123,7 +100,7 @@ class TableModel(QAbstractTableModel):
# self._undo.push(
# AddCommand(
# self._params, row
# self._lst, row
# )
# )
@@ -135,7 +112,7 @@ class TableModel(QAbstractTableModel):
# self._undo.push(
# DelCommand(
# self._params, rows
# self._lst, rows
# )
# )
@@ -147,7 +124,7 @@ class TableModel(QAbstractTableModel):
# self._undo.push(
# SortCommand(
# self._params, False
# self._lst, False
# )
# )
@@ -164,7 +141,7 @@ class TableModel(QAbstractTableModel):
# self._undo_stack.push(
# MoveCommand(
# self._params, "up", row
# self._lst, "up", row
# )
# )
@@ -172,7 +149,7 @@ class TableModel(QAbstractTableModel):
# self.layoutChanged.emit()
# def move_down(self, index, parent=QModelIndex()):
# if row > len(self._params):
# if row > len(self._lst):
# return
# target = row
@@ -181,7 +158,7 @@ class TableModel(QAbstractTableModel):
# self._undo_stack.push(
# MoveCommand(
# self._params, "down", row
# self._lst, "down", row
# )
# )
+26 -30
View File
@@ -20,8 +20,7 @@ import logging
from tools import trace, timer
from View.ASubWindow import ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -43,7 +42,7 @@ from PyQt5.QtWidgets import (
from View.SolverParameters.UndoCommand import *
from View.SolverParameters.Table import TableModel
from View.SolverParameters import translate as tr
from View.SolverParameters.translate import ParamTranslate
from Solver.Solvers import solver_long_name, solver_type_list
@@ -51,25 +50,25 @@ _translate = QCoreApplication.translate
logger = logging.getLogger()
class SolverParametersWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Solver parameters", study=None, parent=None):
# Init tanslate dictionary
tr.init()
self._title = title + " - " + study.name
class SolverParametersWindow(PamhyrWindow):
_pamhyr_ui = "SolverParameters"
_pamhyr_name = "Solver parameters"
def __init__(self, study=None, config=None, parent=None):
name = self._pamhyr_name + " - " + study.name
super(SolverParametersWindow, self).__init__(
name=title, ui="SolverParameters", parent=parent
title = name,
study = study,
config = config,
options = ['copy'],
trad = ParamTranslate(),
parent = parent
)
self._study = study
self._params = self._study.river.parameters
self.setup_sc()
self.setup_table()
self.setup_connections()
self.ui.setWindowTitle(self._title)
def setup_sc(self):
self._undo_stack = {}
@@ -77,10 +76,10 @@ class SolverParametersWindow(ASubMainWindow, ListedSubWindow):
for st in solver_type_list:
self._undo_stack[st] = 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)
self._undo_sc = QShortcut(QKeySequence.Undo, self)
self._redo_sc = QShortcut(QKeySequence.Redo, self)
self._undo_sc.activated.connect(self._undo)
self._redo_sc.activated.connect(self._redo)
def setup_table(self):
self._table = {}
@@ -97,9 +96,13 @@ class SolverParametersWindow(ASubMainWindow, ListedSubWindow):
# Create table model
self._table[st] = TableModel(
table_view = table,
data = self._study.river,
opt_data = st,
table_headers = self._trad.get_dict("table_headers"),
editable_headers = ["value"],
trad = self._trad,
undo = self._undo_stack[st],
tab = st,
)
table.setModel(self._table[st])
@@ -115,31 +118,24 @@ class SolverParametersWindow(ASubMainWindow, ListedSubWindow):
# Create tab
self._tab_widget.addTab(widget, f"{solver_long_name[st]}")
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)
def current_tab(self):
return self.find(QTabWidget, "tabWidget")\
.currentWidget()\
.objectName()\
.replace("tab_", "")
def undo(self):
def _undo(self):
tab = self.current_tab()
self._table[tab].undo()
self._set_current_reach()
def redo(self):
def _redo(self):
tab = self.current_tab()
self._table[tab].redo()
self._set_current_reach()
def copy(self):
def _copy(self):
logger.info("TODO: copy")
def paste(self):
def _paste(self):
logger.info("TODO: paste")
+51 -57
View File
@@ -18,66 +18,60 @@
from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate
table_headers = None
yes_no = None
r_yes_no = None
names = None
class ParamTranslate(PamhyrTranslate):
def __init__(self):
super(ParamTranslate, self).__init__()
def init():
global table_headers
table_headers = {
"name": _translate("SolverParameters", "Name"),
"value": _translate("SolverParameters", "Value")
}
self._sub_dict["table_headers"] = {
"name": _translate("SolverParameters", "Name"),
"value": _translate("SolverParameters", "Value")
}
# Used to translate user parameter with value yes or no
global yes_no
yes_no = {
"yes": _translate("SolverParameters", "Yes"),
"no": _translate("SolverParameters", "No"),
"y": _translate("SolverParameters", "Y"),
"n": _translate("SolverParameters", "N"),
}
self._sub_dict["yes_no"] = {
"yes": _translate("SolverParameters", "Yes"),
"no": _translate("SolverParameters", "No"),
"y": _translate("SolverParameters", "Y"),
"n": _translate("SolverParameters", "N"),
}
# Reverse
global r_yes_no
r_yes_no = {
_translate("SolverParameters", "Yes"): "yes",
_translate("SolverParameters", "No"): "no",
_translate("SolverParameters", "Y"): "y",
_translate("SolverParameters", "N"): "n",
}
self._sub_dict["r_yes_no"] = {
_translate("SolverParameters", "Yes"): "yes",
_translate("SolverParameters", "No"): "no",
_translate("SolverParameters", "Y"): "y",
_translate("SolverParameters", "N"): "n",
}
global names
names = {
"all_init_time": _translate("SolverParameters", "Initial time (jj:hh:mm:ss)"),
"all_final_time": _translate("SolverParameters", "Final time (jj:hh:mm:ss)"),
"all_timestep": _translate("SolverParameters", "Timestep (second)"),
"all_command_line_arguments": _translate("SolverParameters", "Command line arguments"),
# Mage specific parameters
"mage_min_timestep": _translate("SolverParameters", "Minimum timestep (second)"),
"mage_timestep_tra": _translate("SolverParameters", "Time step of writing on .TRA"),
"mage_timestep_bin": _translate("SolverParameters", "Time step of writing on .BIN"),
"mage_implicitation": _translate("SolverParameters", "Implicitation parameter"),
"mage_continuity_discretization": _translate("SolverParameters", "Continuity discretization type (S/L)"),
"mage_qsj_discretization": _translate("SolverParameters", "QSJ discretization (A/B)"),
"mage_stop_criterion_iterations": _translate("SolverParameters", "Stop criterion iterations (G/A/R)"),
"mage_iteration_type": _translate("SolverParameters", "Iteration type"),
"mage_smooth_coef": _translate("SolverParameters", "Smoothing coefficient"),
"mage_cfl_max": _translate("SolverParameters", "Maximun accepted number of CFL"),
"mage_min_height": _translate("SolverParameters", "Minimum water height (meter)"),
"mage_max_niter": _translate("SolverParameters", "Maximun number of iterations (< 100)"),
"mage_timestep_reduction_factor": _translate("SolverParameters", "Timestep reduction factor"),
"mage_precision_reduction_factor_Z": _translate("SolverParameters", "Reduction precision factor of Z"),
"mage_precision_reduction_factor_Q": _translate("SolverParameters", "Reduction precision factor of Q"),
"mage_precision_reduction_factor_r": _translate("SolverParameters", "Reduction precision factor of residue"),
"mage_niter_max_precision": _translate("SolverParameters", "Number of iteration at maximum precision"),
"mage_niter_before_switch": _translate("SolverParameters", "Number of iteration before switch"),
"mage_max_froude": _translate("SolverParameters", "Maximum accepted Froude number"),
"mage_diffluence_node_height_balance": _translate("SolverParameters", "Diffluence node height balance"),
"mage_compute_reach_volume_balance": _translate("SolverParameters", "Compute reach volume balance (Y/N)"),
"mage_max_reach_volume_balance": _translate("SolverParameters", "Maximum reach volume balance"),
"mage_min_reach_volume_to_check": _translate("SolverParameters", "Minimum reach volume to check"),
}
self._sub_dict["names"] = {
"all_init_time": _translate("SolverParameters", "Initial time (jj:hh:mm:ss)"),
"all_final_time": _translate("SolverParameters", "Final time (jj:hh:mm:ss)"),
"all_timestep": _translate("SolverParameters", "Timestep (second)"),
"all_command_line_arguments": _translate("SolverParameters", "Command line arguments"),
# Mage specific parameters
"mage_min_timestep": _translate("SolverParameters", "Minimum timestep (second)"),
"mage_timestep_tra": _translate("SolverParameters", "Time step of writing on .TRA"),
"mage_timestep_bin": _translate("SolverParameters", "Time step of writing on .BIN"),
"mage_implicitation": _translate("SolverParameters", "Implicitation parameter"),
"mage_continuity_discretization": _translate("SolverParameters", "Continuity discretization type (S/L)"),
"mage_qsj_discretization": _translate("SolverParameters", "QSJ discretization (A/B)"),
"mage_stop_criterion_iterations": _translate("SolverParameters", "Stop criterion iterations (G/A/R)"),
"mage_iteration_type": _translate("SolverParameters", "Iteration type"),
"mage_smooth_coef": _translate("SolverParameters", "Smoothing coefficient"),
"mage_cfl_max": _translate("SolverParameters", "Maximun accepted number of CFL"),
"mage_min_height": _translate("SolverParameters", "Minimum water height (meter)"),
"mage_max_niter": _translate("SolverParameters", "Maximun number of iterations (< 100)"),
"mage_timestep_reduction_factor": _translate("SolverParameters", "Timestep reduction factor"),
"mage_precision_reduction_factor_Z": _translate("SolverParameters", "Reduction precision factor of Z"),
"mage_precision_reduction_factor_Q": _translate("SolverParameters", "Reduction precision factor of Q"),
"mage_precision_reduction_factor_r": _translate("SolverParameters", "Reduction precision factor of residue"),
"mage_niter_max_precision": _translate("SolverParameters", "Number of iteration at maximum precision"),
"mage_niter_before_switch": _translate("SolverParameters", "Number of iteration before switch"),
"mage_max_froude": _translate("SolverParameters", "Maximum accepted Froude number"),
"mage_diffluence_node_height_balance": _translate("SolverParameters", "Diffluence node height balance"),
"mage_compute_reach_volume_balance": _translate("SolverParameters", "Compute reach volume balance (Y/N)"),
"mage_max_reach_volume_balance": _translate("SolverParameters", "Maximum reach volume balance"),
"mage_min_reach_volume_to_check": _translate("SolverParameters", "Minimum reach volume to check"),
}
+18 -33
View File
@@ -20,8 +20,7 @@ import logging
from tools import trace, timer
from View.ASubWindow import ASubMainWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5.QtGui import (
QKeySequence,
@@ -44,40 +43,31 @@ from Model.Stricklers.Stricklers import Stricklers
from View.Stricklers.UndoCommand import PasteCommand
from View.Stricklers.Table import TableModel
from View.Stricklers.translate import table_headers, retranslate
from View.Stricklers.translate import StricklersTranslate
_translate = QCoreApplication.translate
logger = logging.getLogger()
class StricklersWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Stricklers", study=None, config=None, parent=None):
self._title = title + " - " + study.name
class StricklersWindow(PamhyrWindow):
_pamhyr_ui = "Stricklers"
_pamhyr_name = "Stricklers"
def __init__(self, study=None, config=None, parent=None):
name = self._pamhyr_name + " - " + study.name
super(StricklersWindow, self).__init__(
name=title, ui="Stricklers", parent=parent
title = name,
study = study,
config = config,
trad = StricklersTranslate(),
parent = parent
)
self._study = study
self._config = config
self.setup_sc()
self.setup_table()
self.setup_connections()
self.ui.setWindowTitle(self._title)
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):
retranslate()
self._table = {}
for t in ["app", "study"]:
@@ -89,7 +79,7 @@ class StricklersWindow(ASubMainWindow, ListedSubWindow):
self._table[t] = TableModel(
table_view = table,
table_headers = table_headers,
table_headers = self._trad.get_dict("table_headers"),
editable_headers = ["name", "comment", "minor", "medium"],
data = data,
undo = self._undo_stack,
@@ -105,11 +95,6 @@ class StricklersWindow(ASubMainWindow, ListedSubWindow):
self.find(QAction, "action_del").triggered.connect(self.delete)
self.find(QAction, "action_sort").triggered.connect(self.sort)
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)
def index_selected_rows(self):
table = self.find(QTableView, f"tableView_study")
return list(
@@ -139,14 +124,14 @@ class StricklersWindow(ASubMainWindow, ListedSubWindow):
def sort(self):
self._table['study'].sort(False)
def copy(self):
def _copy(self):
logger.info("TODO: copy")
def paste(self):
def _paste(self):
logger.info("TODO: paste")
def undo(self):
def _undo(self):
self._table['study'].undo()
def redo(self):
def _redo(self):
self._table['study'].redo()
+11 -14
View File
@@ -18,21 +18,18 @@
from PyQt5.QtCore import QCoreApplication
from Model.LateralContribution.LateralContributionTypes import (
NotDefined, LateralContrib, Rain, Evaporation,
)
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate
table_headers = {
"name": _translate("LateralContribution", "Name"),
"minor": _translate("LateralContribution", "Minor bed"),
"medium": _translate("LateralContribution", "Medium bed"),
"comment": _translate("LateralContribution", "Comment"),
}
def retranslate():
table_headers["name"] = _translate("LateralContribution", "Name")
table_headers["minor"] = _translate("LateralContribution", "Minor bed")
table_headers["medium"] = _translate("LateralContribution", "Medium bed")
table_headers["comment"] = _translate("LateralContribution", "Comment")
class StricklersTranslate(PamhyrTranslate):
def __init__(self):
super(StricklersTranslate, self).__init__()
self._sub_dict["table_headers"] = {
"name": _translate("LateralContribution", "Name"),
"minor": _translate("LateralContribution", "Minor bed"),
"medium": _translate("LateralContribution", "Medium bed"),
"comment": _translate("LateralContribution", "Comment"),
}
+29 -19
View File
@@ -17,7 +17,7 @@
# -*- coding: utf-8 -*-
from Model.Study import Study
from View.ASubWindow import ASubWindow
from View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtCore import QCoreApplication
@@ -27,27 +27,37 @@ from PyQt5.QtWidgets import (
_translate = QCoreApplication.translate
class NewStudyWindow(ASubWindow):
def __init__(self, study=None, title="New Study", parent=None):
super(NewStudyWindow, self).__init__(name=title, ui="NewStudy", parent=parent)
self.ui.setWindowTitle(title)
class NewStudyWindow(PamhyrDialog):
_pamhyr_ui = "NewStudy"
_pamhyr_name = "Edit/New Study"
self.parent = parent
self.study = study
def __init__(self, study=None, config = None, parent=None):
if study is not None:
name = f"Edit study - {study.name}"
else:
name = "New study"
if not self.study is None:
self.set_line_edit_text("lineEdit_name", self.study.name)
self.set_text_edit_text("textEdit_description", self.study.description)
self.set_datetime_edit("dateTimeEdit_date", self.study.date)
super(NewStudyWindow, self).__init__(
title = name,
study = study,
config = config,
options = [],
parent = parent
)
if not self._study is None:
self.set_line_edit_text("lineEdit_name", self._study.name)
self.set_text_edit_text("textEdit_description", self._study.description)
self.set_datetime_edit("dateTimeEdit_date", self._study.date)
self.find(QLabel, "label_creation_date_data").setText(
self.study.creation_date.isoformat(sep=" ")
self._study.creation_date.isoformat(sep=" ")
)
self.find(QLabel, "label_last_modification_data").setText(
self.study.last_save_date.isoformat(sep=" ")
self._study.last_save_date.isoformat(sep=" ")
)
if self.study.time_system == "date":
if self._study.time_system == "date":
self.set_radio_button("radioButton_date", True)
self.find(QLabel, "label_date").setEnabled(True)
self.find(QDateTimeEdit, "dateTimeEdit_date").setEnabled(True)
@@ -76,18 +86,18 @@ class NewStudyWindow(ASubWindow):
name = self.get_line_edit_text("lineEdit_name")
description = self.get_text_edit_text("textEdit_description")
if self.study is None:
if self._study is None:
study = Study.new(name, description)
if self.get_radio_button("radioButton_date"):
date = self.get_datetime_edit("dateTimeEdit_date")
study.use_date(date)
self.parent.set_model(study)
else:
self.study.name = name
self.study.description = description
self._study.name = name
self._study.description = description
if self.get_radio_button("radioButton_date"):
date = self.get_datetime_edit("dateTimeEdit_date")
self.study.use_date(date)
self._study.use_date(date)
else:
self.study.use_time()
self._study.use_time()
self.done(True)
@@ -463,11 +463,16 @@ class ASubWindowFeatures(object):
# Top level interface
class ASubMainWindow(QMainWindow, ASubWindowFeatures, WindowToolKit):
def __init__(self, name="", ui="dummy", parent=None):
def __init__(self, name="", ui="dummy", parent=None, **kwargs):
super(ASubMainWindow, self).__init__(parent=parent)
if ui is not None:
self.ui = loadUi(
os.path.join(os.path.dirname(__file__), "ui", f"{ui}.ui"),
os.path.abspath(
os.path.join(
os.path.dirname(__file__),
"..", "ui", f"{ui}.ui"
)
),
self
)
@@ -496,10 +501,15 @@ class ASubMainWindow(QMainWindow, ASubWindowFeatures, WindowToolKit):
return self.ui.findChild(qtype, name)
class ASubWindow(QDialog, ASubWindowFeatures, WindowToolKit):
def __init__(self, name="", ui="dummy", parent=None):
def __init__(self, name="", ui="dummy", parent=None, **kwargs):
super(ASubWindow, self).__init__(parent=parent)
self.ui = loadUi(
os.path.join(os.path.dirname(__file__), "ui", f"{ui}.ui"),
os.path.abspath(
os.path.join(
os.path.dirname(__file__),
"..", "ui", f"{ui}.ui"
)
),
self
)
self.name = name
@@ -530,7 +540,12 @@ class AWidget(QWidget, ASubWindowFeatures):
def __init__(self, ui="", parent=None):
super(AWidget, self).__init__(parent=parent)
self.ui = loadUi(
os.path.join(os.path.dirname(__file__), "ui", "Widgets", f"{ui}.ui"),
os.path.abspath(
os.path.join(
os.path.dirname(__file__),
"..", "ui", "Widgets", f"{ui}.ui"
)
),
self
)
self.parent = parent
Loaded 100 of 117 files, more files were not shown because too many files have changed in this diff. Show more