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: artifacts:
paths: paths:
- doc/users/documentation.pdf - doc/users/documentation.pdf
- doc/users/documentation.html
- doc/users/images/
build-developers-doc: build-developers-doc:
stage: build stage: build
@@ -109,9 +111,19 @@ build-developers-doc:
script: script:
- cd ./doc/dev/ - cd ./doc/dev/
- ./build.sh - ./build.sh
# Create html documentation
- cd ../../src
- pdoc --html .
# Create archive
- tar cf html.tar ./html
- cd ../doc/dev
- mv ../../src/html.tar ./
artifacts: artifacts:
paths: paths:
- doc/dev/documentation.pdf - doc/dev/documentation.pdf
- doc/dev/documentation.html
- doc/dev/html.tar
- doc/dev/images/
build-linux: build-linux:
stage: build stage: build
@@ -167,8 +179,10 @@ build-linux:
- cp ../tests_cases/Saar/Saar.pamhyr pamhyr/tests_cases/Saar/ - cp ../tests_cases/Saar/Saar.pamhyr pamhyr/tests_cases/Saar/
# Copy documentations # Copy documentations
- mkdir -p pamhyr/doc/ - mkdir -p pamhyr/doc/
- mkdir -p pamhyr/doc/html/
- cp ../doc/users/documentation.pdf pamhyr/doc/Pamhyr2-users.pdf - cp ../doc/users/documentation.pdf pamhyr/doc/Pamhyr2-users.pdf
- cp ../doc/dev/documentation.pdf pamhyr/doc/Pamhyr2-dev.pdf - cp ../doc/dev/documentation.pdf pamhyr/doc/Pamhyr2-dev.pdf
- cp ../doc/dev/documentation.html pamhyr/doc/html/dev.html
# Create running script # Create running script
- echo "#!/bin/sh" > pamhyr/Pamhyr2 - echo "#!/bin/sh" > pamhyr/Pamhyr2
- echo "./pamhyr/pamhyr $@" >> pamhyr/Pamhyr2 - echo "./pamhyr/pamhyr $@" >> pamhyr/Pamhyr2
+11 -3
View File
@@ -1,10 +1,18 @@
#! /bin/sh #! /bin/sh
# Build the PDF echo " PDF documentation.org"
emacs -nw --batch \
emacs -Q -q -nw --batch \
--eval "(require 'org)" \ --eval "(require 'org)" \
--eval "(require 'ox-latex)" \ --eval "(require 'ox-latex)" \
--eval "(load-file \"../tools/setup.el\")" \ --eval "(load-file \"../tools/setup.el\")" \
--file ./documentation.org \ --file ./documentation.org \
-f org-latex-export-to-pdf -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 #! /bin/sh
# Build the PDF echo " PDF documentation.org"
emacs -nw --batch \
emacs -Q -q -nw --batch \
--eval "(require 'org)" \ --eval "(require 'org)" \
--eval "(require 'ox-latex)" \ --eval "(require 'ox-latex)" \
--eval "(load-file \"../tools/setup.el\")" \ --eval "(load-file \"../tools/setup.el\")" \
--file ./documentation.org \ --file ./documentation.org \
-f org-latex-export-to-pdf -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" echo " *** COPY DATA"
mkdir -p dist/pamhyr/View/ui mkdir -p dist/pamhyr/_internal/View/ui
mkdir -p dist/pamhyr/View/ui/Widgets mkdir -p dist/pamhyr/_internal/View/ui/Widgets
cp -r ../src/View/ui/ressources/ dist/pamhyr/View/ui/ cp -r ../src/View/ui/ressources/ dist/pamhyr/_internal/View/ui/
cp -r ../src/View/ui/Widgets/*.ui dist/pamhyr/View/ui/Widgets/ cp -r ../src/View/ui/Widgets/*.ui dist/pamhyr/_internal/View/ui/Widgets/
cp -r ../src/View/ui/*.ui dist/pamhyr/View/ui/ cp -r ../src/View/ui/*.ui dist/pamhyr/_internal/View/ui/
mkdir -p dist/pamhyr/lang mkdir -p dist/pamhyr/lang
cp -r ../src/lang/*.qm dist/pamhyr/lang/ cp -r ../src/lang/*.qm dist/pamhyr/lang/
cp ../VERSION dist/pamhyr/ mkdir dist/pamhyr/_internal/
cp ../AUTHORS dist/pamhyr/ #cp ../VERSION dist/pamhyr/_internal/
cp ../LICENSE dist/pamhyr/ 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/ mkdir -p dist/pamhyr/mage/
cp ../mage/mage 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 mkdir -p dist/pamhyr/tests_cases/Saar
cp ../tests_cases/Saar/Saar.pamhyr 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" echo " *** MAKE SRC PACKAGE"
OLD_PWD=$PWD OLD_PWD=$PWD
@@ -76,11 +91,11 @@ mv ../pamhyr-src.tar.gz ./
echo " *** MAKE BIN PACKAGE" echo " *** MAKE BIN PACKAGE"
OLD_PWD=$PWD # OLD_PWD=$PWD
cd dist/ # cd dist/
tar --xz -cf pamhyr-gnulinux-amd64.tar.xz pamhyr --checkpoint=.100 # tar --xz -cf pamhyr-gnulinux-amd64.tar.xz pamhyr --checkpoint=.100
cd $OLD_PWD # cd $OLD_PWD
mv dist/pamhyr-gnulinux-amd64.tar.xz ./ # mv dist/pamhyr-gnulinux-amd64.tar.xz ./
echo " *** DONE" echo " *** DONE"
+2 -1
View File
@@ -1,6 +1,7 @@
PyQt5==5.15.4 PyQt5==5.15.4
PyQt5-Qt5==5.15.2 PyQt5-Qt5==5.15.2
PyQt5-sip==12.8.1 PyQt5-sip==12.12.2
PyQtWebEngine==5.15.6
pyqtgraph>=0.12.1 pyqtgraph>=0.12.1
matplotlib>=3.4.1 matplotlib>=3.4.1
numpy>=1.24.2 numpy>=1.24.2
+3
View File
@@ -56,6 +56,9 @@ class Profile(object):
self._profile_type = _type self._profile_type = _type
def __len__(self):
return len(self._points)
@property @property
def number_points(self): def number_points(self):
return len(self._points) return len(self._points)
+4 -1
View File
@@ -42,7 +42,7 @@ class Reach(SQLSubModel):
] ]
def __init__(self, status=None, parent=None): 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._status = status
self._parent = parent self._parent = parent
self._profiles: List[Profile] = [] self._profiles: List[Profile] = []
@@ -106,6 +106,9 @@ class Reach(SQLSubModel):
return self._parent.name return self._parent.name
def __len__(self):
return len(self._profiles)
@property @property
def profiles(self): def profiles(self):
return self._profiles.copy() return self._profiles.copy()
+4
View File
@@ -43,6 +43,10 @@ class Results(object):
def river(self): def river(self):
return self._river return self._river
@property
def study(self):
return self._study
def set(self, key, value): def set(self, key, value):
self._meta_data[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._profile = profile # Source profile in the study
self._data = {} # Dict of dict {<ts>: {<key>: <value>, ...}, ...} self._data = {} # Dict of dict {<ts>: {<key>: <value>, ...}, ...}
def __len__(self):
return len(self._data)
@property @property
def name(self): def name(self):
return self._profile.name return self._profile.name
@@ -66,6 +69,9 @@ class Reach(object):
) )
) )
def __len__(self):
return len(self._profiles)
@property @property
def name(self): def name(self):
return self._reach.name return self._reach.name
@@ -91,6 +97,9 @@ class River(object):
# Dict with timestamps as key # Dict with timestamps as key
self._reachs = [] self._reachs = []
def __len__(self):
return len(self._reachs)
@property @property
def reachs(self): def reachs(self):
return self._reachs.copy() return self._reachs.copy()
+1 -1
View File
@@ -1,4 +1,4 @@
# help.py -- Pamhyr # Hello.py -- Pamhyr
# Copyright (C) 2023 INRAE # Copyright (C) 2023 INRAE
# #
# This program is free software: you can redistribute it and/or modify # 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 _translate = QCoreApplication.translate
solver_long_name = { solver_long_name = {
"generic": _translate("Solvers", "Generic"), "generic": "Generic",
# "mage7": _translate("Solvers", "Mage version 7"), # "mage7": "Mage v7",
"mage8": _translate("Solvers", "Mage version 8"), "mage8": "Mage v8",
} }
solver_type_list = { solver_type_list = {
+13 -6
View File
@@ -19,14 +19,17 @@
import os import os
import logging import logging
from View.ASubWindow import ASubWindow from View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class AboutWindow(ASubWindow): class AboutWindow(PamhyrDialog):
_pamhyr_ui = "about"
_pamhyr_name = "About"
def _path_file(self, filename): def _path_file(self, filename):
return os.path.abspath( return os.path.abspath(
os.path.join( os.path.join(
@@ -35,10 +38,14 @@ class AboutWindow(ASubWindow):
) )
) )
def __init__(self, study = None, config = None, parent=None):
def __init__(self, title="About", parent=None): super(AboutWindow, self).__init__(
super(AboutWindow, self).__init__(name=title, ui="about", parent=parent) title = _translate("About", "About"),
self.ui.setWindowTitle(title) study = study,
config = config,
options = [],
parent = parent
)
# Version # Version
with open(self._path_file("VERSION"), "r") as f: with open(self._path_file("VERSION"), "r") as f:
+14 -10
View File
@@ -21,27 +21,31 @@ import logging
from datetime import datetime from datetime import datetime
from tools import timer, trace from tools import timer, trace
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
) )
from View.BoundaryCondition.Edit.translate import * from View.BoundaryCondition.Edit.translate import BCETranslate
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class Plot(APlot): class Plot(PamhyrPlot):
def __init__(self, canvas=None, data=None, def __init__(self, mode = "time", data=None,
mode = "time", toolbar=None): trad=None, canvas=None, toolbar=None,
parent=None):
super(Plot, self).__init__( super(Plot, self).__init__(
canvas=canvas, canvas = canvas,
data=data, trad = trad,
toolbar=toolbar data = data,
toolbar = toolbar,
parent = parent
) )
self._table_headers = self._trad.get_dict("table_headers")
self._mode = mode self._mode = mode
def custom_ticks(self): def custom_ticks(self):
@@ -109,10 +113,10 @@ class Plot(APlot):
# Plot label # Plot label
header = self.data.header header = self.data.header
self.canvas.axes.set_xlabel( 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( 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) 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 tools import trace, timer
from View.ASubWindow import ASubMainWindow, AWidget
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrTable import PamhyrTableModel from View.Tools.PamhyrTable import PamhyrTableModel
from PyQt5.QtCore import ( from PyQt5.QtCore import (
@@ -48,7 +46,6 @@ from View.BoundaryCondition.Edit.UndoCommand import (
SortCommand, MoveCommand, PasteCommand, SortCommand, MoveCommand, PasteCommand,
DuplicateCommand, DuplicateCommand,
) )
from View.BoundaryCondition.Edit.translate import *
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
+37 -51
View File
@@ -20,8 +20,8 @@ import logging
from tools import timer, trace from tools import timer, trace
from View.ASubWindow import ASubMainWindow, AWidget from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow from View.Tools.PamhyrWidget import PamhyrWidget
from View.Tools.PamhyrDelegate import PamhyrExTimeDelegate from View.Tools.PamhyrDelegate import PamhyrExTimeDelegate
from PyQt5.QtGui import ( from PyQt5.QtGui import (
@@ -41,11 +41,10 @@ from PyQt5.QtWidgets import (
QHeaderView, QDoubleSpinBox, QVBoxLayout, QHeaderView, QDoubleSpinBox, QVBoxLayout,
) )
from View.Plot.MplCanvas import MplCanvas from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.BoundaryCondition.translate import long_types from View.BoundaryCondition.Edit.translate import BCETranslate
from View.BoundaryCondition.Edit.translate import table_headers, retranslate
from View.BoundaryCondition.Edit.UndoCommand import SetMetaDataCommand from View.BoundaryCondition.Edit.UndoCommand import SetMetaDataCommand
from View.BoundaryCondition.Edit.Table import TableModel from View.BoundaryCondition.Edit.Table import TableModel
from View.BoundaryCondition.Edit.Plot import Plot from View.BoundaryCondition.Edit.Plot import Plot
@@ -54,16 +53,16 @@ _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class WD50Sigma(AWidget): class WD50Sigma(PamhyrWidget):
_pamhyr_ui = "d50sigma"
d50Changed = pyqtSignal(float) d50Changed = pyqtSignal(float)
sigmaChanged = pyqtSignal(float) sigmaChanged = pyqtSignal(float)
def __init__(self, parent=None): def __init__(self, parent=None):
super(WD50Sigma, self).__init__( super(WD50Sigma, self).__init__(
ui="d50sigma",
parent=parent parent=parent
) )
self.parent = parent
self.spinBox_d50 = self.find(QDoubleSpinBox, "doubleSpinBox_d50") self.spinBox_d50 = self.find(QDoubleSpinBox, "doubleSpinBox_d50")
self.spinBox_sigma = self.find(QDoubleSpinBox, "doubleSpinBox_sigma") self.spinBox_sigma = self.find(QDoubleSpinBox, "doubleSpinBox_sigma")
@@ -95,46 +94,39 @@ class WD50Sigma(AWidget):
def valueChangedSigma(self, value): def valueChangedSigma(self, value):
self.sigmaChanged.emit(value) self.sigmaChanged.emit(value)
class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow): class EditBoundaryConditionWindow(PamhyrWindow):
def __init__(self, title="Edit boundary condition", _pamhyr_ui = "EditBoundaryConditions"
data=None, study=None, parent=None): _pamhyr_name = "Edit Boundary Conditions"
self._data = data
self._study = study
self._title = title
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__( 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_table()
self.setup_plot() self.setup_plot()
self.setup_data() self.setup_data()
self.setup_connections() 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): def setup_data(self):
self._is_solid = self._data.bctype == "SL" self._is_solid = self._data.bctype == "SL"
@@ -147,8 +139,8 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
self._d50sigma.set_sigma(self._data.sigma) self._d50sigma.set_sigma(self._data.sigma)
def setup_table(self): def setup_table(self):
retranslate()
headers = {} headers = {}
table_headers = self._trad.get_dict("table_headers")
for h in self._data.header: for h in self._data.header:
headers[h] = table_headers[h] headers[h] = table_headers[h]
@@ -189,21 +181,16 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
canvas = self.canvas, canvas = self.canvas,
data = self._data, data = self._data,
mode = self._study.time_system, mode = self._study.time_system,
trad = self._trad,
toolbar = self.toolbar, toolbar = self.toolbar,
) )
self.plot.draw() self.plot.draw()
def setup_connections(self): def setup_connections(self):
self.find(QAction, "action_add").triggered.connect(self.add) self.find(QAction, "action_add").triggered.connect(self.add)
self.find(QAction, "action_del").triggered.connect(self.delete) self.find(QAction, "action_del").triggered.connect(self.delete)
self.find(QAction, "action_sort").triggered.connect(self.sort) 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) self._table.dataChanged.connect(self.update)
if self._is_solid: if self._is_solid:
@@ -252,7 +239,6 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
) )
) )
def add(self): def add(self):
rows = self.index_selected_rows() rows = self.index_selected_rows()
if len(self._data) == 0 or len(rows) == 0: if len(self._data) == 0 or len(rows) == 0:
@@ -285,7 +271,7 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
self.plot.update() self.plot.update()
def copy(self): def _copy(self):
rows = self.index_selected_rows() rows = self.index_selected_rows()
table = [] table = []
@@ -297,7 +283,7 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
self.copyTableIntoClipboard(table) self.copyTableIntoClipboard(table)
def paste(self): def _paste(self):
header, data = self.parseClipboardTable() header, data = self.parseClipboardTable()
if len(data) == 0: if len(data) == 0:
@@ -311,12 +297,12 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
self._table.paste(row, header, data) self._table.paste(row, header, data)
self.plot.update() self.plot.update()
def undo(self): def _undo(self):
self._table.undo() self._table.undo()
self.plot.update() self.plot.update()
self.widget_update() self.widget_update()
def redo(self): def _redo(self):
self._table.redo() self._table.redo()
self.plot.update() self.plot.update()
self.widget_update() self.widget_update()
+16 -17
View File
@@ -18,23 +18,22 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
from View.BoundaryCondition.translate import BCTranslate
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
table_headers = { class BCETranslate(BCTranslate):
"x": _translate("BoundaryCondition", "X"), def __init__(self):
"y": _translate("BoundaryCondition", "Y"), super(BCETranslate, self).__init__()
"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)"),
}
def retranslate(): self._sub_dict["table_headers"] = {
table_headers["x"] = _translate("BoundaryCondition", "X") "x": _translate("BoundaryCondition", "X"),
table_headers["y"] = _translate("BoundaryCondition", "Y") "y": _translate("BoundaryCondition", "Y"),
table_headers["time"] = _translate("BoundaryCondition", "Time") "time": _translate("BoundaryCondition", "Time"),
table_headers["date"] = _translate("BoundaryCondition", "Date") "date": _translate("BoundaryCondition", "Date"),
table_headers["discharge"] = _translate("BoundaryCondition", "Discharge (m³/s)") "discharge": _translate("BoundaryCondition", "Discharge (m³/s)"),
table_headers["z"] = _translate("BoundaryCondition", "Z (m)") "z": _translate("BoundaryCondition", "Z (m)"),
table_headers["solid"] = _translate("BoundaryCondition", "Solid (kg/s)") "solid": _translate("BoundaryCondition", "Solid (kg/s)"),
}
+17 -5
View File
@@ -46,19 +46,24 @@ from View.BoundaryCondition.UndoCommand import (
AddCommand, DelCommand, SortCommand, AddCommand, DelCommand, SortCommand,
MoveCommand, PasteCommand, DuplicateCommand, MoveCommand, PasteCommand, DuplicateCommand,
) )
from View.BoundaryCondition.translate import * from View.BoundaryCondition.translate import BC_types
logger = logging.getLogger() logger = logging.getLogger()
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class ComboBoxDelegate(QItemDelegate): 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) super(ComboBoxDelegate, self).__init__(parent)
self._data = data self._data = data
self._mode = mode self._mode = mode
self._tab = tab 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): def createEditor(self, parent, option, index):
self.editor = QComboBox(parent) self.editor = QComboBox(parent)
@@ -66,7 +71,7 @@ class ComboBoxDelegate(QItemDelegate):
if self._mode == "type": if self._mode == "type":
lst = list( lst = list(
map( map(
lambda k: long_types[k], lambda k: self._long_types[k],
filter( filter(
lambda k: self._tab in BC_types[k].compatibility(), lambda k: self._tab in BC_types[k].compatibility(),
BC_types.keys() BC_types.keys()
@@ -107,6 +112,13 @@ class ComboBoxDelegate(QItemDelegate):
class TableModel(PamhyrTableModel): 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): def _setup_lst(self):
self._lst = self._data.boundary_condition self._lst = self._data.boundary_condition
self._tab = self._opt_data self._tab = self._opt_data
@@ -125,7 +137,7 @@ class TableModel(PamhyrTableModel):
return self._lst.get(self._tab, row).name return self._lst.get(self._tab, row).name
elif self._headers[column] == "type": elif self._headers[column] == "type":
t = self._lst.get(self._tab, row).bctype t = self._lst.get(self._tab, row).bctype
return long_types[t] return self._long_types[t]
elif self._headers[column] == "node": elif self._headers[column] == "node":
n = self._lst.get(self._tab, row).node n = self._lst.get(self._tab, row).node
if n is None: if n is None:
@@ -149,7 +161,7 @@ class TableModel(PamhyrTableModel):
) )
) )
elif self._headers[column] == "type": 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( self._undo.push(
SetTypeCommand( SetTypeCommand(
self._lst, self._tab,row, BC_types[key] self._lst, self._tab,row, BC_types[key]
+21 -28
View File
@@ -20,8 +20,7 @@ import logging
from tools import trace, timer from tools import trace, timer
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -56,51 +55,49 @@ from View.BoundaryCondition.Table import (
) )
from View.Network.GraphWidget import GraphWidget 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 from View.BoundaryCondition.Edit.Window import EditBoundaryConditionWindow
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow): class BoundaryConditionWindow(PamhyrWindow):
def __init__(self, title="Boundary conditions", study=None, parent=None): _pamhyr_ui = "BoundaryConditions"
self._title = title + " - " + study.name _pamhyr_name = "Boundary conditions"
def __init__(self, study=None, config=None, parent=None):
name = self._pamhyr_name + " - " + study.name
super(BoundaryConditionWindow, self).__init__( 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._bcs = self._study.river.boundary_condition
self.setup_sc()
self.setup_table() self.setup_table()
self.setup_graph() self.setup_graph()
self.setup_connections() self.setup_connections()
self.ui.setWindowTitle(self._title) 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): def setup_table(self):
retranslate()
self._table = {} self._table = {}
for t in ["liquid", "solid", "suspenssion"]: for t in ["liquid", "solid", "suspenssion"]:
self._delegate_type = ComboBoxDelegate( self._delegate_type = ComboBoxDelegate(
trad = self._trad,
data = self._study.river, data = self._study.river,
mode = "type", mode = "type",
tab = t, tab = t,
parent=self parent=self
) )
self._delegate_node = ComboBoxDelegate( self._delegate_node = ComboBoxDelegate(
trad = self._trad,
data = self._study.river, data = self._study.river,
mode = "node", mode = "node",
tab = t, tab = t,
@@ -110,12 +107,13 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
table = self.find(QTableView, f"tableView_{t}") table = self.find(QTableView, f"tableView_{t}")
self._table[t] = TableModel( self._table[t] = TableModel(
table_view = table, table_view = table,
table_headers = table_headers, table_headers = self._trad.get_dict("table_headers"),
editable_headers = ["name", "type", "node"], editable_headers = ["name", "type", "node"],
delegates = { delegates = {
"type": self._delegate_type, "type": self._delegate_type,
"node": self._delegate_node, "node": self._delegate_node,
}, },
trad = self._trad,
data = self._study.river, data = self._study.river,
undo = self._undo_stack, undo = self._undo_stack,
opt_data = t, opt_data = t,
@@ -141,11 +139,6 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
self.find(QAction, "action_edit").triggered.connect(self.edit) self.find(QAction, "action_edit").triggered.connect(self.edit)
self.find(QAction, "action_sort").triggered.connect(self.sort) 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): def current_tab(self):
return self.find(QTabWidget, "tabWidget")\ return self.find(QTabWidget, "tabWidget")\
.currentWidget()\ .currentWidget()\
@@ -202,17 +195,17 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
row = self.index_selected_row() row = self.index_selected_row()
self._table[tab].move_down(row) self._table[tab].move_down(row)
def copy(self): def _copy(self):
logger.info("TODO: copy") logger.info("TODO: copy")
def paste(self): def _paste(self):
logger.info("TODO: paste") logger.info("TODO: paste")
def undo(self): def _undo(self):
tab = self.current_tab() tab = self.current_tab()
self._table[tab].undo() self._table[tab].undo()
def redo(self): def _redo(self):
tab = self.current_tab() tab = self.current_tab()
self._table[tab].redo() self._table[tab].redo()
+20 -19
View File
@@ -18,6 +18,8 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
from Model.BoundaryCondition.BoundaryConditionTypes import ( from Model.BoundaryCondition.BoundaryConditionTypes import (
NotDefined, PonctualContribution, NotDefined, PonctualContribution,
TimeOverZ, TimeOverDischarge, ZOverDischarge, TimeOverZ, TimeOverDischarge, ZOverDischarge,
@@ -26,21 +28,6 @@ from Model.BoundaryCondition.BoundaryConditionTypes import (
_translate = QCoreApplication.translate _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 = { BC_types = {
"ND": NotDefined, "ND": NotDefined,
"PC": PonctualContribution, "PC": PonctualContribution,
@@ -50,7 +37,21 @@ BC_types = {
"SL": Solid, "SL": Solid,
} }
def retranslate(): class BCTranslate(PamhyrTranslate):
table_headers["name"] = _translate("BoundaryCondition", "Name") def __init__(self):
table_headers["type"] = _translate("BoundaryCondition", "Type") super(BCTranslate, self).__init__()
table_headers["node"] = _translate("BoundaryCondition", "Node")
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, QComboBox,
) )
from View.Tools.PamhyrTable import PamhyrTableModel
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class TableModel(QAbstractTableModel): class TableModel(PamhyrTableModel):
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)
def data(self, index, role): def data(self, index, role):
row = index.row() row = index.row()
column = index.column() column = index.column()
@@ -81,12 +68,3 @@ class TableModel(QAbstractTableModel):
return self._data[row].summary return self._data[row].summary
return QVariant() 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 tools import trace, timer
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -41,33 +40,36 @@ from PyQt5.QtWidgets import (
from View.CheckList.Table import TableModel from View.CheckList.Table import TableModel
from View.CheckList.Worker import Worker from View.CheckList.Worker import Worker
from View.CheckList.Translate import CheckListTranslate
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class CheckListWindow(ASubMainWindow, ListedSubWindow): class CheckListWindow(PamhyrWindow):
_pamhyr_ui = "CheckList"
_pamhyr_name = "Check list"
signalStatus = pyqtSignal(str) signalStatus = pyqtSignal(str)
def __init__(self, title="Check list", def __init__(self, autorun:bool=True,
autorun:bool=True,
study=None, config=None, study=None, config=None,
solver=None, parent=None): solver=None, parent=None):
self._title = title + " - " + study.name
self._autorun = autorun self._autorun = autorun
self._study = study
self._config = config
self._solver = solver self._solver = solver
self._parent = parent
name = self._pamhyr_name + " - " + study.name
super(CheckListWindow, self).__init__( 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._checker_list = (
self._study.checkers() + self._solver.checkers() self._study.checkers() +
self._solver.checkers()
) )
self.setup_table() self.setup_table()
@@ -78,16 +80,12 @@ class CheckListWindow(ASubMainWindow, ListedSubWindow):
def setup_table(self): def setup_table(self):
table = self.find(QTableView, f"tableView") table = self.find(QTableView, f"tableView")
self._table = TableModel( self._table = TableModel(
table_view = table,
table_headers = self._trad.get_dict("table_headers"),
data = self._checker_list, 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): def setup_progress_bar(self):
self._progress = self.find(QProgressBar, f"progressBar") self._progress = self.find(QProgressBar, f"progressBar")
self._p = 0 # Progress current step self._p = 0 # Progress current step
+18 -8
View File
@@ -16,7 +16,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from View.ASubWindow import ASubWindow from View.Tools.PamhyrWindow import PamhyrDialog
from Solver.Solvers import solver_type_list from Solver.Solvers import solver_type_list
from Solver.GenericSolver import GenericSolver from Solver.GenericSolver import GenericSolver
@@ -24,12 +24,22 @@ from PyQt5.QtWidgets import (
QPushButton, QPushButton,
) )
class ConfigureSolverWindow(ASubWindow): class ConfigureSolverWindow(PamhyrDialog):
def __init__(self, data=None, title="Configuration : Add Solver", parent=None): _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__( super(ConfigureSolverWindow, self).__init__(
name=title, ui="ConfigureAddSolverDialog", parent=parent title = name,
config = config,
options = [],
parent=parent
) )
self.ui.setWindowTitle(title)
# Combo box item # Combo box item
for solver in solver_type_list: for solver in solver_type_list:
@@ -37,10 +47,10 @@ class ConfigureSolverWindow(ASubWindow):
# Data to return # Data to return
self.data = data self.data = data
if not self.data is None: if self.data is not None:
self.copy_data() self.copy_data()
self.connect() self.setup_connection()
def copy_data(self): def copy_data(self):
self.set_combobox_text("comboBox_solver", self.data.type) 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", self.data._path_output)
self.set_line_edit_text("lineEdit_output_cmd", self.data._cmd_output) self.set_line_edit_text("lineEdit_output_cmd", self.data._cmd_output)
def connect(self): def setup_connection(self):
# File button # File button
buttons = { buttons = {
"pushButton_input": (lambda: self.file_dialog( "pushButton_input": (lambda: self.file_dialog(
+58 -59
View File
@@ -21,8 +21,7 @@ import logging
from copy import deepcopy from copy import deepcopy
from config import Config from config import Config
from View.ASubWindow import ASubWindow from View.Tools.PamhyrWindow import PamhyrDialog
from View.ListedSubWindow import ListedSubWindow
from View.Stricklers.Table import TableModel from View.Stricklers.Table import TableModel
from View.Stricklers.translate import * from View.Stricklers.translate import *
@@ -95,50 +94,42 @@ class SolverTableModel(QAbstractTableModel):
self.layoutChanged.emit() self.layoutChanged.emit()
class ConfigureWindow(ASubWindow, ListedSubWindow): class ConfigureWindow(PamhyrDialog):
def __init__(self, conf=None, title="Configure", parent=None): _pamhyr_ui = "ConfigureDialog"
_pamhyr_name = "Configure"
def __init__(self, config=None, parent=None):
if config is None:
config = Config()
super(ConfigureWindow, self).__init__( 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.setup_custom_sc()
self.conf = Config() self.setup_solver()
else: self.setup_stricklers()
self.conf = conf self.setup_data()
self.setup_connection()
self.setup_sc() def setup_solver(self):
# Solver
table = self.find(QTableView, "tableView_solver") table = self.find(QTableView, "tableView_solver")
self.solver_table_model = SolverTableModel( self.solver_table_model = SolverTableModel(
headers = ["name", "type", "description"], headers = ["name", "type", "description"],
rows = conf.solvers rows = self._config.solvers
) )
table.setModel(self.solver_table_model) table.setModel(self.solver_table_model)
table.setSelectionBehavior(QAbstractItemView.SelectRows) table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True) table.setAlternatingRowColors(True)
table.resizeColumnsToContents()
# Meshing_Tool def setup_stricklers(self):
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
table = self.find(QTableView, f"tableView_stricklers") table = self.find(QTableView, f"tableView_stricklers")
self._stricklers = deepcopy(self.conf.stricklers) self._stricklers = deepcopy(self._config.stricklers)
self._stricklers_table = TableModel( self._stricklers_table = TableModel(
data = self._stricklers, data = self._stricklers,
undo = self._undo_stack, undo = self._undo_stack,
@@ -148,26 +139,35 @@ class ConfigureWindow(ASubWindow, ListedSubWindow):
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True) 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 # 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 # Language
languages = Config.languages() languages = Config.languages()
for lang in languages: for lang in languages:
self.combobox_add_item("comboBox_language", lang) 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) self.set_combobox_text("comboBox_language", lang)
def setup_sc(self): def setup_custom_sc(self):
self._undo_stack = QUndoStack() self._debug_sc = QShortcut(QKeySequence("Ctrl+G"), self)
self._debug_sc.activated.connect(self.set_debug)
self.debug_sc = QShortcut(QKeySequence("Ctrl+G"), self) def setup_connection(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):
buttons = { buttons = {
# Solvers # Solvers
"pushButton_solver_add": self.add_solver, "pushButton_solver_add": self.add_solver,
@@ -195,33 +195,31 @@ class ConfigureWindow(ASubWindow, ListedSubWindow):
for button in buttons: for button in buttons:
self.find(QPushButton, button).clicked.connect(buttons[button]) self.find(QPushButton, button).clicked.connect(buttons[button])
self.debug_sc.activated.connect(self.set_debug)
def accept(self): def accept(self):
# Solvers # Solvers
self.conf.solvers = self.solver_table_model.rows.copy() self._config.solvers = self.solver_table_model.rows.copy()
# Meshing_Tool # 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 # Const
self.conf.segment = self.get_line_edit_text("lineEdit_segment") self._config.segment = self.get_line_edit_text("lineEdit_segment")
self.conf.max_listing = self.get_line_edit_text("lineEdit_max_listing") self._config.max_listing = self.get_line_edit_text("lineEdit_max_listing")
# Backup # Backup
self.conf.backup_enable = self.get_check_box("checkBox_backup") self._config.backup_enable = self.get_check_box("checkBox_backup")
self.conf.backup_path = self.get_line_edit_text("lineEdit_backup_path") self._config.backup_path = self.get_line_edit_text("lineEdit_backup_path")
self.conf.backup_frequence = self.get_time_edit("timeEdit_backup_frequence") self._config.backup_frequence = self.get_time_edit("timeEdit_backup_frequence")
self.conf.backup_max = self.get_spin_box("spinBox_backup_max") self._config.backup_max = self.get_spin_box("spinBox_backup_max")
# Stricklers # Stricklers
self.conf.stricklers = deepcopy(self._stricklers) self._config.stricklers = deepcopy(self._stricklers)
# Editor # Editor
self.conf.editor = self.get_line_edit_text("lineEdit_editor_cmd") self._config.editor = self.get_line_edit_text("lineEdit_editor_cmd")
# Language # 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() self.end()
@@ -230,13 +228,13 @@ class ConfigureWindow(ASubWindow, ListedSubWindow):
self.end() self.end()
def end(self): def end(self):
self.conf.save() self._config.save()
self.close() self.close()
# Debug # Debug
def set_debug(self): def set_debug(self):
self.conf.debug = not self.conf.debug self._config.debug = not self._config.debug
logger.info(f"Debug mode set : {self.conf.debug}") logger.info(f"Debug mode set : {self._config.debug}")
self.parent.setup_debug_mode() self.parent.setup_debug_mode()
# Solvers # Solvers
@@ -246,6 +244,7 @@ class ConfigureWindow(ASubWindow, ListedSubWindow):
for index in indexes: for index in indexes:
self.edit_solver = ConfigureSolverWindow( self.edit_solver = ConfigureSolverWindow(
data=self.solver_table_model.rows[index.row()], data=self.solver_table_model.rows[index.row()],
config=self._config,
parent=self parent=self
) )
if self.edit_solver.exec_(): if self.edit_solver.exec_():
+11 -13
View File
@@ -20,8 +20,7 @@ import logging
from tools import trace, timer from tools import trace, timer
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -45,20 +44,19 @@ logger = logging.getLogger()
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class ReplWindow(ASubMainWindow, ListedSubWindow): class ReplWindow(PamhyrWindow):
def __init__(self, title="Debug REPL", _pamhyr_ui = "DebugRepl"
study=None, config=None, _pamhyr_name = "Debug REPL"
def __init__(self, study=None, config=None,
solver=None, parent=None): solver=None, parent=None):
self._title = title
self._study = study
self._config = config
self._parent = parent
super(ReplWindow, self).__init__( 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.__debug_exec_result__ = None
self._history = [] 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 -*- # -*- coding: utf-8 -*-
from View.ASubWindow import ASubWindow from View.Tools.PamhyrWindow import PamhyrWindow
class DummyWindow(ASubWindow): class DummyWindow(PamhyrWindow):
def __init__(self, title="Dummy", parent=None): __ui = "Dummy"
super(DummyWindow, self).__init__(name=title, ui="dummy", parent=parent) __name = "Pamhyr Dummy Window"
self.ui.setWindowTitle(title)
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 -*- # -*- coding: utf-8 -*-
from tools import timer, flatten from tools import timer, flatten
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -25,14 +25,7 @@ from PyQt5.QtCore import (
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class PlotStricklers(APlot): class PlotStricklers(PamhyrPlot):
def __init__(self, canvas=None, data=None, toolbar=None):
super(PlotStricklers, self).__init__(
canvas=canvas,
data=data,
toolbar=toolbar
)
def draw_frictions(self, frictions, color="r"): def draw_frictions(self, frictions, color="r"):
lst = frictions lst = frictions
lst.sort(key = lambda s: s.begin_kp) lst.sort(key = lambda s: s.begin_kp)
+22 -42
View File
@@ -41,6 +41,8 @@ from View.Frictions.UndoCommand import (
MoveCommand, PasteCommand, DuplicateCommand, MoveCommand, PasteCommand, DuplicateCommand,
) )
from View.Tools.PamhyrTable import PamhyrTableModel
from View.Frictions.translate import * from View.Frictions.translate import *
logger = logging.getLogger() logger = logging.getLogger()
@@ -93,26 +95,10 @@ class ComboBoxDelegate(QItemDelegate):
self.commitData.emit(self.sender()) self.commitData.emit(self.sender())
class TableModel(QAbstractTableModel): class TableModel(PamhyrTableModel):
def __init__(self, data=None, study=None, undo=None): def _setup_lst(self):
super(QAbstractTableModel, self).__init__() self._lst = self._data.frictions
self._headers = list(table_headers.keys()) self._study = self._opt_data
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)
def data(self, index, role): def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole: if role != Qt.ItemDataRole.DisplayRole:
@@ -122,30 +108,24 @@ class TableModel(QAbstractTableModel):
column = index.column() column = index.column()
if self._headers[column] == "name": if self._headers[column] == "name":
return self._frictions.get(row).name return self._lst.get(row).name
elif self._headers[column] == "begin_kp": 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": 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": elif self._headers[column] == "begin_strickler":
value = self._frictions.get(row).begin_strickler value = self._lst.get(row).begin_strickler
if value == None: if value == None:
return _translate("Frictions", "Not defined") return _translate("Frictions", "Not defined")
return str(value) return str(value)
elif self._headers[column] == "end_strickler": elif self._headers[column] == "end_strickler":
value = self._frictions.get(row).end_strickler value = self._lst.get(row).end_strickler
if value == None: if value == None:
return _translate("Frictions", "Not defined") return _translate("Frictions", "Not defined")
return str(value) return str(value)
return QVariant() 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): def setData(self, index, value, role=Qt.EditRole):
if not index.isValid() or role != Qt.EditRole: if not index.isValid() or role != Qt.EditRole:
return False return False
@@ -157,31 +137,31 @@ class TableModel(QAbstractTableModel):
if self._headers[column] == "name": if self._headers[column] == "name":
self._undo.push( self._undo.push(
SetNameCommand( SetNameCommand(
self._frictions, row, value self._lst, row, value
) )
) )
elif self._headers[column] == "begin_kp": elif self._headers[column] == "begin_kp":
self._undo.push( self._undo.push(
SetBeginCommand( SetBeginCommand(
self._frictions, row, value self._lst, row, value
) )
) )
elif self._headers[column] == "end_kp": elif self._headers[column] == "end_kp":
self._undo.push( self._undo.push(
SetEndCommand( SetEndCommand(
self._frictions, row, value self._lst, row, value
) )
) )
elif self._headers[column] == "begin_strickler": elif self._headers[column] == "begin_strickler":
self._undo.push( self._undo.push(
SetBeginStricklerCommand( SetBeginStricklerCommand(
self._frictions, row, self._study.river.strickler(value) self._lst, row, self._study.river.strickler(value)
) )
) )
elif self._headers[column] == "end_strickler": elif self._headers[column] == "end_strickler":
self._undo.push( self._undo.push(
SetEndStricklerCommand( SetEndStricklerCommand(
self._frictions, row, self._study.river.strickler(value) self._lst, row, self._study.river.strickler(value)
) )
) )
except Exception as e: except Exception as e:
@@ -196,7 +176,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
AddCommand( AddCommand(
self._frictions, row, self._data self._lst, row, self._data
) )
) )
@@ -208,7 +188,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
DelCommand( DelCommand(
self._frictions, rows self._lst, rows
) )
) )
@@ -220,7 +200,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
SortCommand( SortCommand(
self._frictions, False self._lst, False
) )
) )
@@ -237,7 +217,7 @@ class TableModel(QAbstractTableModel):
self._undo_stack.push( self._undo_stack.push(
MoveCommand( MoveCommand(
self._frictions, "up", row self._lst, "up", row
) )
) )
@@ -245,7 +225,7 @@ class TableModel(QAbstractTableModel):
self.layoutChanged.emit() self.layoutChanged.emit()
def move_down(self, index, parent=QModelIndex()): def move_down(self, index, parent=QModelIndex()):
if row > len(self._frictions): if row > len(self._lst):
return return
target = row target = row
@@ -254,7 +234,7 @@ class TableModel(QAbstractTableModel):
self._undo_stack.push( self._undo_stack.push(
MoveCommand( 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 tools import trace, timer
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -48,63 +47,49 @@ from View.Frictions.Table import (
TableModel, ComboBoxDelegate TableModel, ComboBoxDelegate
) )
from View.Plot.MplCanvas import MplCanvas from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Geometry.PlotKPZ import PlotKPZ from View.Geometry.PlotKPZ import PlotKPZ
from View.Frictions.PlotStricklers import PlotStricklers 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 from View.Stricklers.Window import StricklersWindow
_translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class FrictionsWindow(ASubMainWindow, ListedSubWindow): class FrictionsWindow(PamhyrWindow):
def __init__(self, title="Frictions", study=None, parent=None): _pamhyr_ui = "Frictions"
self._study = study _pamhyr_name = "Edit frictions"
self._reach = self._study.river.current_reach()
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._frictions = self._reach.frictions
self.setup_title(title) name = (
self._pamhyr_name + " - "
super(FrictionsWindow, self).__init__( + study.name + " - "
name=title, ui="Frictions", parent=parent + 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_table()
self.setup_graph() self.setup_graph()
self.setup_connections() 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): def setup_table(self):
retranslate()
self._table = {} 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( self._delegate_stricklers = ComboBoxDelegate(
data = self._reach, data = self._reach,
study = self._study, study = self._study,
@@ -112,13 +97,23 @@ class FrictionsWindow(ASubMainWindow, ListedSubWindow):
parent=self parent=self
) )
table.setItemDelegateForColumn( table = self.find(QTableView, f"tableView")
3, self._delegate_stricklers 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( table.setModel(self._table)
4, self._delegate_stricklers
)
table.setSelectionBehavior(QAbstractItemView.SelectRows) table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True) table.setAlternatingRowColors(True)
@@ -156,11 +151,6 @@ class FrictionsWindow(ASubMainWindow, ListedSubWindow):
self.find(QAction, "action_sort").triggered.connect(self.sort) self.find(QAction, "action_sort").triggered.connect(self.sort)
self.find(QAction, "action_edit_stricklers").triggered.connect(self.edit_stricklers) 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 = self.find(QTableView, f"tableView")
table.selectionModel()\ table.selectionModel()\
.selectionChanged\ .selectionChanged\
@@ -234,16 +224,16 @@ class FrictionsWindow(ASubMainWindow, ListedSubWindow):
row = self.index_selected_row() row = self.index_selected_row()
self._table.move_down(row) self._table.move_down(row)
def copy(self): def _copy(self):
logger.info("TODO: copy") logger.info("TODO: copy")
def paste(self): def _paste(self):
logger.info("TODO: paste") logger.info("TODO: paste")
def undo(self): def _undo(self):
self._table.undo() self._table.undo()
def redo(self): def _redo(self):
self._table.redo() self._table.redo()
def edit_stricklers(self): def edit_stricklers(self):
+13 -15
View File
@@ -18,21 +18,19 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
table_headers = { class FrictionsTranslate(PamhyrTranslate):
"name": _translate("Frictions", "Name"), def __init__(self):
# "edge": _translate("Frictions", "Reach"), super(FrictionsTranslate, self).__init__()
"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"),
}
def retranslate(): self._sub_dict["table_headers"] = {
table_headers["name"] = _translate("Frictions", "Name") "name": _translate("Frictions", "Name"),
# table_headers["edge"] = _translate("Frictions", "Reach") # "edge": _translate("Frictions", "Reach"),
table_headers["begin_kp"] = _translate("Frictions", "Begin kp (m)") "begin_kp": _translate("Frictions", "Begin kp (m)"),
table_headers["end_kp"] = _translate("Frictions", "End kp (m)") "end_kp": _translate("Frictions", "End kp (m)"),
table_headers["begin_strickler"] = _translate("Frictions", "Begin strickler") "begin_strickler": _translate("Frictions", "Begin strickler"),
table_headers["end_strickler"] = _translate("Frictions", "End strickler") "end_strickler": _translate("Frictions", "End strickler"),
}
+9 -6
View File
@@ -19,7 +19,7 @@
import logging import logging
from tools import timer from tools import timer
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -29,12 +29,15 @@ _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class PlotAC(APlot): class PlotAC(PamhyrPlot):
def __init__(self, canvas=None, data=None, toolbar=None, plot_xy=None): def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
plot_xy=None, parent=None):
super(PlotAC, self).__init__( super(PlotAC, self).__init__(
canvas=canvas, canvas = canvas,
data=data, trad = trad,
toolbar=toolbar data = data,
toolbar = toolbar,
parent = parent
) )
self.plot_xy = plot_xy self.plot_xy = plot_xy
+9 -7
View File
@@ -19,7 +19,7 @@
import logging import logging
from tools import timer from tools import timer
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -29,13 +29,15 @@ _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class PlotKPZ(APlot): class PlotKPZ(PamhyrPlot):
def __init__(self, canvas=None, data=None, toolbar=None, def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
display_current=True): display_current=True, parent=None):
super(PlotKPZ, self).__init__( super(PlotKPZ, self).__init__(
canvas=canvas, canvas = canvas,
data=data, trad = trad,
toolbar=toolbar data = data,
toolbar = toolbar,
parent = parent
) )
self.display_current = display_current self.display_current = display_current
+11 -8
View File
@@ -17,7 +17,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from tools import timer, trace from tools import timer, trace
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -25,12 +25,15 @@ from PyQt5.QtCore import (
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class PlotXY(APlot): class PlotXY(PamhyrPlot):
def __init__(self, canvas=None, data=None, toolbar=None, display_current=True): def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
display_current=True, parent=None):
super(PlotXY, self).__init__( super(PlotXY, self).__init__(
canvas=canvas, canvas = canvas,
data=data, trad = trad,
toolbar=toolbar data = data,
toolbar = toolbar,
parent = parent
) )
self.display_current = display_current self.display_current = display_current
@@ -60,11 +63,11 @@ class PlotXY(APlot):
# Axes # Axes
self.canvas.axes.set_xlabel( self.canvas.axes.set_xlabel(
_translate("MainWindow_reach", "X (m)"), _translate("Geometry", "X (m)"),
color='green', fontsize=12 color='green', fontsize=12
) )
self.canvas.axes.set_ylabel( self.canvas.axes.set_ylabel(
_translate("MainWindow_reach", "Y (m)"), _translate("Geometry", "Y (m)"),
color='green', fontsize=12 color='green', fontsize=12
) )
self.canvas.axes.axis("equal") self.canvas.axes.axis("equal")
+10 -7
View File
@@ -19,8 +19,8 @@
import logging import logging
from tools import timer, trace from tools import timer, trace
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from View.Plot.mpl_canvas_onpick_event import OnpickEvent from View.Tools.Plot.OnPickEvent import OnpickEvent
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -30,12 +30,15 @@ _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class Plot(APlot): class Plot(PamhyrPlot):
def __init__(self, canvas=None, data=None, toolbar=None, table=None): def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
table=None, parent=None):
super(Plot, self).__init__( super(Plot, self).__init__(
canvas=canvas, canvas = canvas,
data=data, trad = trad,
toolbar=toolbar data = data,
toolbar = toolbar,
parent = parent
) )
self._table = table self._table = table
+46 -104
View File
@@ -29,10 +29,11 @@ from PyQt5.QtWidgets import (
QMessageBox, QStyledItemDelegate, QLineEdit QMessageBox, QStyledItemDelegate, QLineEdit
) )
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QModelIndex, Qt, QAbstractTableModel, QModelIndex, Qt, QVariant, QCoreApplication
QVariant, QCoreApplication
) )
from View.Tools.PamhyrTable import PamhyrTableModel
from Model.Geometry.PointXYZ import PointXYZ from Model.Geometry.PointXYZ import PointXYZ
from Model.Geometry.ProfileXYZ import ProfileXYZ from Model.Geometry.ProfileXYZ import ProfileXYZ
@@ -43,43 +44,22 @@ logger = logging.getLogger()
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class TableEditableModel(QAbstractTableModel): class GeometryProfileTableModel(PamhyrTableModel):
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)
def data(self, index, role=Qt.DisplayRole): def data(self, index, role=Qt.DisplayRole):
if index.isValid(): if index.isValid():
if role == Qt.DisplayRole: if role == Qt.DisplayRole:
value = "" value = ""
if index.column() == 0: if index.column() == 0:
value = self._profile.point(index.row()).x value = self._data.point(index.row()).x
elif index.column() == 1: elif index.column() == 1:
value = self._profile.point(index.row()).y value = self._data.point(index.row()).y
elif index.column() == 2: elif index.column() == 2:
value = self._profile.point(index.row()).z value = self._data.point(index.row()).z
elif index.column() == 3: elif index.column() == 3:
value = self._profile.point(index.row()).name value = self._data.point(index.row()).name
elif index.column() == 4: elif index.column() == 4:
station = self._profile.get_station() station = self._data.get_station()
if station is None: if station is None:
return "-" return "-"
else: else:
@@ -95,25 +75,25 @@ class TableEditableModel(QAbstractTableModel):
return Qt.AlignHCenter | Qt.AlignVCenter return Qt.AlignHCenter | Qt.AlignVCenter
if index.column() == 2: if index.column() == 2:
value = self._profile.point(index.row()).z value = self._data.point(index.row()).z
if role == Qt.ForegroundRole: if role == Qt.ForegroundRole:
if value == self._profile.z_min(): if value == self._data.z_min():
return QColor("red") return QColor("red")
elif value == self._profile.z_max(): elif value == self._data.z_max():
return QColor("blue") return QColor("blue")
if role == Qt.ToolTipRole: if role == Qt.ToolTipRole:
if value == self._profile.z_min(): if value == self._data.z_min():
return _translate("MainWindowProfile", return _translate("MainWindowProfile",
"La cote du fond", "La cote du fond",
"Z minimale") "Z minimale")
elif value == self._profile.z_max(): elif value == self._data.z_max():
return _translate("MainWindowProfile", return _translate("MainWindowProfile",
"La cote maximale", "La cote maximale",
"Z maximale") "Z maximale")
if index.column() == 3: 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 value.strip().upper() in ["RG", "RD"]:
if role == Qt.FontRole: if role == Qt.FontRole:
@@ -132,21 +112,6 @@ class TableEditableModel(QAbstractTableModel):
return QVariant() 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): def setData(self, index, value, role=Qt.EditRole):
row = index.row() row = index.row()
column = index.column() column = index.column()
@@ -154,34 +119,34 @@ class TableEditableModel(QAbstractTableModel):
if role == Qt.EditRole: if role == Qt.EditRole:
try: try:
if column == 0: if column == 0:
self._undo_stack.push( self._undo.push(
SetXCommand( SetXCommand(
self._profile, row, self._data, row,
self._profile.point(row).x, self._data.point(row).x,
value value
) )
) )
elif column == 1: elif column == 1:
self._undo_stack.push( self._undo.push(
SetYCommand( SetYCommand(
self._profile, row, self._data, row,
self._profile.point(row).y, self._data.point(row).y,
value value
) )
) )
elif column == 2: elif column == 2:
self._undo_stack.push( self._undo.push(
SetZCommand( SetZCommand(
self._profile, row, self._data, row,
self._profile.point(row).z, self._data.point(row).z,
value value
) )
) )
elif column == 3: elif column == 3:
self._undo_stack.push( self._undo.push(
SetNameCommand( SetNameCommand(
self._profile, row, self._data, row,
self._profile.point(row).name, self._data.point(row).name,
value value
) )
) )
@@ -213,9 +178,9 @@ class TableEditableModel(QAbstractTableModel):
def insert_row(self, row, parent=QModelIndex()): def insert_row(self, row, parent=QModelIndex()):
self.beginInsertRows(parent, row, row - 1) self.beginInsertRows(parent, row, row - 1)
self._undo_stack.push( self._undo.push(
AddCommand( AddCommand(
self._profile, row self._data, row
) )
) )
@@ -225,9 +190,9 @@ class TableEditableModel(QAbstractTableModel):
def remove_rows(self, rows, parent=QModelIndex()): def remove_rows(self, rows, parent=QModelIndex()):
self.beginRemoveRows(parent, rows[0], rows[-1]) self.beginRemoveRows(parent, rows[0], rows[-1])
self._undo_stack.push( self._undo.push(
DelCommand( DelCommand(
self._profile, rows self._data, rows
) )
) )
@@ -239,15 +204,15 @@ class TableEditableModel(QAbstractTableModel):
reverse = (order != Qt.AscendingOrder) reverse = (order != Qt.AscendingOrder)
self._undo_stack.push( self._undo.push(
SortCommand( SortCommand(
self._profile, column, reverse self._data, column, reverse
) )
) )
self.layoutChanged.emit() self.layoutChanged.emit()
def move_row_up(self, row, parent=QModelIndex()): def move_up(self, row, parent=QModelIndex()):
if row <= 0: if row <= 0:
return return
@@ -255,26 +220,26 @@ class TableEditableModel(QAbstractTableModel):
self.beginMoveRows(parent, row - 1, row - 1, parent, target) self.beginMoveRows(parent, row - 1, row - 1, parent, target)
self._undo_stack.push( self._undo.push(
MoveCommand( MoveCommand(
self._profile, "up", row self._data, "up", row
) )
) )
self.endMoveRows() self.endMoveRows()
self.layoutChanged.emit() self.layoutChanged.emit()
def move_row_down(self, row_to_move, parent=QModelIndex()): def move_down(self, row_to_move, parent=QModelIndex()):
if row > self._profile.number_points: if row > self._data.number_points:
return return
target = row target = row
self.beginMoveRows(parent, row + 1, row + 1, parent, target) self.beginMoveRows(parent, row + 1, row + 1, parent, target)
self._undo_stack.push( self._undo.push(
MoveCommand( MoveCommand(
self._profile, "down", row self._data, "down", row
) )
) )
@@ -282,7 +247,7 @@ class TableEditableModel(QAbstractTableModel):
self.layoutChanged.emit() self.layoutChanged.emit()
def paste(self, row, header, data): def paste(self, row, header, data):
if row > self._profile.number_points: if row > self._data.number_points:
return return
if len(data) == 0: if len(data) == 0:
@@ -290,12 +255,12 @@ class TableEditableModel(QAbstractTableModel):
self.layoutAboutToBeChanged.emit() self.layoutAboutToBeChanged.emit()
self._undo_stack.push( self._undo.push(
PasteCommand( PasteCommand(
self._profile, row, self._data, row,
list( list(
map( map(
lambda d: self._profile.point_from_data(header, d), lambda d: self._data.point_from_data(header, d),
data data
) )
) )
@@ -306,32 +271,9 @@ class TableEditableModel(QAbstractTableModel):
self.layoutChanged.emit() self.layoutChanged.emit()
def undo(self): def undo(self):
self._undo_stack.undo() self._undo.undo()
self.layoutChanged.emit() self.layoutChanged.emit()
def redo(self): def redo(self):
self._undo_stack.redo() self._undo.redo()
self.layoutChanged.emit() 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 ( from PyQt5.QtWidgets import (
QApplication, QMainWindow, QFileDialog, QCheckBox, QApplication, QMainWindow, QFileDialog, QCheckBox,
QUndoStack, QShortcut, QUndoStack, QShortcut, QTableView, QAbstractItemView,
QHeaderView, QVBoxLayout, QAction,
) )
from Model.Geometry.Reach import Reach from Model.Geometry.Reach import Reach
from Model.Geometry.ProfileXYZ import ProfileXYZ from Model.Geometry.ProfileXYZ import ProfileXYZ
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.Geometry.Profile.mainwindow_ui_profile import Ui_MainWindow 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.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 _translate = QCoreApplication.translate
class ProfileWindow(ASubMainWindow): class ProfileWindow(PamhyrWindow):
def __init__(self, profile=None, title="Profile", parent=None): _pamhyr_ui = "GeometryCrossSection"
self._title = title _pamhyr_name = "Geometry cross-section"
self.parent = parent
super(ProfileWindow, self).__init__(
name=self._title,
parent=self.parent
)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
def __init__(self, profile=None, study=None, config=None, parent=None):
self._profile = profile self._profile = profile
self._model = None
self.setup_window() name = f"{self._pamhyr_name} - {self._profile.name} {self._profile.kp}"
self.setup_sc() super(ProfileWindow, self).__init__(
self.setup_model() title = name,
self.setup_connections() study = study,
self.plot() config = config,
trad = GeometryProfileTranslate(),
self._model.dataChanged.connect(self.update_plot) parent = parent
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})"
) )
self.setWindowTitle(self._title) self.setup_table()
self.setup_plot()
self.setup_connections()
def setup_sc(self): def setup_table(self):
self._undo_stack = QUndoStack() table_headers = self._trad.get_dict("table_headers")
self.undo_sc = QShortcut(QKeySequence.Undo, self) table = self.find(QTableView, "tableView")
self.redo_sc = QShortcut(QKeySequence.Redo, self) self._tablemodel = GeometryProfileTableModel(
self.copy_sc = QShortcut(QKeySequence.Copy, self) table_view = table,
self.paste_sc = QShortcut(QKeySequence.Paste, self) table_headers = table_headers,
editable_headers = ["name", "x", "y", "z"],
def setup_model(self): data = self._profile,
self._model = TableEditableModel(
profile = self._profile,
undo = self._undo_stack 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) def setup_plot(self):
self.ui.tableView.setItemDelegate(Delegate()) self._tablemodel.blockSignals(True)
def setup_connections(self): self._canvas = MplCanvas(width=3, height=4, dpi=100)
self.ui.btn_sort_asc_x.triggered.connect(self.sort_X_ascending) self._canvas.setObjectName("canvas")
self.ui.btn_sort_desc_x.triggered.connect(self.sort_X_descending) self._toolbar = PamhyrPlotToolbar(
self.ui.btn_sort_asc_y.triggered.connect(self.sort_Y_ascending) self._canvas, self,
self.ui.btn_sort_desc_y.triggered.connect(self.sort_Y_descending) items = ["home", "zoom", "save", "iso", "back/forward", "move"]
self.ui.btn_move_up.triggered.connect(self.move_row_up) )
self.ui.btn_move_down.triggered.connect(self.move_row_down) self._plot_layout = self.find(QVBoxLayout, "verticalLayout")
self.ui.btn_export.triggered.connect(self.handleSave) self._plot_layout.addWidget(self._toolbar)
self.ui.btn_add.triggered.connect(self.insert_row) self._plot_layout.addWidget(self._canvas)
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._plot = Plot( self._plot = Plot(
canvas = self.ui.canvas, canvas = self._canvas,
data = self._profile, data = self._profile,
toolbar = None, toolbar = self._toolbar,
table = self.ui.tableView, table = self.find(QTableView, "tableView")
) )
self._plot.draw() 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): def update_plot(self):
self.ui.tableView.model().blockSignals(True) self._tablemodel.blockSignals(True)
# TODO: Do not rebuild all graph # TODO: Do not rebuild all graph
self._plot.update() self._plot.update()
self.ui.tableView.model().blockSignals(False) self._tablemodel.blockSignals(False)
def index_selected_row(self): def index_selected_row(self):
rows = self.ui.tableView\ rows = self._tablemodel\
.selectionModel()\ .selectionModel()\
.selectedRows() .selectedRows()
if len(rows) == 0: if len(rows) == 0:
return 0 return 0
return self.ui.tableView\ return self._tablemodel\
.selectionModel()\ .selectionModel()\
.selectedRows()[0]\ .selectedRows()[0]\
.row() .row()
def insert_row(self): def add(self):
if len(self.ui.tableView.selectedIndexes()) == 0: table = self.find(QTableView, "tableView")
self._model.insert_row(self._model.rowCount()) if len(table.selectedIndexes()) == 0:
self._tablemodel.insert_row(self._tablemodel.rowCount())
else: else:
row = self.index_selected_row() row = self.index_selected_row()
self._model.insert_row(row + 1) self._tablemodel.insert_row(row + 1)
self.update_plot() self.update_plot()
def delete_row(self): def delete(self):
table = self.find(QTableView, "tableView")
rows = sorted( rows = sorted(
list( list(
set( set(
[index.row() for index in self.ui.tableView.selectedIndexes()] [index.row() for index in table.selectedIndexes()]
) )
) )
) )
if len(rows) > 0: if len(rows) > 0:
self._model.remove_rows(rows) self._tablemodel.remove_rows(rows)
self.update_plot() self.update_plot()
def sort_X_ascending(self): def sort_X_ascending(self):
self._model.sort('x', order=Qt.AscendingOrder) self._tablemodel.sort('x', order=Qt.AscendingOrder)
self.update_plot() self.update_plot()
def sort_X_descending(self): def sort_X_descending(self):
self._model.sort('x', order=Qt.DescendingOrder) self._tablemodel.sort('x', order=Qt.DescendingOrder)
self.update_plot() self.update_plot()
def sort_Y_ascending(self): def sort_Y_ascending(self):
self._model.sort('y', order=Qt.AscendingOrder) self._tablemodel.sort('y', order=Qt.AscendingOrder)
self.update_plot() self.update_plot()
def sort_Y_descending(self): def sort_Y_descending(self):
self._model.sort('y', order=Qt.DescendingOrder) self._tablemodel.sort('y', order=Qt.DescendingOrder)
self.update_plot() self.update_plot()
def move_row_down(self): def move_down(self):
rows = list( rows = list(
set( set(
[index.row() for index in self.ui.tableView.selectedIndexes()] [index.row() for index in
self.find(QTableView, "tableView").selectedIndexes()]
) )
) )
for row in rows: for row in rows:
if row < self._model.rowCount() - 1: if row < self._tablemodel.rowCount() - 1:
self._model.move_row_down(row) self._tablemodel.move_down(row)
self.update_plot() self.update_plot()
def move_row_up(self): def move_up(self):
rows = list( rows = list(
set( set(
[index.row() for index in self.ui.tableView.selectedIndexes()] [index.row() for index in
self.find(QTableView, "tableView").selectedIndexes()]
) )
) )
for row in rows: for row in rows:
if 0 < row: if 0 < row:
self._model.move_row_up(row) self._tablemodel.move_up(row)
self.update_plot() self.update_plot()
def copy(self): def copy(self):
rows = self.ui.tableView\ rows = self._tablemodel\
.selectionModel()\ .selectionModel()\
.selectedRows() .selectedRows()
table = [] table = []
@@ -257,136 +240,13 @@ class ProfileWindow(ASubMainWindow):
row.append(self._profile) row.append(self._profile)
row = self.index_selected_row() row = self.index_selected_row()
self._model.paste(row, header, data) self._tablemodel.paste(row, header, data)
self.update_plot() self.update_plot()
def undo(self): def undo(self):
self._model.undo() self._tablemodel.undo()
self.update_plot() self.update_plot()
def redo(self): def redo(self):
self._model.redo() self._tablemodel.redo()
self.update_plot() 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, QComboBox,
) )
from View.Tools.PamhyrTable import PamhyrTableModel
from Model.Geometry import Reach from Model.Geometry import Reach
from Model.Geometry.ProfileXYZ import ProfileXYZ from Model.Geometry.ProfileXYZ import ProfileXYZ
from View.Geometry.UndoCommand import * from View.Geometry.UndoCommand import *
@@ -44,53 +46,26 @@ logger = logging.getLogger()
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class TableEditableModel(QAbstractTableModel): class GeometryReachTableModel(PamhyrTableModel):
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)
def data(self, index, role=Qt.DisplayRole): def data(self, index, role=Qt.DisplayRole):
if not index.isValid(): if not index.isValid():
return QVariant() return QVariant()
if role == Qt.DisplayRole and index.column() == 0: 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: 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}" return f"{kp:.4f}"
if role == Qt.DisplayRole and index.column() == 2: 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: if role == Qt.TextAlignmentRole:
return Qt.AlignHCenter | Qt.AlignVCenter return Qt.AlignHCenter | Qt.AlignVCenter
if role == Qt.ForegroundRole and index.column() == 0: if role == Qt.ForegroundRole and index.column() == 0:
name = self._reach.profile(index.row()).name\ name = self._data.profile(index.row()).name\
.strip()\ .strip()\
.lower() .lower()
if (name == "upstream" or name == "up" or if (name == "upstream" or name == "up" or
@@ -102,16 +77,6 @@ class TableEditableModel(QAbstractTableModel):
return QVariant() 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): def setData(self, index, value, role=Qt.EditRole):
row = index.row() row = index.row()
column = index.column() column = index.column()
@@ -119,19 +84,19 @@ class TableEditableModel(QAbstractTableModel):
if role == Qt.EditRole and index.column() != 2: if role == Qt.EditRole and index.column() != 2:
try: try:
if index.column() == 0: if index.column() == 0:
self._undo_stack.push( self._undo.push(
SetNameCommand( SetNameCommand(
self._reach, index.row(), self._data, index.row(),
self._reach.profile(index.row()).name, self._data.profile(index.row()).name,
value value
) )
) )
if index.column() == 1: if index.column() == 1:
self._undo_stack.push( self._undo.push(
SetKPCommand( SetKPCommand(
self._reach, index.row(), self._data, index.row(),
self._reach.profile(index.row()).kp, self._data.profile(index.row()).kp,
value value
) )
) )
@@ -149,39 +114,25 @@ class TableEditableModel(QAbstractTableModel):
return False 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() # @QtCore.pyqtSlot()
def insert_row(self, row, parent=QModelIndex()): def add(self, row, parent=QModelIndex()):
self.beginInsertRows(parent, row, row - 1) self.beginInsertRows(parent, row, row - 1)
self._undo_stack.push( self._undo.push(
AddCommand( AddCommand(
self._reach, row self._data, row
) )
) )
self.endInsertRows() self.endInsertRows()
self.layoutChanged.emit() self.layoutChanged.emit()
def remove_rows(self, rows, parent=QModelIndex()): def delete(self, rows, parent=QModelIndex()):
self.beginRemoveRows(parent, rows[0], rows[-1]) self.beginRemoveRows(parent, rows[0], rows[-1])
self._undo_stack.push( self._undo.push(
DelCommand( DelCommand(
self._reach, rows self._data, rows
) )
) )
@@ -191,9 +142,9 @@ class TableEditableModel(QAbstractTableModel):
def sort_profiles(self, _reverse): def sort_profiles(self, _reverse):
self.layoutAboutToBeChanged.emit() self.layoutAboutToBeChanged.emit()
self._undo_stack.push( self._undo.push(
SortCommand( SortCommand(
self._reach, _reverse self._data, _reverse
) )
) )
@@ -201,7 +152,7 @@ class TableEditableModel(QAbstractTableModel):
self.layoutChanged.emit() self.layoutChanged.emit()
def move_row_up(self, row, parent=QModelIndex()): def move_up(self, row, parent=QModelIndex()):
if row <= 0: if row <= 0:
return return
@@ -209,26 +160,26 @@ class TableEditableModel(QAbstractTableModel):
self.beginMoveRows(parent, row - 1, row - 1, parent, target) self.beginMoveRows(parent, row - 1, row - 1, parent, target)
self._undo_stack.push( self._undo.push(
MoveCommand( MoveCommand(
self._reach, "up", row self._data, "up", row
) )
) )
self.endMoveRows() self.endMoveRows()
self.layoutChanged.emit() self.layoutChanged.emit()
def move_row_down(self, row, parent=QModelIndex()): def move_down(self, row, parent=QModelIndex()):
if row > self._reach.number_profiles: if row > self._data.number_profiles:
return return
target = row target = row
self.beginMoveRows(parent, row + 1, row + 1, parent, target) self.beginMoveRows(parent, row + 1, row + 1, parent, target)
self._undo_stack.push( self._undo.push(
MoveCommand( MoveCommand(
self._reach, "down", row self._data, "down", row
) )
) )
@@ -238,9 +189,9 @@ class TableEditableModel(QAbstractTableModel):
def duplicate(self, rows, profiles): def duplicate(self, rows, profiles):
self.layoutAboutToBeChanged.emit() self.layoutAboutToBeChanged.emit()
self._undo_stack.push( self._undo.push(
DuplicateCommand( DuplicateCommand(
self._reach, rows, self._data, rows,
profiles profiles
) )
) )
@@ -250,7 +201,7 @@ class TableEditableModel(QAbstractTableModel):
def paste(self, row, header, data): def paste(self, row, header, data):
if row > self._reach.number_profiles: if row > self._data.number_profiles:
return return
if len(data) == 0: if len(data) == 0:
@@ -258,9 +209,9 @@ class TableEditableModel(QAbstractTableModel):
self.layoutAboutToBeChanged.emit() self.layoutAboutToBeChanged.emit()
self._undo_stack.push( self._undo.push(
PasteCommand( PasteCommand(
self._reach, row, self._data, row,
list( list(
map( map(
lambda d: ProfileXYZ.from_data(header, d), lambda d: ProfileXYZ.from_data(header, d),
@@ -272,71 +223,3 @@ class TableEditableModel(QAbstractTableModel):
self.layoutAboutToBeChanged.emit() self.layoutAboutToBeChanged.emit()
self.layoutChanged.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 ( from PyQt5.QtWidgets import (
QApplication, QMainWindow, QFileDialog, QCheckBox, QApplication, QMainWindow, QFileDialog, QCheckBox,
QUndoStack, QShortcut, QUndoStack, QShortcut, QTableView, QHeaderView,
QAction, QSlider, QPushButton, QVBoxLayout,
QLabel, QAbstractItemView,
) )
from View.Geometry.PlotXY import PlotXY from View.Tools.PamhyrWindow import PamhyrWindow
from View.Geometry.PlotKPZ import PlotKPZ from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.Geometry.PlotAC import PlotAC from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.ASubWindow import ASubMainWindow, WindowToolKit from View.Geometry.Table import GeometryReachTableModel
from View.ListedSubWindow import ListedSubWindow from View.Geometry.PlotXY import PlotXY
from View.Geometry.mainwindow_ui_reach import Ui_MainWindow from View.Geometry.PlotAC import PlotAC
from View.Geometry.Table import * from View.Geometry.PlotKPZ import PlotKPZ
from View.Geometry.Translate import GeometryTranslate
from View.Geometry.Profile.Window import ProfileWindow from View.Geometry.Profile.Window import ProfileWindow
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class GeometryWindow(ASubMainWindow, ListedSubWindow): class GeometryWindow(PamhyrWindow):
def __init__(self, model=None, title="Geometry", parent=None): _pamhyr_ui = "GeometryReach"
self._title = title _pamhyr_name = "Geometry"
self.parent = parent
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__( super(GeometryWindow, self).__init__(
name=self._title, title = name,
parent=parent 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._tablemodel = None
self._profile_window = [] self._profile_window = []
self._clipboard = None
self.setup_window() self.setup_table()
self.setup_sc()
self.setup_model()
self.setup_plots() self.setup_plots()
self.setup_statusbar()
self.setup_connections() self.setup_connections()
self.changed_slider_value() self.changed_slider_value()
def setup_window(self): def setup_table(self):
self._title = f"{self.ui.mainwindow_title} - {self._reach.name}" table_headers = self._trad.get_dict("table_headers")
self.setWindowTitle(self._title)
def setup_sc(self): table = self.find(QTableView, "tableView")
self._undo_stack = QUndoStack() self._tablemodel = GeometryReachTableModel(
table_view = table,
self.undo_sc = QShortcut(QKeySequence.Undo, self) table_headers = table_headers,
self.redo_sc = QShortcut(QKeySequence.Redo, self) editable_headers = ["name", "kp"],
self.copy_sc = QShortcut(QKeySequence.Copy, self) data = self._reach,
self.paste_sc = QShortcut(QKeySequence.Paste, self)
def setup_model(self):
self._tablemodel = TableEditableModel(
headers = self.ui.tableView_header,
reach = self._reach,
undo = self._undo_stack undo = self._undo_stack
) )
self.tableView.setModel(self._tablemodel) table.setModel(self._tablemodel)
self.tableView.setItemDelegate(Delegate()) table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
def setup_plots(self): 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.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.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() 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): def setup_connections(self):
self.ui.btn_open.triggered.connect(self.open_file_dialog) actions = {
self.ui.btn_sort_asc.triggered.connect(self.sort_ascending) "action_import": self.import_from_file,
self.ui.btn_sort_desc.triggered.connect(self.sort_descending) # "action_export": self.export_to_file,
self.ui.btn_move_up.triggered.connect(self.move_row_up) "action_sort_asc": self.sort_ascending,
self.ui.btn_move_down.triggered.connect(self.move_row_down) "action_sort_des": self.sort_descending,
# self.ui.btn_end_editing.triggered.connect(self.handleSave) "action_up": self.move_up,
self.ui.btn_add.triggered.connect(self.insert_row) "action_down": self.move_down,
self.ui.btn_delete.triggered.connect(self.delete_rows) "action_add": self.add,
self.ui.btn_edit.triggered.connect(self.edit_profile) "action_delete": self.delete,
self.ui.verticalSlider.valueChanged.connect(self.changed_slider_value) "action_edit": self.edit_profile,
}
self.ui.btn_slider_up.clicked.connect(self.decrement_value_slider) for action in actions:
self.ui.btn_slider_down.clicked.connect(self.increment_value_slider) self.find(QAction, action)\
self.ui.btn_move_up.triggered.connect(self.changed_profile_slot) .triggered.connect(actions[action])
self.undo_sc.activated.connect(self.undo) self.find(QSlider, "verticalSlider").valueChanged.connect(self.changed_slider_value)
self.redo_sc.activated.connect(self.redo) self.find(QPushButton, "pushButton_up").clicked.connect(self.decrement_value_slider)
self.copy_sc.activated.connect(self.copy) self.find(QPushButton, "pushButton_down").clicked.connect(self.increment_value_slider)
self.paste_sc.activated.connect(self.paste)
# Profile selection when line change in table # Profile selection when line change in table
self.tableView.selectionModel()\ self.find(QTableView, "tableView").selectionModel()\
.selectionChanged\ .selectionChanged\
.connect(self.select_current_profile) .connect(self.select_current_profile)
def open_file_dialog(self):
def import_from_file(self):
options = QFileDialog.Options() options = QFileDialog.Options()
settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'MyOrg', ) settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'MyOrg', )
options |= QFileDialog.DontUseNativeDialog options |= QFileDialog.DontUseNativeDialog
file_types = [
self._trad["file_st"],
self._trad["file_m"],
self._trad["file_all"],
]
filename, _ = QtWidgets.QFileDialog.getOpenFileName( filename, _ = QtWidgets.QFileDialog.getOpenFileName(
self, self,
_translate("MainWindow_reach", "Ouvrir un fichier"), self._trad["open_file"],
"", "",
_translate("MainWindow_reach", "Fichiers .ST (*.ST)") + ";; ".join(file_types),
";; " +
_translate("MainWindow_reach", "Fichiers .M (*.M)") +
";; " +
_translate("MainWindow_reach", "Tous les fichiers (*)"),
options=options options=options
) )
@@ -158,20 +208,6 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self.plot_kpc() self.plot_kpc()
self.plot_ac() 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): def edit_profile(self):
self.tableView.model().blockSignals(True) self.tableView.model().blockSignals(True)
@@ -214,9 +250,9 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self.tableView.model().blockSignals(True) self.tableView.model().blockSignals(True)
self._plot_xy = PlotXY( self._plot_xy = PlotXY(
canvas = self.ui.canvas_1, canvas = self._canvas_xy,
data = self._reach, data = self._reach,
toolbar = self.ui.toolbar_1 toolbar = self._toolbar_xy
) )
self._plot_xy.draw() self._plot_xy.draw()
@@ -231,9 +267,9 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self.tableView.model().blockSignals(True) self.tableView.model().blockSignals(True)
self._plot_kpc = PlotKPZ( self._plot_kpc = PlotKPZ(
canvas = self.ui.canvas_2, canvas = self._canvas_kpc,
data = self._reach, data = self._reach,
toolbar = self.ui.toolbar_2 toolbar = self._toolbar_kpc
) )
self._plot_kpc.draw() self._plot_kpc.draw()
@@ -248,9 +284,9 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self.tableView.model().blockSignals(True) self.tableView.model().blockSignals(True)
self._plot_ac = PlotAC( self._plot_ac = PlotAC(
canvas = self.ui.canvas_3, canvas = self._canvas_ac,
data = self._reach, data = self._reach,
toolbar = self.ui.toolbar_3, toolbar = self._toolbar_ac,
plot_xy = self._plot_xy plot_xy = self._plot_xy
) )
self._plot_ac.draw() self._plot_ac.draw()
@@ -303,7 +339,7 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
if len(self.tableView.selectedIndexes()) > 0: if len(self.tableView.selectedIndexes()) > 0:
row = self.index_selected_row() row = self.index_selected_row()
self.ui.verticalSlider.setValue(row) self.find(QSlider, "verticalSlider").setValue(row)
self.select_plot_xy(row) self.select_plot_xy(row)
self.select_plot_kpc(row) self.select_plot_kpc(row)
self.select_plot_ac(row) self.select_plot_ac(row)
@@ -314,41 +350,37 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self.tableView.model().blockSignals(True) self.tableView.model().blockSignals(True)
if self._tablemodel.rowCount() != 0: 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 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_xy(slider_value)
self.select_plot_kpc(slider_value) self.select_plot_kpc(slider_value)
self.select_row_profile_slider(slider_value) self.select_row_profile_slider(slider_value)
self.update_statusbar()
self.tableView.model().blockSignals(False) self.tableView.model().blockSignals(False)
def increment_value_slider(self): def increment_value_slider(self):
if 0 <= self.ui.verticalSlider.value() < self._tablemodel.rowCount() - 1: slider = self.find(QSlider, "verticalSlider")
self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() + 1) if 0 <= slider.value() < self._tablemodel.rowCount() - 1:
slider.setValue(slider.value() + 1)
def decrement_value_slider(self): def decrement_value_slider(self):
if 0 < self.ui.verticalSlider.value() < self._tablemodel.rowCount(): slider = self.find(QSlider, "verticalSlider")
self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() - 1) 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: if len(self.tableView.selectedIndexes()) == 0:
self._tablemodel.insert_row(self._tablemodel.rowCount()) self._tablemodel.add(self._tablemodel.rowCount())
else: else:
row = self.index_selected_row() 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( rows = sorted(
list( list(
set( set(
@@ -358,7 +390,7 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
) )
if len(rows) > 0: if len(rows) > 0:
self._tablemodel.remove_rows(rows) self._tablemodel.delete(rows)
self.update_plot_xy() self.update_plot_xy()
self.select_current_profile() self.select_current_profile()
@@ -373,24 +405,24 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
.row() .row()
def sort_ascending(self): def sort_ascending(self):
self._tablemodel.sort_profiles(True) self._tablemodel.sort_profiles(False)
self.select_current_profile() self.select_current_profile()
self.changed_slider_value() self.changed_slider_value()
def sort_descending(self): def sort_descending(self):
self._tablemodel.sort_profiles(False) self._tablemodel.sort_profiles(True)
self.select_current_profile() self.select_current_profile()
self.changed_slider_value() self.changed_slider_value()
def move_row_up(self): def move_up(self):
row = self.index_selected_row() row = self.index_selected_row()
self._tablemodel.move_row_up(row) self._tablemodel.move_up(row)
self.select_current_profile() self.select_current_profile()
def move_row_down(self): def move_down(self):
row = self.index_selected_row() row = self.index_selected_row()
self._tablemodel.move_row_down(row) self._tablemodel.move_down(row)
self.select_current_profile() self.select_current_profile()
def duplicate(self): def duplicate(self):
@@ -411,7 +443,7 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self._tablemodel.duplicate(rows, profiles) self._tablemodel.duplicate(rows, profiles)
self.select_current_profile() self.select_current_profile()
def copy(self): def _copy(self):
rows = self.tableView\ rows = self.tableView\
.selectionModel()\ .selectionModel()\
.selectedRows() .selectedRows()
@@ -427,7 +459,7 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self.copyTableIntoClipboard(table) self.copyTableIntoClipboard(table)
def paste(self): def _paste(self):
header, data = self.parseClipboardTable() header, data = self.parseClipboardTable()
if len(data) == 0: if len(data) == 0:
@@ -442,19 +474,19 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
self._tablemodel.paste(row, header, data) self._tablemodel.paste(row, header, data)
self.select_current_profile() self.select_current_profile()
def undo(self): def _undo(self):
self._tablemodel.undo() self._tablemodel.undo()
self.select_current_profile() self.select_current_profile()
self.update_plot_xy() self.update_plot_xy()
self.update_plot_kpc() self.update_plot_kpc()
def redo(self): def _redo(self):
self._tablemodel.redo() self._tablemodel.redo()
self.select_current_profile() self.select_current_profile()
self.update_plot_xy() self.update_plot_xy()
self.update_plot_kpc() self.update_plot_kpc()
def handleSave(self): def export_to_file(self):
options = QFileDialog.Options() options = QFileDialog.Options()
DEFAULT_DIRECTORY = '/home/' DEFAULT_DIRECTORY = '/home/'
settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'MyOrg', ) settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'MyOrg', )
@@ -463,32 +495,11 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow):
filename, filters = QFileDialog.getSaveFileName( filename, filters = QFileDialog.getSaveFileName(
self, self,
filter=_translate("MainWindow_reach", filter = self._trad["file_st"] + ";; " + self._trad["file_all"],
"Files .ST(*.ST or *.st)") options = options
+ ";; " +
_translate("MainWindow_reach", "All files "
"(*)"),
options=options
) )
current_dir = os.path.split(filename)[0] or DEFAULT_DIRECTORY current_dir = os.path.split(filename)[0] or DEFAULT_DIRECTORY
if filename != '': if filename != '':
self._tablemodel.export_reach(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 -*- # -*- coding: utf-8 -*-
from View.ASubWindow import ASubWindow from View.Tools.PamhyrWindow import PamhyrDialog
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -32,10 +31,15 @@ from PyQt5.QtWidgets import (
QDoubleSpinBox, QDoubleSpinBox,
) )
class DischargeDialog(ASubWindow, ListedSubWindow): class DischargeDialog(PamhyrDialog):
_pamhyr_ui = "InitialConditions_Dialog_Generator_Discharge"
_pamhyr_name = "Discharge"
def __init__(self, title="Discharge", parent=None): def __init__(self, title="Discharge", parent=None):
super(DischargeDialog, self).__init__( super(DischargeDialog, self).__init__(
name=title, ui="InitialConditions_Dialog_Generator_Discharge", parent=parent title = self._pamhyr_name,
options = [],
parent = parent
) )
self.value = None self.value = None
+9 -5
View File
@@ -16,8 +16,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from View.ASubWindow import ASubWindow from View.Tools.PamhyrWindow import PamhyrDialog
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -32,10 +31,15 @@ from PyQt5.QtWidgets import (
QDoubleSpinBox, QDoubleSpinBox,
) )
class HeightDialog(ASubWindow, ListedSubWindow): class HeightDialog(PamhyrDialog):
def __init__(self, title="Height", parent=None): _pamhyr_ui = "InitialConditions_Dialog_Generator_Height"
_pamhyr_name = "Height"
def __init__(self, parent=None):
super(HeightDialog, self).__init__( super(HeightDialog, self).__init__(
name=title, ui="InitialConditions_Dialog_Generator_Height", parent=parent title = self._pamhyr_name,
options = [],
parent = parent
) )
self.value = None self.value = None
+4 -11
View File
@@ -17,7 +17,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from tools import timer from tools import timer
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -25,14 +25,7 @@ from PyQt5.QtCore import (
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class PlotDKP(APlot): class PlotDKP(PamhyrPlot):
def __init__(self, canvas=None, data=None, toolbar=None):
super(PlotDKP, self).__init__(
canvas=canvas,
data=data,
toolbar=toolbar
)
@timer @timer
def draw(self, highlight=None): def draw(self, highlight=None):
self.canvas.axes.cla() self.canvas.axes.cla()
@@ -42,11 +35,11 @@ class PlotDKP(APlot):
return return
self.canvas.axes.set_ylabel( self.canvas.axes.set_ylabel(
_translate("MainWindow_reach", "Elevation (m)"), self._trad["elevation"],
color='green', fontsize=11 color='green', fontsize=11
) )
self.canvas.axes.set_xlabel( self.canvas.axes.set_xlabel(
_translate("MainWindow_reach", "KP (m)"), self._trad["kp"],
color='green', fontsize=11 color='green', fontsize=11
) )
+4 -17
View File
@@ -17,22 +17,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from tools import timer from tools import timer
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
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
)
class PlotDischarge(PamhyrPlot):
@timer @timer
def draw(self, highlight=None): def draw(self, highlight=None):
self.canvas.axes.cla() self.canvas.axes.cla()
@@ -42,11 +29,11 @@ class PlotDischarge(APlot):
return return
self.canvas.axes.set_ylabel( self.canvas.axes.set_ylabel(
_translate("MainWindow_reach", "Discharge (m^3/s)"), self._trad["discharge"],
color='green', fontsize=11 color='green', fontsize=11
) )
self.canvas.axes.set_xlabel( self.canvas.axes.set_xlabel(
_translate("MainWindow_reach", "KP (m)"), self._trad["kp"],
color='green', fontsize=11 color='green', fontsize=11
) )
+17 -39
View File
@@ -33,14 +33,14 @@ from PyQt5.QtWidgets import (
QComboBox, QComboBox,
) )
from View.Tools.PamhyrTable import PamhyrTableModel
from View.InitialConditions.UndoCommand import ( from View.InitialConditions.UndoCommand import (
SetCommand, AddCommand, DelCommand, SetCommand, AddCommand, DelCommand,
SortCommand, MoveCommand, PasteCommand, SortCommand, MoveCommand, PasteCommand,
DuplicateCommand, GenerateCommand, DuplicateCommand, GenerateCommand,
) )
from View.InitialConditions.translate import *
logger = logging.getLogger() logger = logging.getLogger()
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
@@ -87,29 +87,13 @@ class ComboBoxDelegate(QItemDelegate):
self.commitData.emit(self.sender()) self.commitData.emit(self.sender())
class TableModel(QAbstractTableModel): class InitialConditionTableModel(PamhyrTableModel):
def __init__(self, river=None, reach=None, undo=None): def __init__(self, reach=None, **kwargs):
super(QAbstractTableModel, self).__init__()
self._headers = list(table_headers.keys())
self._river = river
self._reach = reach self._reach = reach
self._undo = undo super(InitialConditionTableModel, self).__init__(**kwargs)
self._ics = self._river.initial_conditions.get(reach)
def flags(self, index): def _setup_lst(self):
column = index.column() self._lst = self._data.river.initial_conditions.get(self._reach)
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 data(self, index, role): def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole: if role != Qt.ItemDataRole.DisplayRole:
@@ -119,16 +103,10 @@ class TableModel(QAbstractTableModel):
column = index.column() column = index.column()
if self._headers[column] not in ["name", "comment"]: 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}" return f"{v:.4f}"
else: else:
return self._ics.get(row)[self._headers[column]] return self._lst.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 QVariant() return QVariant()
@@ -143,7 +121,7 @@ class TableModel(QAbstractTableModel):
if self._headers[column] is not None: if self._headers[column] is not None:
self._undo.push( self._undo.push(
SetCommand( SetCommand(
self._ics, row, self._headers[column], value self._lst, row, self._headers[column], value
) )
) )
except Exception as e: except Exception as e:
@@ -158,7 +136,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
AddCommand( AddCommand(
self._ics, row self._lst, row
) )
) )
@@ -170,7 +148,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
DelCommand( DelCommand(
self._ics, rows self._lst, rows
) )
) )
@@ -182,7 +160,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
SortCommand( SortCommand(
self._ics, False self._lst, False
) )
) )
@@ -199,7 +177,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
MoveCommand( MoveCommand(
self._ics, "up", row self._lst, "up", row
) )
) )
@@ -207,7 +185,7 @@ class TableModel(QAbstractTableModel):
self.layoutChanged.emit() self.layoutChanged.emit()
def move_down(self, index, parent=QModelIndex()): def move_down(self, index, parent=QModelIndex()):
if row > len(self._ics): if row > len(self._lst):
return return
target = row target = row
@@ -216,7 +194,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
MoveCommand( MoveCommand(
self._ics, "down", row self._lst, "down", row
) )
) )
@@ -234,7 +212,7 @@ class TableModel(QAbstractTableModel):
def generate(self, generator, param): def generate(self, generator, param):
self._undo.push( self._undo.push(
GenerateCommand( GenerateCommand(
self._ics, generator, param self._lst, generator, param
) )
) )
self.layoutChanged.emit() self.layoutChanged.emit()
+48 -55
View File
@@ -20,8 +20,7 @@ import logging
from tools import trace, timer from tools import trace, timer
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -46,14 +45,14 @@ from View.InitialConditions.UndoCommand import (
DuplicateCommand, DuplicateCommand,
) )
from View.InitialConditions.Table import TableModel, ComboBoxDelegate from View.InitialConditions.Table import InitialConditionTableModel, ComboBoxDelegate
from View.Plot.MplCanvas import MplCanvas from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.InitialConditions.PlotDKP import PlotDKP from View.InitialConditions.PlotDKP import PlotDKP
from View.InitialConditions.PlotDischarge import PlotDischarge 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.DialogHeight import HeightDialog
from View.InitialConditions.DialogDischarge import DischargeDialog from View.InitialConditions.DialogDischarge import DischargeDialog
@@ -61,67 +60,62 @@ _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class InitialConditionsWindow(ASubMainWindow, ListedSubWindow): class InitialConditionsWindow(PamhyrWindow):
def __init__(self, title="Initial condition", _pamhyr_ui = "InitialConditions"
study=None, parent=None): _pamhyr_name = "Initial condition"
self._study = study
self._reach = study.river.current_reach()
self._ics = self._study.river.initial_conditions.get(self._reach)
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 = (
name=self._title, ui="InitialConditions", parent=parent 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_table()
self.setup_graph() self.setup_plot()
self.setup_connections() self.setup_connections()
self.ui.setWindowTitle(self._title) 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): def setup_table(self):
retranslate()
table = self.find(QTableView, f"tableView") 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( self._delegate_kp = ComboBoxDelegate(
reach = self._reach, reach = self._reach,
parent=self parent = self
) )
table.setItemDelegateForColumn( self._table = InitialConditionTableModel(
list(table_headers).index("kp"), reach = self._reach,
self._delegate_kp 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.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True) table.setAlternatingRowColors(True)
def setup_graph(self): def setup_plot(self):
self.canvas_1 = MplCanvas(width=5, height=4, dpi=100) self.canvas_1 = MplCanvas(width=5, height=4, dpi=100)
self.canvas_1.setObjectName("canvas_1") self.canvas_1.setObjectName("canvas_1")
self.toolbar_1 = PamhyrPlotToolbar( self.toolbar_1 = PamhyrPlotToolbar(
@@ -134,7 +128,9 @@ class InitialConditionsWindow(ASubMainWindow, ListedSubWindow):
self.plot_1 = PlotDKP( self.plot_1 = PlotDKP(
canvas = self.canvas_1, canvas = self.canvas_1,
data = self._ics, data = self._ics,
trad = self._trad,
toolbar = self.toolbar_1, toolbar = self.toolbar_1,
parent = self
) )
self.plot_1.draw() self.plot_1.draw()
@@ -150,7 +146,9 @@ class InitialConditionsWindow(ASubMainWindow, ListedSubWindow):
self.plot_2 = PlotDischarge( self.plot_2 = PlotDischarge(
canvas = self.canvas_2, canvas = self.canvas_2,
data = self._ics, data = self._ics,
trad = self._trad,
toolbar = self.toolbar_2, toolbar = self.toolbar_2,
parent = self
) )
self.plot_2.draw() self.plot_2.draw()
@@ -167,11 +165,6 @@ class InitialConditionsWindow(ASubMainWindow, ListedSubWindow):
self.generate_discharge 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) self._table.dataChanged.connect(self._update_plot)
def index_selected_row(self): def index_selected_row(self):
@@ -227,19 +220,19 @@ class InitialConditionsWindow(ASubMainWindow, ListedSubWindow):
self._table.move_down(row) self._table.move_down(row)
self._update_plot() self._update_plot()
def copy(self): def _copy(self):
logger.info("TODO: copy") logger.info("TODO: copy")
self._update_plot() self._update_plot()
def paste(self): def _paste(self):
logger.info("TODO: paste") logger.info("TODO: paste")
self._update_plot() self._update_plot()
def undo(self): def _undo(self):
self._table.undo() self._table.undo()
self._update_plot() self._update_plot()
def redo(self): def _redo(self):
self._table.redo() self._table.redo()
self._update_plot() self._update_plot()
+18 -17
View File
@@ -18,23 +18,24 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
table_headers = { class ICTranslate(PamhyrTranslate):
# "name": _translate("LateralContribution", "Name"), def __init__(self):
"kp": _translate("LateralContribution", "KP (m)"), super(ICTranslate, self).__init__()
# "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"),
}
def retranslate(): self._dict["elevation"] = _translate("InitialCondition", "Elevation (m)")
# table_headers["name"] = _translate("LateralContribution", "Name") self._dict["discharge"] = _translate("InitialCondition", "Discharge (m³/s)")
table_headers["kp"] = _translate("LateralContribution", "KP (m)") self._dict["kp"] = _translate("InitialCondition", "KP (m)")
# table_headers["speed"] = _translate("LateralContribution", "Speed (m/s)")
table_headers["discharge"] = _translate("LateralContribution", "Discharge (m³/s)") self._sub_dict["table_headers"] = {
table_headers["elevation"] = _translate("LateralContribution", "Elevation (m)") # "name": _translate("InitialCondition", "Name"),
table_headers["height"] = _translate("LateralContribution", "Height (m)") "kp": _translate("InitialCondition", "KP (m)"),
# table_headers["comment"] = _translate("LateralContribution", "Comment") # "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 datetime import datetime
from tools import timer, trace from tools import timer, trace
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -29,15 +29,19 @@ from View.LateralContribution.Edit.translate import *
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class Plot(APlot): class Plot(PamhyrPlot):
def __init__(self, canvas=None, data=None, def __init__(self, mode = "time", data=None,
mode = "time", toolbar=None): canvas=None, trad=None, toolbar=None,
parent=None):
super(Plot, self).__init__( super(Plot, self).__init__(
canvas=canvas, canvas = canvas,
data=data, trad = trad,
toolbar=toolbar data = data,
toolbar = toolbar,
parent = parent
) )
self._table_headers = self._trad.get_dict("table_headers")
self._mode = mode self._mode = mode
def custom_ticks(self): def custom_ticks(self):
@@ -105,10 +109,10 @@ class Plot(APlot):
# Plot label # Plot label
header = self.data.header header = self.data.header
self.canvas.axes.set_xlabel( 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( 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) 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 tools import trace, timer
from View.ASubWindow import ASubMainWindow, AWidget
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrTable import PamhyrTableModel from View.Tools.PamhyrTable import PamhyrTableModel
from PyQt5.QtCore import ( from PyQt5.QtCore import (
+40 -52
View File
@@ -18,8 +18,7 @@
from tools import timer, trace from tools import timer, trace
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from View.Tools.PamhyrDelegate import PamhyrExTimeDelegate from View.Tools.PamhyrDelegate import PamhyrExTimeDelegate
from PyQt5.QtGui import ( from PyQt5.QtGui import (
@@ -37,67 +36,60 @@ from PyQt5.QtWidgets import (
QHeaderView, QHeaderView,
) )
from View.Plot.MplCanvas import MplCanvas from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.LateralContribution.translate import long_types from View.LateralContribution.Edit.translate import LCETranslate
from View.LateralContribution.Edit.translate import table_headers, retranslate
from View.LateralContribution.Edit.Table import TableModel from View.LateralContribution.Edit.Table import TableModel
from View.LateralContribution.Edit.Plot import Plot from View.LateralContribution.Edit.Plot import Plot
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow): class EditLateralContributionWindow(PamhyrWindow):
def __init__(self, title="Edit lateral contribution", _pamhyr_ui = "EditLateralContribution"
data=None, study=None, parent=None): _pamhyr_name = "Edit lateral contribution"
self._data = data
self._study = study
self._title = title
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__( 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_table()
self.setup_plot() self.setup_plot()
self.setup_connections() 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): def setup_table(self):
retranslate()
headers = {}
for h in self._data.header:
headers[h] = table_headers[h]
self._delegate_time = PamhyrExTimeDelegate( self._delegate_time = PamhyrExTimeDelegate(
data = self._data, data = self._data,
mode = self._study.time_system, mode = self._study.time_system,
parent = self 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") table = self.find(QTableView, "tableView")
self._table = TableModel( self._table = TableModel(
table_view = table, table_view = table,
@@ -108,6 +100,7 @@ class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow):
}, },
data = self._data, data = self._data,
undo = self._undo_stack, undo = self._undo_stack,
trad = self._trad,
opt_data = self._study.time_system opt_data = self._study.time_system
) )
@@ -130,20 +123,16 @@ class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow):
data = self._data, data = self._data,
mode = self._study.time_system, mode = self._study.time_system,
toolbar = self.toolbar, toolbar = self.toolbar,
trad = self._trad,
parent = self
) )
self.plot.draw() self.plot.draw()
def setup_connections(self): def setup_connections(self):
self.find(QAction, "action_add").triggered.connect(self.add) self.find(QAction, "action_add").triggered.connect(self.add)
self.find(QAction, "action_del").triggered.connect(self.delete) self.find(QAction, "action_del").triggered.connect(self.delete)
self.find(QAction, "action_sort").triggered.connect(self.sort) 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) self._table.dataChanged.connect(self.update)
def update(self): def update(self):
@@ -199,8 +188,7 @@ class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow):
self._table.move_down(row) self._table.move_down(row)
self.plot.update() self.plot.update()
def _copy(self):
def copy(self):
rows = self.index_selected_rows() rows = self.index_selected_rows()
table = [] table = []
@@ -212,7 +200,7 @@ class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow):
self.copyTableIntoClipboard(table) self.copyTableIntoClipboard(table)
def paste(self): def _paste(self):
header, data = self.parseClipboardTable() header, data = self.parseClipboardTable()
if len(data) == 0: if len(data) == 0:
@@ -226,10 +214,10 @@ class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow):
self._table.paste(row, header, data) self._table.paste(row, header, data)
self.plot.update() self.plot.update()
def undo(self): def _undo(self):
self._table.undo() self._table.undo()
self.plot.update() self.plot.update()
def redo(self): def _redo(self):
self._table.redo() self._table.redo()
self.plot.update() self.plot.update()
+14 -15
View File
@@ -18,21 +18,20 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
from View.LateralContribution.translate import LCTranslate
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
table_headers = { class LCETranslate(LCTranslate):
"x": _translate("LateralContribution", "X"), def __init__(self):
"y": _translate("LateralContribution", "Y"), super(LCETranslate, self).__init__()
"time": _translate("LateralContribution", "Time"),
"date": _translate("LateralContribution", "Date"),
"discharge": _translate("LateralContribution", "Discharge (m³/s)"),
"z": _translate("LateralContribution", "Z (m)")
}
def retranslate(): self._sub_dict["table_headers"] = {
table_headers["x"] = _translate("LateralContribution", "X") "x": _translate("LateralContribution", "X"),
table_headers["y"] = _translate("LateralContribution", "Y") "y": _translate("LateralContribution", "Y"),
table_headers["time"] = _translate("LateralContribution", "Time") "time": _translate("LateralContribution", "Time"),
table_headers["date"] = _translate("LateralContribution", "Date") "date": _translate("LateralContribution", "Date"),
table_headers["discharge"] = _translate("LateralContribution", "Discharge (m³/s)") "discharge": _translate("LateralContribution", "Discharge (m³/s)"),
table_headers["z"] = _translate("LateralContribution", "Z (m)") "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.Tools.PamhyrTable import PamhyrTableModel
from View.LateralContribution.translate import * from View.LateralContribution.translate import LC_types
logger = logging.getLogger() logger = logging.getLogger()
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class ComboBoxDelegate(QItemDelegate): 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) super(ComboBoxDelegate, self).__init__(parent)
self._data = data self._data = data
self._mode = mode self._mode = mode
self._tab = tab self._tab = tab
self._trad = trad
def createEditor(self, parent, option, index): def createEditor(self, parent, option, index):
self.editor = QComboBox(parent) self.editor = QComboBox(parent)
long_types = self._trad.get_dict("long_types")
if self._mode == "type": if self._mode == "type":
lst = list( lst = list(
@@ -108,6 +110,7 @@ class TableModel(PamhyrTableModel):
def _setup_lst(self): def _setup_lst(self):
self._lst = self._data.lateral_contribution self._lst = self._data.lateral_contribution
self._tab = self._opt_data self._tab = self._opt_data
self._long_types = self._trad.get_dict("long_types")
def rowCount(self, parent): def rowCount(self, parent):
return self._lst.len(self._tab) return self._lst.len(self._tab)
@@ -123,7 +126,7 @@ class TableModel(PamhyrTableModel):
return self._lst.get(self._tab, row).name return self._lst.get(self._tab, row).name
elif self._headers[column] == "type": elif self._headers[column] == "type":
t = self._lst.get(self._tab, row).lctype t = self._lst.get(self._tab, row).lctype
return long_types[t] return self._long_types[t]
elif self._headers[column] == "edge": elif self._headers[column] == "edge":
n = self._lst.get(self._tab, row).edge n = self._lst.get(self._tab, row).edge
if n is None: if n is None:
@@ -151,7 +154,7 @@ class TableModel(PamhyrTableModel):
) )
) )
elif self._headers[column] == "type": 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( self._undo.push(
SetTypeCommand( SetTypeCommand(
self._lst, self._tab, row, LC_types[key] self._lst, self._tab, row, LC_types[key]
+22 -34
View File
@@ -20,8 +20,7 @@ import logging
from tools import trace, timer from tools import trace, timer
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -54,46 +53,37 @@ from View.LateralContribution.Table import (
TableModel, ComboBoxDelegate TableModel, ComboBoxDelegate
) )
from View.Plot.MplCanvas import MplCanvas from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Geometry.PlotXY import PlotXY from View.Geometry.PlotXY import PlotXY
from View.LateralContribution.translate import ( from View.LateralContribution.translate import (
long_types, table_headers, LC_types, LC_types, LCTranslate,
retranslate,
) )
from View.LateralContribution.Edit.Window import EditLateralContributionWindow from View.LateralContribution.Edit.Window import EditLateralContributionWindow
_translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class LateralContributionWindow(ASubMainWindow, ListedSubWindow): class LateralContributionWindow(PamhyrWindow):
def __init__(self, title="Lateral contribution", study=None, parent=None): _pamhyr_ui = "LateralContributions"
self._title = title + " - " + study.name _pamhyr_name = "Lateral contribution"
def __init__(self, study=None, config=None, parent=None):
name = self._pamhyr_name + " - " + study.name
super(LateralContributionWindow, self).__init__( 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._lcs = self._study.river.lateral_contribution
self.setup_sc()
self.setup_table() self.setup_table()
self.setup_graph() self.setup_graph()
self.setup_connections() 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): def setup_table(self):
retranslate()
self._table = {} self._table = {}
for t in ["liquid", "solid", "suspenssion"]: for t in ["liquid", "solid", "suspenssion"]:
@@ -101,19 +91,21 @@ class LateralContributionWindow(ASubMainWindow, ListedSubWindow):
data = self._study.river, data = self._study.river,
mode = "type", mode = "type",
tab = t, tab = t,
trad = self._trad,
parent=self parent=self
) )
self._delegate_edge = ComboBoxDelegate( self._delegate_edge = ComboBoxDelegate(
data = self._study.river, data = self._study.river,
mode = "edge", mode = "edge",
tab = t, tab = t,
trad = self._trad,
parent=self parent=self
) )
table = self.find(QTableView, f"tableView_{t}") table = self.find(QTableView, f"tableView_{t}")
self._table[t] = TableModel( self._table[t] = TableModel(
table_view = table, table_view = table,
table_headers = table_headers, table_headers = self._trad.get_dict("table_headers"),
editable_headers = True, editable_headers = True,
delegates = { delegates = {
"type": self._delegate_type, "type": self._delegate_type,
@@ -121,6 +113,7 @@ class LateralContributionWindow(ASubMainWindow, ListedSubWindow):
}, },
data = self._study.river, data = self._study.river,
undo = self._undo_stack, undo = self._undo_stack,
trad = self._trad,
opt_data = t, opt_data = t,
) )
table.setModel(self._table[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_edit").triggered.connect(self.edit)
self.find(QAction, "action_sort").triggered.connect(self.sort) 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"]: for t in ["liquid", "solid", "suspenssion"]:
table = self.find(QTableView, f"tableView_{t}") table = self.find(QTableView, f"tableView_{t}")
table.selectionModel()\ table.selectionModel()\
@@ -247,20 +235,20 @@ class LateralContributionWindow(ASubMainWindow, ListedSubWindow):
self._table[tab].move_down(row) self._table[tab].move_down(row)
self._set_current_reach() self._set_current_reach()
def copy(self): def _copy(self):
logger.info("TODO: copy") logger.info("TODO: copy")
self._set_current_reach() self._set_current_reach()
def paste(self): def _paste(self):
logger.info("TODO: paste") logger.info("TODO: paste")
self._set_current_reach() self._set_current_reach()
def undo(self): def _undo(self):
tab = self.current_tab() tab = self.current_tab()
self._table[tab].undo() self._table[tab].undo()
self._set_current_reach() self._set_current_reach()
def redo(self): def _redo(self):
tab = self.current_tab() tab = self.current_tab()
self._table[tab].redo() self._table[tab].redo()
self._set_current_reach() self._set_current_reach()
+19 -25
View File
@@ -18,27 +18,14 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
from Model.LateralContribution.LateralContributionTypes import ( from Model.LateralContribution.LateralContributionTypes import (
NotDefined, LateralContrib, Rain, Evaporation, NotDefined, LateralContrib, Rain, Evaporation,
) )
_translate = QCoreApplication.translate _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 = { LC_types = {
"ND": NotDefined, "ND": NotDefined,
"LC": LateralContrib, "LC": LateralContrib,
@@ -46,14 +33,21 @@ LC_types = {
"EV": Evaporation, "EV": Evaporation,
} }
def retranslate(): class LCTranslate(PamhyrTranslate):
table_headers["name"] = _translate("LateralContribution", "Name") def __init__(self):
table_headers["type"] = _translate("LateralContribution", "Type") super(LCTranslate, self).__init__()
table_headers["edge"] = _translate("LateralContribution", "Reach")
table_headers["begin_kp"] = _translate("LateralContribution", "Begin kp (m)")
table_headers["end_kp"] = _translate("LateralContribution", "End kp (m)")
long_types["ND"] = _translate("LateralContribution", "Not defined") self._sub_dict["long_types"] = {
long_types["LC"] = _translate("LateralContribution", "Lateral contribution") "ND": _translate("LateralContribution", "Not defined"),
long_types["RA"] = _translate("LateralContribution", "Rain") "LC": _translate("LateralContribution", "Lateral contribution"),
long_types["EV"] = _translate("LateralContribution", "Evaporation") "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 PyQt5.uic import loadUi
from View.ASubWindow import WindowToolKit from View.Tools.ASubWindow import WindowToolKit
from View.ListedSubWindow import ListedSubWindow from View.Tools.ListedSubWindow import ListedSubWindow
from View.DummyWindow import DummyWindow from View.DummyWindow import DummyWindow
from View.Configure.Window import ConfigureWindow 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.RunSolver.Window import SelectSolverWindow, SolverLogWindow
from View.CheckList.Window import CheckListWindow from View.CheckList.Window import CheckListWindow
from View.Results.Window import ResultsWindow from View.Results.Window import ResultsWindow
from View.Doc.Window import DocWindow
from View.Debug.Window import ReplWindow from View.Debug.Window import ReplWindow
from Model.Study import Study from Model.Study import Study
@@ -108,9 +109,10 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
self.conf = conf self.conf = conf
# Model # Model
self.model = None self._study = None
# Results # Results
self._last_solver = None
self._last_results = None self._last_results = None
# UI # UI
@@ -133,8 +135,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def set_title(self): def set_title(self):
title = "(dbg) " if self.conf.debug else "" title = "(dbg) " if self.conf.debug else ""
if self.model is not None: if self._study is not None:
title += f"Pamhyr2 - {self.model.name}" title += f"Pamhyr2 - {self._study.name}"
self.setWindowTitle(title) self.setWindowTitle(title)
else: else:
title += "Pamhyr2" title += "Pamhyr2"
@@ -150,6 +152,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
logger.debug(f"Set {action} to {enable}")
self.findChild(QAction, action).setEnabled(enable) self.findChild(QAction, action).setEnabled(enable)
def setup_sc(self): def setup_sc(self):
@@ -181,7 +184,12 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
"action_menu_sediment_layers": self.open_sediment_layers, "action_menu_sediment_layers": self.open_sediment_layers,
"action_menu_edit_reach_sediment_layers": self.open_reach_sediment_layers, "action_menu_edit_reach_sediment_layers": self.open_reach_sediment_layers,
"action_menu_close": self.close_model, "action_menu_close": self.close_model,
"action_menu_results_last": self.open_last_results,
## Help ## 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, "action_menu_about": self.open_about,
# ToolBar action # ToolBar action
"action_toolBar_quit": self.close, "action_toolBar_quit": self.close,
@@ -217,7 +225,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
super(ApplicationWindow, self).changeEvent(event) super(ApplicationWindow, self).changeEvent(event)
def close(self): 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 self._close_question = True
if self.dialog_close(): if self.dialog_close():
# PAMHYR is close correctly (no crash) # PAMHYR is close correctly (no crash)
@@ -234,7 +242,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def closeEvent(self, event): def closeEvent(self, event):
if not self._close_question: 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): if self.dialog_close(cancel = False):
# PAMHYR is close correctly (no crash) # PAMHYR is close correctly (no crash)
self.conf.set_close_correctly() self.conf.set_close_correctly()
@@ -292,16 +300,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
######### #########
def get_model(self): def get_model(self):
return self.model return self._study
def set_model(self, model): def set_model(self, model):
self.model = model self._study = model
self.update_enable_action() self.update_enable_action()
self.conf.set_last_study(self.model.filename) self.conf.set_last_study(self._study.filename)
self.set_title() self.set_title()
def close_model(self): def close_model(self):
self.model = None self._study = None
self.update_enable_action() self.update_enable_action()
self.conf.set_close_correctly() self.conf.set_close_correctly()
self.set_title() self.set_title()
@@ -315,7 +323,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
no_model = self.model is None no_model = self._study is None
for action in no_model_action: for action in no_model_action:
self.enable_actions(action, no_model) self.enable_actions(action, no_model)
@@ -326,9 +334,12 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
for action in model_action: for action in model_action:
self.enable_actions(action, not no_model) 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._last_results = results
self.enable_actions("action_menu_results_last", True)
############ ############
# FEATURES # # FEATURES #
############ ############
@@ -343,7 +354,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Nothing Nothing
""" """
self.set_model(Study.open(filename)) 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() self.set_title()
def save_study(self): def save_study(self):
@@ -355,22 +366,22 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing 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( file_name, _ = QFileDialog.getSaveFileName(
self, "Save File", self, "Save File",
"", "Pamhyr(*.pamhyr)" "", "Pamhyr(*.pamhyr)"
) )
if file_name.rsplit(".", 1)[-1] == "pamhyr": if file_name.rsplit(".", 1)[-1] == "pamhyr":
self.model.filename = file_name self._study.filename = file_name
else: else:
self.model.filename = file_name + ".pamhyr" self._study.filename = file_name + ".pamhyr"
if self.model.is_saved: if self._study.is_saved:
return return
logger.info("Save...") logger.info("Save...")
self.model.save() self._study.save()
def save_as_study(self): def save_as_study(self):
"""Save current study as new file """Save current study as new file
@@ -387,11 +398,11 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
) )
if file_name[-4:] == ".pamhyr": if file_name[-4:] == ".pamhyr":
self.model.filename = file_name self._study.filename = file_name
else: else:
self.model.filename = file_name + ".pamhyr" self._study.filename = file_name + ".pamhyr"
self.model.save() self._study.save()
################## ##################
# MSG AND DIALOG # # MSG AND DIALOG #
@@ -457,7 +468,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
self.config = ConfigureWindow(conf=self.conf, parent=self) self.config = ConfigureWindow(config=self.conf, parent=self)
self.config.show() self.config.show()
def open_about(self): def open_about(self):
@@ -477,7 +488,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
if self.model is None: if self._study is None:
dialog = QFileDialog(self) dialog = QFileDialog(self)
dialog.setFileMode(QFileDialog.FileMode.ExistingFile) dialog.setFileMode(QFileDialog.FileMode.ExistingFile)
dialog.setDefaultSuffix(".pamhyr") dialog.setDefaultSuffix(".pamhyr")
@@ -495,7 +506,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
if self.model is None: if self._study is None:
self.new_study = NewStudyWindow(parent=self) self.new_study = NewStudyWindow(parent=self)
self.new_study.show() self.new_study.show()
@@ -505,8 +516,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
if not self.model is None: if not self._study is None:
self.new_study = NewStudyWindow(study=self.model, parent=self) self.new_study = NewStudyWindow(study=self._study, parent=self)
self.new_study.show() self.new_study.show()
def open_network(self): def open_network(self):
@@ -515,9 +526,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
if self.model is not None: if self._study is not None:
if not self.sub_win_exists("River network"): 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() self.network.show()
else: else:
self.network.activateWindow() self.network.activateWindow()
@@ -528,14 +539,14 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing 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 = self.sub_win_filter_first(
"Geometry", "Geometry",
contain = [self.model.river.current_reach().name] contain = [self._study.river.current_reach().name]
) )
if geometry is None: if geometry is None:
geometry = GeometryWindow(model=self.model, parent=self) geometry = GeometryWindow(study=self._study, config=self.conf, parent=self)
geometry.show() geometry.show()
else: else:
geometry.activateWindow() geometry.activateWindow()
@@ -549,7 +560,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
) )
if bound is None: if bound is None:
bound = BoundaryConditionWindow(study = self.model, parent = self) bound = BoundaryConditionWindow(study = self._study, parent = self)
bound.show() bound.show()
else: else:
bound.activateWindow() bound.activateWindow()
@@ -561,7 +572,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
) )
if lateral is None: if lateral is None:
lateral = LateralContributionWindow(study = self.model, parent = self) lateral = LateralContributionWindow(study = self._study, parent = self)
lateral.show() lateral.show()
else: else:
lateral.activateWindow() lateral.activateWindow()
@@ -574,7 +585,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if strick is None: if strick is None:
strick = StricklersWindow( strick = StricklersWindow(
study = self.model, study = self._study,
config = self.conf, config = self.conf,
parent = self parent = self
) )
@@ -583,17 +594,17 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
strick.activateWindow() strick.activateWindow()
def open_frictions(self): def open_frictions(self):
if (self.model is not None and if (self._study is not None and
self.model.river.has_current_reach()): self._study.river.has_current_reach()):
frictions = self.sub_win_filter_first( frictions = self.sub_win_filter_first(
"Frictions", "Frictions",
contain = [self.model.river.current_reach().name] contain = [self._study.river.current_reach().name]
) )
if frictions is None: if frictions is None:
frictions = FrictionsWindow( frictions = FrictionsWindow(
study = self.model, study = self._study,
parent = self parent = self
) )
frictions.show() frictions.show()
@@ -603,15 +614,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
self.msg_select_reach() self.msg_select_reach()
def open_initial_conditions(self): 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 = self.sub_win_filter_first(
"Initial condition", "Initial condition",
contain = [self.model.river.current_reach().name] contain = [self._study.river.current_reach().name]
) )
if initial is None: if initial is None:
initial = InitialConditionsWindow( initial = InitialConditionsWindow(
study = self.model, study = self._study,
config = self.conf,
parent = self parent = self
) )
initial.show() initial.show()
@@ -628,7 +640,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if params is None: if params is None:
params = SolverParametersWindow( params = SolverParametersWindow(
study = self.model, study = self._study,
parent = self parent = self
) )
params.show() params.show()
@@ -637,31 +649,31 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def open_sediment_layers(self): def open_sediment_layers(self):
sl = SedimentLayersWindow( sl = SedimentLayersWindow(
study = self.model, study = self._study,
parent = self parent = self
) )
sl.show() sl.show()
def open_reach_sediment_layers(self): def open_reach_sediment_layers(self):
sl = ReachSedimentLayersWindow( sl = ReachSedimentLayersWindow(
study = self.model, study = self._study,
parent = self parent = self
) )
sl.show() sl.show()
def run_solver(self): def run_solver(self):
if self.model is None: if self._study is None:
return return
run = SelectSolverWindow( run = SelectSolverWindow(
study = self.model, study = self._study,
config = self.conf, config = self.conf,
parent = self parent = self
) )
if run.exec(): if run.exec():
solver = run.solver solver = run.solver
check = CheckListWindow( check = CheckListWindow(
study = self.model, study = self._study,
config = self.conf, config = self.conf,
solver = solver, solver = solver,
parent = self parent = self
@@ -670,7 +682,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def solver_log(self, solver): def solver_log(self, solver):
sol = SolverLogWindow( sol = SolverLogWindow(
study = self.model, study = self._study,
config = self.conf, config = self.conf,
solver = solver, solver = solver,
parent = self parent = self
@@ -694,7 +706,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if res is None: if res is None:
res = ResultsWindow( res = ResultsWindow(
study = self.model, study = self._study,
solver = solver, solver = solver,
results = results, results = results,
parent = self parent = self
@@ -703,24 +715,44 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
else: else:
res.activateWindow() 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 # # DEBUG #
######### #########
def open_debug(self): def open_debug(self):
repl = ReplWindow( repl = ReplWindow(
study = self.model, study = self._study,
config = self.conf, config = self.conf,
parent = self parent = self
) )
repl.show() repl.show()
def open_sqlite(self): def open_sqlite(self):
if self.model is None: if self._study is None:
logger.debug("No study open for sql debuging...") logger.debug("No study open for sql debuging...")
return return
file = self.model.filename file = self._study.filename
_ = subprocess.Popen( _ = subprocess.Popen(
f"sqlitebrowser {file}", f"sqlitebrowser {file}",
shell=True shell=True
-1
View File
@@ -22,7 +22,6 @@ import traceback
from Model.Network.Node import Node from Model.Network.Node import Node
from Model.Network.Edge import Edge from Model.Network.Edge import Edge
from Model.Network.Graph import Graph from Model.Network.Graph import Graph
from View.ASubWindow import ASubWindow
from View.Network.GraphWidget import GraphWidget from View.Network.GraphWidget import GraphWidget
from View.Network.UndoCommand import * from View.Network.UndoCommand import *
from View.Tools.PamhyrTable import PamhyrTableModel from View.Tools.PamhyrTable import PamhyrTableModel
+26 -33
View File
@@ -16,6 +16,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import ( from PyQt5.QtGui import (
@@ -36,55 +38,47 @@ from PyQt5.QtWidgets import (
from Model.River import RiverNode, RiverReach, River 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.GraphWidget import GraphWidget
from View.Network.UndoCommand import * from View.Network.UndoCommand import *
from View.Network.translate import ( from View.Network.translate import NetworkTranslate
table_headers_node, table_headers_edge,
retranslate,
)
from View.Network.Table import ( from View.Network.Table import (
ComboBoxDelegate, NodeTableModel, EdgeTableModel, ComboBoxDelegate, NodeTableModel, EdgeTableModel,
) )
logger = logging.getLogger()
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class NetworkWindow(ASubMainWindow): class NetworkWindow(PamhyrWindow):
def __init__(self, model=None, title="River network", parent=None): _pamhyr_ui = "Network"
self._title = title _pamhyr_name = "River network"
self._model = model
self._graph = self._model.river
self.setup_title()
def __init__(self, study=None, config=None, parent=None):
super(NetworkWindow, self).__init__( 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_graph()
self.setup_table() self.setup_table()
self.setup_connections() 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): def setup_table(self):
retranslate()
# Nodes table # Nodes table
table = self.find(QTableView, "tableView_nodes") table = self.find(QTableView, "tableView_nodes")
self._nodes_model = NodeTableModel( self._nodes_model = NodeTableModel(
table_view = table, table_view = table,
table_headers = table_headers_node, table_headers = self._table_headers_node,
editable_headers = ["name"], editable_headers = ["name"],
data = self._graph, data = self._graph,
undo = self._undo_stack, undo = self._undo_stack,
@@ -103,7 +97,7 @@ class NetworkWindow(ASubMainWindow):
self._reachs_model = EdgeTableModel( self._reachs_model = EdgeTableModel(
table_view = table, table_view = table,
table_headers = table_headers_edge, table_headers = self._table_headers_edge,
editable_headers = ["name", "node1", "node2"], editable_headers = ["name", "node1", "node2"],
delegates = { delegates = {
"node1": self.delegate_combobox, "node1": self.delegate_combobox,
@@ -143,9 +137,6 @@ class NetworkWindow(ASubMainWindow):
self.clicked_del self.clicked_del
) )
self.undo_sc.activated.connect(self.undo)
self.redo_sc.activated.connect(self.redo)
def clicked_add(self): def clicked_add(self):
if self.get_action_checkable("action_toolBar_add"): if self.get_action_checkable("action_toolBar_add"):
self.set_action_checkable("action_toolBar_del", False) self.set_action_checkable("action_toolBar_del", False)
@@ -166,13 +157,15 @@ class NetworkWindow(ASubMainWindow):
if key == Qt.Key_Escape: if key == Qt.Key_Escape:
self._graph_widget.reset_selection self._graph_widget.reset_selection
def undo(self): # Redefine undo/redo method
def _undo(self):
self._undo_stack.undo() self._undo_stack.undo()
self._reachs_model.update() self._reachs_model.update()
self._nodes_model.update() self._nodes_model.update()
self._graph_widget.display_update() self._graph_widget.display_update()
def redo(self): def _redo(self):
self._undo_stack.redo() self._undo_stack.redo()
self._reachs_model.update() self._reachs_model.update()
self._nodes_model.update() self._nodes_model.update()
+14 -16
View File
@@ -18,23 +18,21 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
table_headers_node = { class NetworkTranslate(PamhyrTranslate):
"name": _translate("Network", "Name"), def __init__(self):
"type": _translate("Network", "Type"), super(NetworkTranslate, self).__init__()
}
table_headers_edge = { self._sub_dict["table_headers_node"] = {
"name": _translate("Network", "Name"), "name": _translate("Network", "Name"),
"node1": _translate("Network", "Source node"), "type": _translate("Network", "Type"),
"node2": _translate("Network", "Destination node"), }
}
def retranslate(): self._sub_dict["table_headers_edge"] = {
table_headers_node["name"] = _translate("Network", "Name") "name": _translate("Network", "Name"),
table_headers_node["type"] = _translate("Network", "Type") "node1": _translate("Network", "Source node"),
"node2": _translate("Network", "Destination node"),
table_headers_edge["name"] = _translate("Network", "Name") }
table_headers_edge["node1"] = _translate("Network", "Source node")
table_headers_edge["node2"] = _translate("Network", "Destination node")
+10 -8
View File
@@ -17,7 +17,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from tools import timer from tools import timer
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -25,14 +25,16 @@ from PyQt5.QtCore import (
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class PlotAC(APlot): class PlotAC(PamhyrPlot):
def __init__(self, canvas=None, results=None, def __init__(self, canvas=None, trad=None, toolbar=None,
reach_id=0, profile_id=0, results=None, reach_id=0, profile_id=0,
toolbar=None): parent=None):
super(PlotAC, self).__init__( super(PlotAC, self).__init__(
canvas=canvas, canvas = canvas,
data=results, trad = trad,
toolbar=toolbar data = results,
toolbar = toolbar,
parent = parent
) )
self._current_timestamp = max(results.get("timestamps")) self._current_timestamp = max(results.get("timestamps"))
+10 -8
View File
@@ -22,7 +22,7 @@ from functools import reduce
from datetime import datetime from datetime import datetime
from tools import timer, trace from tools import timer, trace
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -32,14 +32,16 @@ _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class PlotH(APlot): class PlotH(PamhyrPlot):
def __init__(self, canvas=None, results=None, def __init__(self, canvas=None, trad=None, toolbar=None,
reach_id=0, profile_id=0, results=None, reach_id=0, profile_id=0,
toolbar=None): parent=None):
super(PlotH, self).__init__( super(PlotH, self).__init__(
canvas=canvas, canvas = canvas,
data=results, trad = trad,
toolbar=toolbar data = results,
toolbar = toolbar,
parent = parent
) )
self._mode = "time" self._mode = "time"
+10 -8
View File
@@ -17,7 +17,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from tools import timer from tools import timer
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -25,14 +25,16 @@ from PyQt5.QtCore import (
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class PlotKPC(APlot): class PlotKPC(PamhyrPlot):
def __init__(self, canvas=None, results=None, def __init__(self, canvas=None, trad=None, toolbar=None,
reach_id=0, profile_id=0, results=None, reach_id=0, profile_id=0,
toolbar=None): parent=None):
super(PlotKPC, self).__init__( super(PlotKPC, self).__init__(
canvas=canvas, canvas = canvas,
data=results, trad = trad,
toolbar=toolbar data = results,
toolbar = toolbar,
parent = parent
) )
self._current_timestamp = max(results.get("timestamps")) self._current_timestamp = max(results.get("timestamps"))
+10 -8
View File
@@ -5,7 +5,7 @@ import logging
from functools import reduce from functools import reduce
from tools import timer from tools import timer
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -15,14 +15,16 @@ _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class PlotSedProfile(APlot): class PlotSedProfile(PamhyrPlot):
def __init__(self, canvas=None, study=None, results=None, def __init__(self, canvas=None, trad=None, toolbar=None,
reach_id=0, profile_id=0, results=None, reach_id=0, profile_id=0,
toolbar=None): parent=None):
super(PlotSedProfile, self).__init__( super(PlotSedProfile, self).__init__(
canvas=canvas, canvas = canvas,
data=study, trad = trad,
toolbar=toolbar data = results,
toolbar = toolbar,
parent = parent
) )
self._results = results self._results = results
+10 -8
View File
@@ -5,7 +5,7 @@ import logging
from functools import reduce from functools import reduce
from tools import timer from tools import timer
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -15,14 +15,16 @@ _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class PlotSedReach(APlot): class PlotSedReach(PamhyrPlot):
def __init__(self, canvas=None, study=None, results=None, def __init__(self, canvas=None, trad=None, toolbar=None,
reach_id=0, profile_id=0, results=None, reach_id=0, profile_id=0,
toolbar=None): parent=None):
super(PlotSedReach, self).__init__( super(PlotSedReach, self).__init__(
canvas=canvas, canvas = canvas,
data=study, trad = trad,
toolbar=toolbar data = results,
toolbar = toolbar,
parent = parent
) )
self._results = results self._results = results
+10 -8
View File
@@ -21,7 +21,7 @@ import logging
from functools import reduce from functools import reduce
from tools import timer, trace from tools import timer, trace
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -31,14 +31,16 @@ _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class PlotXY(APlot): class PlotXY(PamhyrPlot):
def __init__(self, canvas=None, results=None, def __init__(self, canvas=None, trad=None, toolbar=None,
reach_id=0, profile_id=0, results=None, reach_id=0, profile_id=0,
toolbar=None, display_current=True): display_current=True, parent=None):
super(PlotXY, self).__init__( super(PlotXY, self).__init__(
canvas=canvas, canvas = canvas,
data=results, trad = trad,
toolbar=toolbar data = results,
toolbar = toolbar,
parent = parent
) )
self.display_current = display_current self.display_current = display_current
+20 -45
View File
@@ -34,6 +34,7 @@ from PyQt5.QtWidgets import (
QComboBox, QComboBox,
) )
from View.Tools.PamhyrTable import PamhyrTableModel
from View.Results.translate import * from View.Results.translate import *
logger = logging.getLogger() logger = logging.getLogger()
@@ -41,33 +42,16 @@ logger = logging.getLogger()
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class TableModel(QAbstractTableModel): class TableModel(PamhyrTableModel):
def __init__(self, results = None, study = None, mode = None, undo=None): def _setup_lst(self):
super(QAbstractTableModel, self).__init__() _river = self._data.river
if self._opt_data == "reach":
self._lst = _river.reachs
else:
self._lst = _river.reach(0).profiles
self._results = results def __init__(self, **kwargs):
self._study = study super(TableModel, self).__init__(**kwargs)
self._mode = mode
self._undo_stack = undo
self._table_headers = table_headers_reach
if mode != "reach":
self._table_headers = table_headers_profile
self._headers = list(self._table_headers.keys())
self._selected = 0
self._timestamp = 0
def rowCount(self, parent=QModelIndex()):
if self._mode == "reach":
return len(self._results.river.reachs)
current_reach = self._results.river.reach(self._selected)
return len(current_reach.profiles)
def columnCount(self, parent=QModelIndex()):
return len(self._headers)
def data(self, index, role=Qt.DisplayRole): def data(self, index, role=Qt.DisplayRole):
if role != Qt.ItemDataRole.DisplayRole: if role != Qt.ItemDataRole.DisplayRole:
@@ -76,32 +60,23 @@ class TableModel(QAbstractTableModel):
row = index.row() row = index.row()
column = index.column() column = index.column()
if self._mode == "reach": if self._opt_data == "reach":
if self._headers[column] == "name": if self._headers[column] == "name":
v = self._results.river.reach(row).name v = self._lst[row].name
return str(v) return str(v)
else: else:
current_reach = self._results.river.reach(self._selected)
if self._headers[column] == "name": if self._headers[column] == "name":
v = current_reach.profile(row).name v = self._lst[row].name
return str(v) return str(v)
elif self._headers[column] == "kp": elif self._headers[column] == "kp":
v = current_reach.profile(row).kp v = self._lst[row].kp
return f"{v:.4f}" return f"{v:.4f}"
return QVariant() return QVariant()
def headerData(self, section, orientation, role=Qt.DisplayRole): def update(self, reach):
if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal: _river = self._data.river
return self._table_headers[self._headers[section]] if self._opt_data == "reach":
self._lst = _river.reachs
return QVariant() else:
self._lst = _river.reach(reach).profiles
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
+34 -59
View File
@@ -21,8 +21,7 @@ from datetime import datetime
from tools import trace, timer from tools import trace, timer
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -42,8 +41,8 @@ from PyQt5.QtWidgets import (
QSlider, QLabel, QSlider, QLabel,
) )
from View.Plot.MplCanvas import MplCanvas from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.Results.PlotXY import PlotXY from View.Results.PlotXY import PlotXY
from View.Results.PlotAC import PlotAC 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.PlotSedProfile import PlotSedProfile
from View.Results.Table import TableModel from View.Results.Table import TableModel
from View.Results.translate import ( from View.Results.translate import ResultsTranslate
table_headers_reach, table_headers_profile,
retranslate,
)
from View.Stricklers.Window import StricklersWindow from View.Stricklers.Window import StricklersWindow
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class ResultsWindow(ASubMainWindow, ListedSubWindow): class ResultsWindow(PamhyrWindow):
def __init__(self, title="Results", _pamhyr_ui = "Results"
study=None, solver=None, results=None, _pamhyr_name = "Results"
def __init__(self, study=None, config=None,
solver=None, results=None,
parent=None): parent=None):
self._study = study
self._solver = solver self._solver = solver
self._results = results self._results = results
self._timestamps = sorted(list(self._results.get("timestamps"))) self._timestamps = sorted(list(self._results.get("timestamps")))
self.setup_title(title) name = (
self._pamhyr_name + " - "
super(ResultsWindow, self).__init__( + study.name + " - "
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 + " - "
+ self._solver.name + " - " + self._solver.name + " - "
+ self._results.date + self._results.date
) )
def setup_sc(self): super(ResultsWindow, self).__init__(
self._undo_stack = QUndoStack() title = name,
study = study,
config = config,
trad = ResultsTranslate(),
parent=parent
)
self.undo_sc = QShortcut(QKeySequence.Undo, self) self.setup_table()
self.redo_sc = QShortcut(QKeySequence.Redo, self) self.setup_plot()
self.copy_sc = QShortcut(QKeySequence.Copy, self) self.setup_slider()
self.paste_sc = QShortcut(QKeySequence.Paste, self) self.setup_statusbar()
self.setup_connections()
def setup_table(self): def setup_table(self):
retranslate()
self._table = {} self._table = {}
for t in ["reach", "profile"]: for t in ["reach", "profile"]:
table = self.find(QTableView, f"tableView_{t}") table = self.find(QTableView, f"tableView_{t}")
self._table[t] = TableModel( self._table[t] = TableModel(
results = self._results, table_view = table,
study = self._study, table_headers = self._trad.get_dict(f"table_headers_{t}"),
mode = t, data = self._results,
undo = self._undo_stack, 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): def setup_slider(self):
self._slider_profile = self.find(QSlider, f"verticalSlider_profile") 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.setMaximum(len(self._timestamps) - 1)
self._slider_time.setValue(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 = MplCanvas(width=5, height=4, dpi=100)
self.canvas.setObjectName("canvas") self.canvas.setObjectName("canvas")
self.toolbar = PamhyrPlotToolbar( self.toolbar = PamhyrPlotToolbar(
@@ -219,7 +201,6 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
self.plot_sed_reach = PlotSedReach( self.plot_sed_reach = PlotSedReach(
canvas = self.canvas_5, canvas = self.canvas_5,
results = self._results, results = self._results,
study = self._study,
reach_id = 0, reach_id = 0,
profile_id = 0, profile_id = 0,
toolbar = self.toolbar_5 toolbar = self.toolbar_5
@@ -239,7 +220,6 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
self.plot_sed_profile = PlotSedProfile( self.plot_sed_profile = PlotSedProfile(
canvas = self.canvas_6, canvas = self.canvas_6,
results = self._results, results = self._results,
study = self._study,
reach_id = 0, reach_id = 0,
profile_id = 0, profile_id = 0,
toolbar = self.toolbar_6 toolbar = self.toolbar_6
@@ -289,11 +269,6 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
self._status_label.setText(txt) self._status_label.setText(txt)
def setup_connections(self): 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 = { fun = {
"reach": self._set_current_reach, "reach": self._set_current_reach,
"profile": self._set_current_profile, "profile": self._set_current_profile,
@@ -411,14 +386,14 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
timestamp = self._timestamps[self._slider_time.value()] timestamp = self._timestamps[self._slider_time.value()]
self.update(timestamp = timestamp) self.update(timestamp = timestamp)
def copy(self): def _copy(self):
logger.info("TODO: copy") logger.info("TODO: copy")
def paste(self): def _paste(self):
logger.info("TODO: paste") logger.info("TODO: paste")
def undo(self): def _undo(self):
self._table.undo() self._table.undo()
def redo(self): def _redo(self):
self._table.redo() self._table.redo()
+12 -12
View File
@@ -18,19 +18,19 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
table_headers_reach = { class ResultsTranslate(PamhyrTranslate):
"name": _translate("Results", "Reach name"), def __init__(self):
} super(ResultsTranslate, self).__init__()
table_headers_profile = { self._sub_dict["table_headers_reach"] = {
"name": _translate("Results", "Name"), "name": _translate("Results", "Reach name"),
"kp": _translate("Results", "KP (m)"), }
}
def retranslate(): self._sub_dict["table_headers_profile"] = {
table_headers_reach["name"] = _translate("Results", "Reach name") "name": _translate("Results", "Name"),
"kp": _translate("Results", "KP (m)"),
table_headers_profile["name"] = _translate("Results", "Name") }
table_headers_profile["kp"] = _translate("Results", "KP (m)")
+11 -13
View File
@@ -22,8 +22,7 @@ import os
from queue import Queue from queue import Queue
from tools import trace, timer from tools import trace, timer
from View.ASubWindow import ASubWindow, ASubMainWindow from View.Tools.PamhyrWindow import PamhyrDialog, PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -45,24 +44,23 @@ from PyQt5.QtWidgets import (
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class SolverLogFileWindow(ASubMainWindow, ListedSubWindow): class SolverLogFileWindow(PamhyrWindow):
def __init__(self, title="Solver logs", _pamhyr_ui = "SolverLogFile"
file_name = None, _pamhyr_name = "Solver logs"
def __init__(self, file_name = None,
study=None, config=None, study=None, config=None,
solver=None, parent=None): solver=None, parent=None):
self._title = title
self._parent = parent
self._study = study
self._config = config
self._solver = solver self._solver = solver
self._file_name = file_name self._file_name = file_name
super(SolverLogFileWindow, self).__init__( 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_action()
self.setup_connections() self.setup_connections()
+26 -23
View File
@@ -23,8 +23,7 @@ import tempfile
from queue import Queue from queue import Queue
from tools import trace, timer from tools import trace, timer
from View.ASubWindow import ASubWindow, ASubMainWindow from View.Tools.PamhyrWindow import PamhyrDialog, PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -56,20 +55,21 @@ _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class SelectSolverWindow(ASubWindow, ListedSubWindow): class SelectSolverWindow(PamhyrDialog):
def __init__(self, title="Select solver", _pamhyr_ui = "SelectSolver"
study=None, config=None, _pamhyr_name = "Select solver"
parent=None):
self._title = title
self._study = study def __init__(self, study=None, config=None,
self._config = config parent=None):
self._solver = None self._solver = None
super(SelectSolverWindow, self).__init__( 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_combobox()
self.setup_connections() self.setup_connections()
@@ -101,24 +101,22 @@ class SelectSolverWindow(ASubWindow, ListedSubWindow):
super(SelectSolverWindow, self).accept() super(SelectSolverWindow, self).accept()
class SolverLogWindow(PamhyrWindow):
_pamhyr_ui = "SolverLog"
_pamhyr_name = "Solver Log"
class SolverLogWindow(ASubMainWindow, ListedSubWindow): def __init__(self, study=None, config=None,
def __init__(self, title="Solver logs",
study=None, config=None,
solver=None, parent=None): solver=None, parent=None):
self._title = title
self._parent = parent
self._study = study
self._config = config
self._solver = solver self._solver = solver
self._results = None self._results = None
super(SolverLogWindow, self).__init__( 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_action()
self.setup_alarm() self.setup_alarm()
@@ -206,6 +204,11 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
if self._solver.log_file() != "": if self._solver.log_file() != "":
self.find(QAction, "action_log_file").setEnabled(True) 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: while self._output.qsize() != 0:
s = self._output.get() s = self._output.get()
if type(s) is str and "[ERROR]" in s: if type(s) is str and "[ERROR]" in s:
@@ -258,7 +261,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
if self._results is None: if self._results is None:
self._results = self._solver.results(self._study, self._workdir, qlog = self._output) 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) self._parent.open_solver_results(self._solver, self._results)
def log_file(self): def log_file(self):
+10 -18
View File
@@ -5,23 +5,19 @@ import logging
from functools import reduce from functools import reduce
from tools import timer from tools import timer
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import (
QCoreApplication
)
_translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class Plot(APlot): class Plot(PamhyrPlot):
def __init__(self, canvas=None, data=None, toolbar=None, def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
display_current=True): display_current=True, parent=None):
super(Plot, self).__init__( super(Plot, self).__init__(
canvas=canvas, canvas = canvas,
data=data, trad = trad,
toolbar=toolbar data = data,
toolbar = toolbar,
parent = parent
) )
self._display_current = display_current self._display_current = display_current
@@ -34,13 +30,9 @@ class Plot(APlot):
self.canvas.axes.cla() self.canvas.axes.cla()
self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5) 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.axes.get_xaxis().set_visible(False)
self.canvas.axes.set_ylabel( self.canvas.axes.set_ylabel(
_translate("MainWindow_reach", "Height (m)"), self._trad["height"],
color='green', fontsize=12 color='green', fontsize=12
) )
+20 -44
View File
@@ -15,32 +15,14 @@ from PyQt5.QtWidgets import (
QComboBox, QComboBox,
) )
from View.Tools.PamhyrTable import PamhyrTableModel
from View.SedimentLayers.Edit.UndoCommand import * from View.SedimentLayers.Edit.UndoCommand import *
from View.SedimentLayers.Edit.translate import *
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class TableModel(QAbstractTableModel): class TableModel(PamhyrTableModel):
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)
def data(self, index, role): def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole: if role != Qt.ItemDataRole.DisplayRole:
return QVariant() return QVariant()
@@ -49,23 +31,17 @@ class TableModel(QAbstractTableModel):
column = index.column() column = index.column()
if self._headers[column] == "name": if self._headers[column] == "name":
return self._sl.get(row).name return self._data.get(row).name
elif self._headers[column] == "type": elif self._headers[column] == "type":
return self._sl.get(row).type return self._data.get(row).type
elif self._headers[column] == "height": elif self._headers[column] == "height":
return self._sl.get(row).height return self._data.get(row).height
elif self._headers[column] == "d50": elif self._headers[column] == "d50":
return self._sl.get(row).d50 return self._data.get(row).d50
elif self._headers[column] == "sigma": elif self._headers[column] == "sigma":
return self._sl.get(row).sigma return self._data.get(row).sigma
elif self._headers[column] == "critical_constraint": elif self._headers[column] == "critical_constraint":
return self._sl.get(row).critical_constraint return self._data.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 QVariant() return QVariant()
@@ -79,37 +55,37 @@ class TableModel(QAbstractTableModel):
if self._headers[column] == "name": if self._headers[column] == "name":
self._undo.push( self._undo.push(
SetNameCommand( SetNameCommand(
self._sl, row, value self._data, row, value
) )
) )
if self._headers[column] == "type": if self._headers[column] == "type":
self._undo.push( self._undo.push(
SetTypeCommand( SetTypeCommand(
self._sl, row, value self._data, row, value
) )
) )
if self._headers[column] == "height": if self._headers[column] == "height":
self._undo.push( self._undo.push(
SetHeightCommand( SetHeightCommand(
self._sl, row, value self._data, row, value
) )
) )
if self._headers[column] == "d50": if self._headers[column] == "d50":
self._undo.push( self._undo.push(
SetD50Command( SetD50Command(
self._sl, row, value self._data, row, value
) )
) )
if self._headers[column] == "sigma": if self._headers[column] == "sigma":
self._undo.push( self._undo.push(
SetSigmaCommand( SetSigmaCommand(
self._sl, row, value self._data, row, value
) )
) )
if self._headers[column] == "critical_constraint": if self._headers[column] == "critical_constraint":
self._undo.push( self._undo.push(
SetCriticalConstraintCommand( SetCriticalConstraintCommand(
self._sl, row, value self._data, row, value
) )
) )
@@ -121,7 +97,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
AddCommand( AddCommand(
self._sl, row self._data, row
) )
) )
@@ -133,7 +109,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
DelCommand( DelCommand(
self._sl, rows self._data, rows
) )
) )
@@ -150,7 +126,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
MoveCommand( MoveCommand(
self._sl, "up", row self._data, "up", row
) )
) )
@@ -158,7 +134,7 @@ class TableModel(QAbstractTableModel):
self.layoutChanged.emit() self.layoutChanged.emit()
def move_down(self, row, parent=QModelIndex()): def move_down(self, row, parent=QModelIndex()):
if row + 1 >= len(self._sl): if row + 1 >= len(self._data):
return return
target = row target = row
@@ -167,7 +143,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
MoveCommand( 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 tools import trace, timer
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -40,66 +39,58 @@ from PyQt5.QtWidgets import (
QComboBox, QVBoxLayout, QHeaderView, QTabWidget, QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
) )
from View.Plot.MplCanvas import MplCanvas from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.SedimentLayers.Edit.UndoCommand import * from View.SedimentLayers.Edit.UndoCommand import *
from View.SedimentLayers.Edit.Table import * from View.SedimentLayers.Edit.Table import *
from View.SedimentLayers.Edit.Plot import Plot 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 _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class EditSedimentLayersWindow(ASubMainWindow, ListedSubWindow): class EditSedimentLayersWindow(PamhyrWindow):
def __init__(self, title="Edit Sediment Layers", _pamhyr_ui = "EditSedimentLayers"
study=None, sl=None, parent=None): _pamhyr_name = "Edit Sediment Layers"
self._study = study
def __init__(self, study=None, config = None,
sl=None, parent=None):
self._sl = sl 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 name = self._sl.name
if name == "": if name == "":
name = _translate("SedimentLayers", "(no name)") name = _translate("SedimentLayers", "(no name)")
self._title = ( name = (
title + " - " + self._study.name + " - " + name self._pamhyr_name + " - " + study.name + " - " + name
) )
def setup_sc(self): super(EditSedimentLayersWindow, self).__init__(
self._undo_stack = QUndoStack() title = name,
study = study,
config = config,
trad = SedimentEditTranslate(),
parent = parent
)
self.undo_sc = QShortcut(QKeySequence.Undo, self) self.setup_table()
self.redo_sc = QShortcut(QKeySequence.Redo, self) self.setup_graph()
self.copy_sc = QShortcut(QKeySequence.Copy, self) self.setup_connections()
self.paste_sc = QShortcut(QKeySequence.Paste, self)
def setup_table(self): def setup_table(self):
retranslate() table_headers = self._trad.get_dict("table_headers")
self._table = {}
table = self.find(QTableView, f"tableView") table = self.find(QTableView, f"tableView")
self._table = TableModel( self._table = TableModel(
study = self._study, table_view = table,
sl = self._sl, table_headers = table_headers,
editable_headers = list(table_headers),
data = self._sl,
trad = self._trad,
undo = self._undo_stack, undo = self._undo_stack,
) )
table.setModel(self._table) table.setModel(self._table)
table.setSelectionBehavior(QAbstractItemView.SelectRows) table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True) table.setAlternatingRowColors(True)
@@ -120,6 +111,7 @@ class EditSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
canvas = self.canvas, canvas = self.canvas,
data = self._sl, data = self._sl,
toolbar = self.toolbar, toolbar = self.toolbar,
trad = self._trad,
display_current = False display_current = False
) )
self.plot.draw() 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_up").triggered.connect(self.move_up)
self.find(QAction, "action_move_down").triggered.connect(self.move_down) 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.dataChanged.connect(self._set_plot)
self._table.layoutChanged.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]) self._table.move_down(rows[0])
def copy(self): def _copy(self):
logger.info("TODO: copy") logger.info("TODO: copy")
def paste(self): def _paste(self):
logger.info("TODO: paste") logger.info("TODO: paste")
def undo(self): def _undo(self):
self._table.undo() self._table.undo()
def redo(self): def _redo(self):
self._table.redo() self._table.redo()
+15 -15
View File
@@ -2,21 +2,21 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from View.SedimentLayers.translate import SedimentTranslate
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
table_headers = { class SedimentEditTranslate(SedimentTranslate):
"name": _translate("SedimentLayers", "Name"), def __init__(self):
# "type": _translate("SedimentLayers", "Type"), super(SedimentEditTranslate, self).__init__()
"height": _translate("SedimentLayers", "Height"),
"d50": _translate("SedimentLayers", "D50"),
"sigma": _translate("SedimentLayers", "Sigma"),
"critical_constraint": _translate("SedimentLayers", "Critical constraint"),
}
def retranslate(): self._dict["height"] = _translate("SedimentLayers", "Height (m)"),
table_headers["name"] = _translate("SedimentLayers", "Name")
# table_headers["type"] = _translate("SedimentLayers", "Type") self._sub_dict["table_headers"] = {
table_headers["height"] = _translate("SedimentLayers", "Height") "name": _translate("SedimentLayers", "Name"),
table_headers["d50"] = _translate("SedimentLayers", "D50") # "type": _translate("SedimentLayers", "Type"),
table_headers["sigma"] = _translate("SedimentLayers", "Sigma") "height": _translate("SedimentLayers", "Height"),
table_headers["critical_constraint"] = _translate("SedimentLayers", "Critical constraint") "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 functools import reduce
from tools import timer from tools import timer
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -15,13 +15,16 @@ _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class Plot(APlot): class Plot(PamhyrPlot):
def __init__(self, canvas=None, data=None, toolbar=None, def __init__(self, data=None, display_current=True,
display_current=True): canvas=None, trad=None, toolbar=None,
parent=None):
super(Plot, self).__init__( super(Plot, self).__init__(
canvas=canvas, canvas = canvas,
data=data, trad = trad,
toolbar=toolbar data = data,
toolbar = toolbar,
parent = parent
) )
self._display_current = display_current self._display_current = display_current
@@ -41,11 +44,11 @@ class Plot(APlot):
return return
self.canvas.axes.set_xlabel( self.canvas.axes.set_xlabel(
_translate("MainWindow_reach", "Kp (m)"), self._trad["kp"],
color='green', fontsize=12 color='green', fontsize=12
) )
self.canvas.axes.set_ylabel( self.canvas.axes.set_ylabel(
_translate("MainWindow_reach", "Height (m)"), self._trad["height"],
color='green', fontsize=12 color='green', fontsize=12
) )
+10 -7
View File
@@ -5,7 +5,7 @@ import logging
from functools import reduce from functools import reduce
from tools import timer from tools import timer
from View.Plot.APlot import APlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QCoreApplication QCoreApplication
@@ -15,13 +15,16 @@ _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class Plot(APlot): class Plot(PamhyrPlot):
def __init__(self, canvas=None, data=None, toolbar=None, def __init__(self, data=None, display_current=True,
display_current=True): canvas=None, trad=None, toolbar=None,
parent=None):
super(Plot, self).__init__( super(Plot, self).__init__(
canvas=canvas, canvas = canvas,
data=data, trad = trad,
toolbar=toolbar data = data,
toolbar = toolbar,
parent = parent
) )
self._display_current = display_current 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.UndoCommand import *
from View.SedimentLayers.Reach.Profile.translate import * from View.SedimentLayers.Reach.Profile.translate import *
from View.Tools.PamhyrTable import PamhyrTableModel
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
@@ -67,28 +69,10 @@ class ComboBoxDelegate(QItemDelegate):
self.commitData.emit(self.sender()) self.commitData.emit(self.sender())
class TableModel(QAbstractTableModel): class TableModel(PamhyrTableModel):
def __init__(self, study=None, profile=None, undo=None): def _setup_lst(self):
super(QAbstractTableModel, self).__init__() self._lst = self._data
self._headers = list(table_headers.keys()) self._study = self._opt_data
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)
def data(self, index, role): def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole: if role != Qt.ItemDataRole.DisplayRole:
@@ -98,25 +82,19 @@ class TableModel(QAbstractTableModel):
column = index.column() column = index.column()
if self._headers[column] == "name": if self._headers[column] == "name":
return self._profile.point(row).name return self._data.point(row).name
elif self._headers[column] == "sl": elif self._headers[column] == "sl":
value = self._profile.point(row).sl value = self._data.point(row).sl
if value == None: if value == None:
text = _translate("SedimentLayers", "Not defined") text = _translate("SedimentLayers", "Not defined")
return text return text
return str(value) return str(value)
elif self._headers[column] == "x": elif self._headers[column] == "x":
return self._profile.point(row).x return self._data.point(row).x
elif self._headers[column] == "y": elif self._headers[column] == "y":
return self._profile.point(row).y return self._data.point(row).y
elif self._headers[column] == "z": elif self._headers[column] == "z":
return self._profile.point(row).z return self._data.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 QVariant() return QVariant()
@@ -139,7 +117,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
SetSLCommand( 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 tools import trace, timer
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -28,37 +27,42 @@ from View.SedimentLayers.Reach.Profile.UndoCommand import *
from View.SedimentLayers.Reach.Profile.Table import * from View.SedimentLayers.Reach.Profile.Table import *
from View.SedimentLayers.Reach.Profile.Plot import Plot from View.SedimentLayers.Reach.Profile.Plot import Plot
from View.Plot.MplCanvas import MplCanvas from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar 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 from View.SedimentLayers.Window import SedimentLayersWindow
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class ProfileSedimentLayersWindow(ASubMainWindow, ListedSubWindow): class ProfileSedimentLayersWindow(PamhyrWindow):
def __init__(self, title="Profile sediment layers", study=None, profile=None, parent=None): _pamhyr_ui = "ProfileSedimentLayers"
self._study = study _pamhyr_name = "Profile sediment layers"
self._sediment_layers = self._study.river.sediment_layers
self._profile = profile
self._reach = self._study.river.current_reach().reach
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__( 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_table()
self.setup_graph() self.setup_graph()
self.setup_connections() self.setup_connections()
self.ui.setWindowTitle(self._title) self.ui.setWindowTitle(self._title)
def setup_title(self, title): def compute_name(self, study):
rname = self._reach.name rname = self._reach.name
if rname == "": if rname == "":
rname = _translate("SedimentLayers", "(no name)") rname = _translate("SedimentLayers", "(no name)")
@@ -70,41 +74,32 @@ class ProfileSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
"(no name - @kp)").replace("@kp", str(self._profile.kp) "(no name - @kp)").replace("@kp", str(self._profile.kp)
) )
self._title = ( return (
title + " - " self._pamhyr_name + " - "
+ self._study.name + " - " + study.name + " - "
+ rname + " - " + pname + 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): def setup_table(self):
retranslate() table_headers = self._trad.get_dict("table_headers")
table = self.find(QTableView, f"tableView") self._delegate_sl = ComboBoxDelegate(
self._table = TableModel(
study = self._study,
profile = self._profile,
undo = self._undo_stack,
)
table.setModel(self._table)
self._delegate_stricklers = ComboBoxDelegate(
study = self._study, study = self._study,
parent=self parent=self
) )
table.setItemDelegateForColumn( table = self.find(QTableView, f"tableView")
list(table_headers).index("sl"), self._table = TableModel(
self._delegate_stricklers 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.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True) table.setAlternatingRowColors(True)
@@ -130,18 +125,9 @@ class ProfileSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
) )
self.plot.draw() self.plot.draw()
def setup_connections(self): def setup_connections(self):
self.undo_sc.activated.connect(self.undo) self._table.layoutChanged.connect(self._update_plot)
self.redo_sc.activated.connect(self.redo) self._table.dataChanged.connect(self._update_plot)
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)
def index_selected_rows(self): def index_selected_rows(self):
table = self.find(QTableView, f"tableView") table = self.find(QTableView, f"tableView")
@@ -155,14 +141,14 @@ class ProfileSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
) )
) )
def copy(self): def _copy(self):
logger.info("TODO: copy") logger.info("TODO: copy")
def paste(self): def _paste(self):
logger.info("TODO: paste") logger.info("TODO: paste")
def undo(self): def _undo(self):
self._table.undo() self._table.undo()
def redo(self): def _redo(self):
self._table.redo() self._table.redo()
@@ -2,19 +2,18 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from View.SedimentLayers.Reach.translate import SedimentReachTranslate
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
table_headers = { class SedimentProfileTranslate(SedimentReachTranslate):
"x": _translate("SedimentLayers", "X (m)"), def __init__(self):
"y": _translate("SedimentLayers", "Y (m)"), super(SedimentProfileTranslate, self).__init__()
"z": _translate("SedimentLayers", "Z (m)"),
"name": _translate("SedimentLayers", "Name"),
"sl": _translate("SedimentLayers", "Sediment layers"),
}
def retranslate(): self._sub_dict["table_headers"] = {
table_headers["x"] = _translate("SedimentLayers", "X (m)") "x": _translate("SedimentLayers", "X (m)"),
table_headers["y"] = _translate("SedimentLayers", "Y (m)") "y": _translate("SedimentLayers", "Y (m)"),
table_headers["z"] = _translate("SedimentLayers", "Z (m)") "z": _translate("SedimentLayers", "Z (m)"),
table_headers["name"] = _translate("SedimentLayers", "Name") "name": _translate("SedimentLayers", "Name"),
table_headers["sl"] = _translate("SedimentLayers", "Sediment layers") "sl": _translate("SedimentLayers", "Sediment layers"),
}
+9 -6
View File
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from View.ASubWindow import ASubWindow from View.Tools.PamhyrWindow import PamhyrDialog
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -20,12 +19,16 @@ from View.SedimentLayers.Reach.translate import *
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class SLDialog(ASubWindow, ListedSubWindow): class SLDialog(PamhyrDialog):
def __init__(self, title="SL", study=None, parent=None): _pamhyr_ui = "SLDialog"
self._study = study _pamhyr_name = "SL"
def __init__(self, study=None, config=None, parent=None):
super(SLDialog, self).__init__( super(SLDialog, self).__init__(
name=title, ui="SLDialog", parent=parent title = self._pamhyr_name,
study = study,
config = config,
parent=parent
) )
self.setup_combobox() 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.UndoCommand import *
from View.SedimentLayers.Reach.translate import *
from View.Tools.PamhyrTable import PamhyrTableModel
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class ComboBoxDelegate(QItemDelegate): class ComboBoxDelegate(QItemDelegate):
def __init__(self, study=None, parent=None): def __init__(self, study=None, trad=None, parent=None):
super(ComboBoxDelegate, self).__init__(parent) super(ComboBoxDelegate, self).__init__(parent)
self._study = study self._study = study
self._trad = trad
def createEditor(self, parent, option, index): def createEditor(self, parent, option, index):
self.editor = QComboBox(parent) self.editor = QComboBox(parent)
self.editor.addItems( self.editor.addItems(
[_translate("SedimentLayers", "Not defined")] + [self._trad["nd"]] +
list( list(
map( map(
lambda sl: str(sl), lambda sl: str(sl),
@@ -67,28 +69,10 @@ class ComboBoxDelegate(QItemDelegate):
self.commitData.emit(self.sender()) self.commitData.emit(self.sender())
class TableModel(QAbstractTableModel): class TableModel(PamhyrTableModel):
def __init__(self, study=None, reach=None, undo=None): def _setup_lst(self):
super(QAbstractTableModel, self).__init__() self._lst = self._data
self._headers = list(table_headers.keys()) self._study = self._opt_data
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)
def data(self, index, role): def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole: if role != Qt.ItemDataRole.DisplayRole:
@@ -98,11 +82,11 @@ class TableModel(QAbstractTableModel):
column = index.column() column = index.column()
if self._headers[column] == "name": if self._headers[column] == "name":
return self._reach.profile(row).name return self._data.profile(row).name
if self._headers[column] == "kp": if self._headers[column] == "kp":
return self._reach.profile(row).kp return self._data.profile(row).kp
if self._headers[column] == "sl": if self._headers[column] == "sl":
value = self._reach.profile(row).sl value = self._data.profile(row).sl
if value == None: if value == None:
text = _translate("SedimentLayers", "Not defined") text = _translate("SedimentLayers", "Not defined")
return text return text
@@ -110,12 +94,6 @@ class TableModel(QAbstractTableModel):
return QVariant() 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): def setData(self, index, value, role=Qt.EditRole):
if not index.isValid() or role != Qt.EditRole: if not index.isValid() or role != Qt.EditRole:
return False return False
@@ -135,7 +113,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
SetSLCommand( SetSLCommand(
self._reach, row, new self._data, row, new
) )
) )
@@ -145,7 +123,7 @@ class TableModel(QAbstractTableModel):
def apply_sl_each_profile(self, sl): def apply_sl_each_profile(self, sl):
self._undo.push( self._undo.push(
ApplySLCommand( ApplySLCommand(
self._reach, sl self._data, sl
) )
) )
self.layoutChanged.emit() self.layoutChanged.emit()
+42 -53
View File
@@ -4,8 +4,7 @@ import logging
from tools import trace, timer from tools import trace, timer
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -29,10 +28,10 @@ from View.SedimentLayers.Reach.Table import *
from View.SedimentLayers.Reach.Plot import Plot from View.SedimentLayers.Reach.Plot import Plot
from View.SedimentLayers.Reach.SLDialog import SLDialog from View.SedimentLayers.Reach.SLDialog import SLDialog
from View.Plot.MplCanvas import MplCanvas from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Plot.PamhyrToolbar import PamhyrPlotToolbar 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.Window import SedimentLayersWindow
from View.SedimentLayers.Reach.Profile.Window import ProfileSedimentLayersWindow from View.SedimentLayers.Reach.Profile.Window import ProfileSedimentLayersWindow
@@ -40,64 +39,58 @@ _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class ReachSedimentLayersWindow(ASubMainWindow, ListedSubWindow): class ReachSedimentLayersWindow(PamhyrWindow):
def __init__(self, title="Reach sediment layers", study=None, parent=None): _pamhyr_ui = "ReachSedimentLayers"
self._study = study _pamhyr_name = "Reach sediment layers"
self._sediment_layers = self._study.river.sediment_layers
self._reach = self._study.river.current_reach().reach
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__( 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_table()
self.setup_graph() self.setup_plot()
self.setup_connections() 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): def setup_table(self):
retranslate() table_headers = self._trad.get_dict("table_headers")
table = self.find(QTableView, f"tableView") self._delegate_sl = ComboBoxDelegate(
self._table = TableModel(
study = self._study,
reach = self._reach,
undo = self._undo_stack,
)
table.setModel(self._table)
self._delegate_stricklers = ComboBoxDelegate(
study = self._study, study = self._study,
trad = self._trad,
parent=self parent=self
) )
table.setItemDelegateForColumn( table = self.find(QTableView, f"tableView")
list(table_headers).index("sl"), self._table = TableModel(
self._delegate_stricklers 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.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True) table.setAlternatingRowColors(True)
def setup_graph(self): def setup_plot(self):
self.canvas = MplCanvas(width=5, height=4, dpi=100) self.canvas = MplCanvas(width=5, height=4, dpi=100)
self.canvas.setObjectName("canvas") self.canvas.setObjectName("canvas")
self.toolbar = PamhyrPlotToolbar( self.toolbar = PamhyrPlotToolbar(
@@ -114,6 +107,7 @@ class ReachSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
canvas = self.canvas, canvas = self.canvas,
data = self._reach, data = self._reach,
toolbar = self.toolbar, toolbar = self.toolbar,
trad = self._trad,
display_current = False display_current = False
) )
self.plot.draw() self.plot.draw()
@@ -129,11 +123,6 @@ class ReachSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
.clicked\ .clicked\
.connect(self.apply_sl_each_profile) .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\ self._table.layoutChanged\
.connect(self._update_plot) .connect(self._update_plot)
self._table.dataChanged\ self._table.dataChanged\
@@ -152,17 +141,17 @@ class ReachSedimentLayersWindow(ASubMainWindow, ListedSubWindow):
) )
) )
def copy(self): def _copy(self):
logger.info("TODO: copy") logger.info("TODO: copy")
def paste(self): def _paste(self):
logger.info("TODO: paste") logger.info("TODO: paste")
def undo(self): def _undo(self):
self._table.undo() self._table.undo()
self._update_plot() self._update_plot()
def redo(self): def _redo(self):
self._table.redo() self._table.redo()
self._update_plot() self._update_plot()
+14 -9
View File
@@ -2,15 +2,20 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from View.SedimentLayers.translate import SedimentTranslate
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
table_headers = { class SedimentReachTranslate(SedimentTranslate):
"name": _translate("SedimentLayers", "Name"), def __init__(self):
"kp": _translate("SedimentLayers", "KP (m)"), super(SedimentReachTranslate, self).__init__()
"sl": _translate("SedimentLayers", "Sediment layers"),
}
def retranslate(): self._dict["nd"] = _translate("SedimentLayers", "Not defined")
table_headers["name"] = _translate("SedimentLayers", "Name") self._dict["kp"] = _translate("SedimentLayers", "Kp (m)")
table_headers["kp"] = _translate("SedimentLayers", "KP (m)") self._dict["height"] = _translate("SedimentLayers", "Height (m)")
table_headers["sl"] = _translate("SedimentLayers", "Sediment layers")
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, QComboBox,
) )
from View.Tools.PamhyrTable import PamhyrTableModel
from View.SedimentLayers.UndoCommand import * from View.SedimentLayers.UndoCommand import *
from View.SedimentLayers.translate import *
_translate = QCoreApplication.translate
class TableModel(QAbstractTableModel): class TableModel(PamhyrTableModel):
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)
def data(self, index, role): def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole: if role != Qt.ItemDataRole.DisplayRole:
return QVariant() return QVariant()
@@ -49,15 +29,9 @@ class TableModel(QAbstractTableModel):
column = index.column() column = index.column()
if self._headers[column] == "name": if self._headers[column] == "name":
return self._sl.get(row).name return self._data.get(row).name
elif self._headers[column] == "comment": elif self._headers[column] == "comment":
return self._sl.get(row).comment return self._data.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 QVariant() return QVariant()
@@ -71,13 +45,13 @@ class TableModel(QAbstractTableModel):
if self._headers[column] == "name": if self._headers[column] == "name":
self._undo.push( self._undo.push(
SetNameCommand( SetNameCommand(
self._sl, row, value self._data, row, value
) )
) )
if self._headers[column] == "comment": if self._headers[column] == "comment":
self._undo.push( self._undo.push(
SetCommentCommand( SetCommentCommand(
self._sl, row, value self._data, row, value
) )
) )
@@ -89,7 +63,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
AddCommand( AddCommand(
self._sl, row self._data, row
) )
) )
@@ -101,7 +75,7 @@ class TableModel(QAbstractTableModel):
self._undo.push( self._undo.push(
DelCommand( DelCommand(
self._sl, rows self._data, rows
) )
) )
@@ -118,7 +92,7 @@ class TableModel(QAbstractTableModel):
self._undo_stack.push( self._undo_stack.push(
MoveCommand( MoveCommand(
self._sl, "up", row self._data, "up", row
) )
) )
@@ -126,7 +100,7 @@ class TableModel(QAbstractTableModel):
self.layoutChanged.emit() self.layoutChanged.emit()
def move_down(self, index, parent=QModelIndex()): def move_down(self, index, parent=QModelIndex()):
if row > len(self._sl): if row > len(self._data):
return return
target = row target = row
@@ -135,7 +109,7 @@ class TableModel(QAbstractTableModel):
self._undo_stack.push( self._undo_stack.push(
MoveCommand( 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 -*- # -*- coding: utf-8 -*-
import logging import logging
from tools import trace, timer from tools import trace, timer
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -29,62 +44,53 @@ from View.SedimentLayers.Table import *
from View.SedimentLayers.Edit.Plot import Plot from View.SedimentLayers.Edit.Plot import Plot
from View.Plot.MplCanvas import MplCanvas from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.SedimentLayers.translate import table_headers, retranslate from View.SedimentLayers.translate import SedimentTranslate
from View.SedimentLayers.Edit.Window import EditSedimentLayersWindow from View.SedimentLayers.Edit.Window import EditSedimentLayersWindow
_translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class SedimentLayersWindow(ASubMainWindow, ListedSubWindow): class SedimentLayersWindow(PamhyrWindow):
def __init__(self, title="SedimentLayersList", study=None, parent=None): _pamhyr_ui = "SedimentLayersList"
self._study = study _pamhyr_name = "Sediment Layers List"
self._sediment_layers = self._study.river.sediment_layers
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__( 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_table()
self.setup_graph() self.setup_plot()
self.setup_connections() 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): def setup_table(self):
retranslate()
table = self.find(QTableView, f"tableView") table = self.find(QTableView, f"tableView")
self._table = TableModel( 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, undo = self._undo_stack,
) )
table.setModel(self._table) table.setModel(self._table)
table.setSelectionBehavior(QAbstractItemView.SelectRows) table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True) table.setAlternatingRowColors(True)
def setup_graph(self): def setup_plot(self):
self.canvas = MplCanvas(width=5, height=4, dpi=100) self.canvas = MplCanvas(width=2, height=4, dpi=100)
self.canvas.setObjectName("canvas") self.canvas.setObjectName("canvas")
self.plot_layout = self.find(QVBoxLayout, "verticalLayout") self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
self.plot_layout.addWidget(self.canvas) 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_del").triggered.connect(self.delete)
self.find(QAction, "action_edit").triggered.connect(self.edit_sediment_layers) 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 = self.find(QTableView, f"tableView")
table.selectionModel()\ table.selectionModel()\
.selectionChanged\ .selectionChanged\
@@ -116,6 +117,7 @@ class SedimentLayersWindow(ASubMainWindow, ListedSubWindow):
self.plot = Plot( self.plot = Plot(
canvas = self.canvas, canvas = self.canvas,
data = self._sediment_layers.get(rows[0]), data = self._sediment_layers.get(rows[0]),
trad = self._trad,
toolbar = None, toolbar = None,
display_current = False display_current = False
) )
@@ -148,16 +150,16 @@ class SedimentLayersWindow(ASubMainWindow, ListedSubWindow):
self._table.delete(rows) self._table.delete(rows)
def copy(self): def _copy(self):
logger.info("TODO: copy") logger.info("TODO: copy")
def paste(self): def _paste(self):
logger.info("TODO: paste") logger.info("TODO: paste")
def undo(self): def _undo(self):
self._table.undo() self._table.undo()
def redo(self): def _redo(self):
self._table.redo() self._table.redo()
def edit_sediment_layers(self): def edit_sediment_layers(self):
+9 -7
View File
@@ -2,13 +2,15 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
table_headers = { class SedimentTranslate(PamhyrTranslate):
"name": _translate("SedimentLayers", "Name"), def __init__(self):
"comment": _translate("SedimentLayers", "Comment"), super(SedimentTranslate, self).__init__()
}
def retranslate(): self._sub_dict["table_headers"] = {
table_headers["name"] = _translate("SedimentLayers", "Name") "name": _translate("SedimentLayers", "Name"),
table_headers["comment"] = _translate("SedimentLayers", "Comment") "comment": _translate("SedimentLayers", "Comment"),
}
+23 -46
View File
@@ -34,37 +34,20 @@ from PyQt5.QtWidgets import (
QComboBox, QComboBox,
) )
from View.Tools.PamhyrTable import PamhyrTableModel
from View.SolverParameters.UndoCommand import * from View.SolverParameters.UndoCommand import *
from View.SolverParameters import translate as tr
from Solver.Solvers import solver_long_name, solver_type_list from Solver.Solvers import solver_long_name, solver_type_list
logger = logging.getLogger()
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class TableModel(QAbstractTableModel): class TableModel(PamhyrTableModel):
def __init__(self, data=None, undo=None, tab=""): def _setup_lst(self):
super(QAbstractTableModel, self).__init__() self._tab = self._opt_data
self._headers = list(tr.table_headers.keys()) self._lst = self._data.get_params(self._tab)
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)
def data(self, index, role): def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole: if role != Qt.ItemDataRole.DisplayRole:
@@ -75,24 +58,18 @@ class TableModel(QAbstractTableModel):
cname = self._headers[column] cname = self._headers[column]
if cname == "name": if cname == "name":
value = self._params.get(row)[cname] value = self._lst.get(row)[cname]
if value in tr.names: if value in self._trad.get_dict("names"):
value = tr.names[value] value = self._trad.get_dict("names")[value]
return value return value
elif cname == "value": elif cname == "value":
value = self._params.get(row)[cname] value = self._lst.get(row)[cname]
if value in tr.yes_no: if value in self._trad.get_dict("yes_no"):
value = tr.yes_no[value] value = self._trad.get_dict("yes_no")[value]
return value return value
return QVariant() 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): def setData(self, index, value, role=Qt.EditRole):
if not index.isValid() or role != Qt.EditRole: if not index.isValid() or role != Qt.EditRole:
return False return False
@@ -102,12 +79,12 @@ class TableModel(QAbstractTableModel):
try: try:
if self._headers[column] == "value": if self._headers[column] == "value":
if value in tr.r_yes_no: if value in self._trad.get_dict("r_yes_no"):
value = tr.r_yes_no[value].lower() value = self._trad.get_dict("r_yes_no")[value].lower()
self._undo.push( self._undo.push(
SetCommand( SetCommand(
self._params, row, self._lst, row,
"value", value "value", value
) )
) )
@@ -123,7 +100,7 @@ class TableModel(QAbstractTableModel):
# self._undo.push( # self._undo.push(
# AddCommand( # AddCommand(
# self._params, row # self._lst, row
# ) # )
# ) # )
@@ -135,7 +112,7 @@ class TableModel(QAbstractTableModel):
# self._undo.push( # self._undo.push(
# DelCommand( # DelCommand(
# self._params, rows # self._lst, rows
# ) # )
# ) # )
@@ -147,7 +124,7 @@ class TableModel(QAbstractTableModel):
# self._undo.push( # self._undo.push(
# SortCommand( # SortCommand(
# self._params, False # self._lst, False
# ) # )
# ) # )
@@ -164,7 +141,7 @@ class TableModel(QAbstractTableModel):
# self._undo_stack.push( # self._undo_stack.push(
# MoveCommand( # MoveCommand(
# self._params, "up", row # self._lst, "up", row
# ) # )
# ) # )
@@ -172,7 +149,7 @@ class TableModel(QAbstractTableModel):
# self.layoutChanged.emit() # self.layoutChanged.emit()
# def move_down(self, index, parent=QModelIndex()): # def move_down(self, index, parent=QModelIndex()):
# if row > len(self._params): # if row > len(self._lst):
# return # return
# target = row # target = row
@@ -181,7 +158,7 @@ class TableModel(QAbstractTableModel):
# self._undo_stack.push( # self._undo_stack.push(
# MoveCommand( # 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 tools import trace, timer
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -43,7 +42,7 @@ from PyQt5.QtWidgets import (
from View.SolverParameters.UndoCommand import * from View.SolverParameters.UndoCommand import *
from View.SolverParameters.Table import TableModel 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 from Solver.Solvers import solver_long_name, solver_type_list
@@ -51,25 +50,25 @@ _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class SolverParametersWindow(ASubMainWindow, ListedSubWindow): class SolverParametersWindow(PamhyrWindow):
def __init__(self, title="Solver parameters", study=None, parent=None): _pamhyr_ui = "SolverParameters"
# Init tanslate dictionary _pamhyr_name = "Solver parameters"
tr.init()
self._title = title + " - " + study.name
def __init__(self, study=None, config=None, parent=None):
name = self._pamhyr_name + " - " + study.name
super(SolverParametersWindow, self).__init__( 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._params = self._study.river.parameters
self.setup_sc() self.setup_sc()
self.setup_table() self.setup_table()
self.setup_connections()
self.ui.setWindowTitle(self._title)
def setup_sc(self): def setup_sc(self):
self._undo_stack = {} self._undo_stack = {}
@@ -77,10 +76,10 @@ class SolverParametersWindow(ASubMainWindow, ListedSubWindow):
for st in solver_type_list: for st in solver_type_list:
self._undo_stack[st] = QUndoStack() self._undo_stack[st] = QUndoStack()
self.undo_sc = QShortcut(QKeySequence.Undo, self) self._undo_sc = QShortcut(QKeySequence.Undo, self)
self.redo_sc = QShortcut(QKeySequence.Redo, self) self._redo_sc = QShortcut(QKeySequence.Redo, self)
self.copy_sc = QShortcut(QKeySequence.Copy, self) self._undo_sc.activated.connect(self._undo)
self.paste_sc = QShortcut(QKeySequence.Paste, self) self._redo_sc.activated.connect(self._redo)
def setup_table(self): def setup_table(self):
self._table = {} self._table = {}
@@ -97,9 +96,13 @@ class SolverParametersWindow(ASubMainWindow, ListedSubWindow):
# Create table model # Create table model
self._table[st] = TableModel( self._table[st] = TableModel(
table_view = table,
data = self._study.river, 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], undo = self._undo_stack[st],
tab = st,
) )
table.setModel(self._table[st]) table.setModel(self._table[st])
@@ -115,31 +118,24 @@ class SolverParametersWindow(ASubMainWindow, ListedSubWindow):
# Create tab # Create tab
self._tab_widget.addTab(widget, f"{solver_long_name[st]}") 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): def current_tab(self):
return self.find(QTabWidget, "tabWidget")\ return self.find(QTabWidget, "tabWidget")\
.currentWidget()\ .currentWidget()\
.objectName()\ .objectName()\
.replace("tab_", "") .replace("tab_", "")
def undo(self): def _undo(self):
tab = self.current_tab() tab = self.current_tab()
self._table[tab].undo() self._table[tab].undo()
self._set_current_reach() self._set_current_reach()
def redo(self): def _redo(self):
tab = self.current_tab() tab = self.current_tab()
self._table[tab].redo() self._table[tab].redo()
self._set_current_reach() self._set_current_reach()
def copy(self): def _copy(self):
logger.info("TODO: copy") logger.info("TODO: copy")
def paste(self): def _paste(self):
logger.info("TODO: paste") logger.info("TODO: paste")
+51 -57
View File
@@ -18,66 +18,60 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
table_headers = None class ParamTranslate(PamhyrTranslate):
yes_no = None def __init__(self):
r_yes_no = None super(ParamTranslate, self).__init__()
names = None
def init(): self._sub_dict["table_headers"] = {
global table_headers "name": _translate("SolverParameters", "Name"),
table_headers = { "value": _translate("SolverParameters", "Value")
"name": _translate("SolverParameters", "Name"), }
"value": _translate("SolverParameters", "Value")
}
# Used to translate user parameter with value yes or no self._sub_dict["yes_no"] = {
global yes_no "yes": _translate("SolverParameters", "Yes"),
yes_no = { "no": _translate("SolverParameters", "No"),
"yes": _translate("SolverParameters", "Yes"), "y": _translate("SolverParameters", "Y"),
"no": _translate("SolverParameters", "No"), "n": _translate("SolverParameters", "N"),
"y": _translate("SolverParameters", "Y"), }
"n": _translate("SolverParameters", "N"),
}
# Reverse self._sub_dict["r_yes_no"] = {
global r_yes_no _translate("SolverParameters", "Yes"): "yes",
r_yes_no = { _translate("SolverParameters", "No"): "no",
_translate("SolverParameters", "Yes"): "yes", _translate("SolverParameters", "Y"): "y",
_translate("SolverParameters", "No"): "no", _translate("SolverParameters", "N"): "n",
_translate("SolverParameters", "Y"): "y", }
_translate("SolverParameters", "N"): "n",
}
global names self._sub_dict["names"] = {
names = { "all_init_time": _translate("SolverParameters", "Initial time (jj:hh:mm:ss)"),
"all_init_time": _translate("SolverParameters", "Initial time (jj:hh:mm:ss)"), "all_final_time": _translate("SolverParameters", "Final time (jj:hh:mm:ss)"),
"all_final_time": _translate("SolverParameters", "Final time (jj:hh:mm:ss)"), "all_timestep": _translate("SolverParameters", "Timestep (second)"),
"all_timestep": _translate("SolverParameters", "Timestep (second)"), "all_command_line_arguments": _translate("SolverParameters", "Command line arguments"),
"all_command_line_arguments": _translate("SolverParameters", "Command line arguments"), # Mage specific parameters
# Mage specific parameters "mage_min_timestep": _translate("SolverParameters", "Minimum timestep (second)"),
"mage_min_timestep": _translate("SolverParameters", "Minimum timestep (second)"), "mage_timestep_tra": _translate("SolverParameters", "Time step of writing on .TRA"),
"mage_timestep_tra": _translate("SolverParameters", "Time step of writing on .TRA"), "mage_timestep_bin": _translate("SolverParameters", "Time step of writing on .BIN"),
"mage_timestep_bin": _translate("SolverParameters", "Time step of writing on .BIN"), "mage_implicitation": _translate("SolverParameters", "Implicitation parameter"),
"mage_implicitation": _translate("SolverParameters", "Implicitation parameter"), "mage_continuity_discretization": _translate("SolverParameters", "Continuity discretization type (S/L)"),
"mage_continuity_discretization": _translate("SolverParameters", "Continuity discretization type (S/L)"), "mage_qsj_discretization": _translate("SolverParameters", "QSJ discretization (A/B)"),
"mage_qsj_discretization": _translate("SolverParameters", "QSJ discretization (A/B)"), "mage_stop_criterion_iterations": _translate("SolverParameters", "Stop criterion iterations (G/A/R)"),
"mage_stop_criterion_iterations": _translate("SolverParameters", "Stop criterion iterations (G/A/R)"), "mage_iteration_type": _translate("SolverParameters", "Iteration type"),
"mage_iteration_type": _translate("SolverParameters", "Iteration type"), "mage_smooth_coef": _translate("SolverParameters", "Smoothing coefficient"),
"mage_smooth_coef": _translate("SolverParameters", "Smoothing coefficient"), "mage_cfl_max": _translate("SolverParameters", "Maximun accepted number of CFL"),
"mage_cfl_max": _translate("SolverParameters", "Maximun accepted number of CFL"), "mage_min_height": _translate("SolverParameters", "Minimum water height (meter)"),
"mage_min_height": _translate("SolverParameters", "Minimum water height (meter)"), "mage_max_niter": _translate("SolverParameters", "Maximun number of iterations (< 100)"),
"mage_max_niter": _translate("SolverParameters", "Maximun number of iterations (< 100)"), "mage_timestep_reduction_factor": _translate("SolverParameters", "Timestep reduction factor"),
"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_Z": _translate("SolverParameters", "Reduction precision factor of Z"), "mage_precision_reduction_factor_Q": _translate("SolverParameters", "Reduction precision factor of Q"),
"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_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_max_precision": _translate("SolverParameters", "Number of iteration at maximum precision"), "mage_niter_before_switch": _translate("SolverParameters", "Number of iteration before switch"),
"mage_niter_before_switch": _translate("SolverParameters", "Number of iteration before switch"), "mage_max_froude": _translate("SolverParameters", "Maximum accepted Froude number"),
"mage_max_froude": _translate("SolverParameters", "Maximum accepted Froude number"), "mage_diffluence_node_height_balance": _translate("SolverParameters", "Diffluence node height balance"),
"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_compute_reach_volume_balance": _translate("SolverParameters", "Compute reach volume balance (Y/N)"), "mage_max_reach_volume_balance": _translate("SolverParameters", "Maximum reach volume balance"),
"mage_max_reach_volume_balance": _translate("SolverParameters", "Maximum reach volume balance"), "mage_min_reach_volume_to_check": _translate("SolverParameters", "Minimum reach volume to check"),
"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 tools import trace, timer
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.ListedSubWindow import ListedSubWindow
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence,
@@ -44,40 +43,31 @@ from Model.Stricklers.Stricklers import Stricklers
from View.Stricklers.UndoCommand import PasteCommand from View.Stricklers.UndoCommand import PasteCommand
from View.Stricklers.Table import TableModel from View.Stricklers.Table import TableModel
from View.Stricklers.translate import table_headers, retranslate from View.Stricklers.translate import StricklersTranslate
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class StricklersWindow(ASubMainWindow, ListedSubWindow): class StricklersWindow(PamhyrWindow):
def __init__(self, title="Stricklers", study=None, config=None, parent=None): _pamhyr_ui = "Stricklers"
self._title = title + " - " + study.name _pamhyr_name = "Stricklers"
def __init__(self, study=None, config=None, parent=None):
name = self._pamhyr_name + " - " + study.name
super(StricklersWindow, self).__init__( 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_table()
self.setup_connections() 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): def setup_table(self):
retranslate()
self._table = {} self._table = {}
for t in ["app", "study"]: for t in ["app", "study"]:
@@ -89,7 +79,7 @@ class StricklersWindow(ASubMainWindow, ListedSubWindow):
self._table[t] = TableModel( self._table[t] = TableModel(
table_view = table, table_view = table,
table_headers = table_headers, table_headers = self._trad.get_dict("table_headers"),
editable_headers = ["name", "comment", "minor", "medium"], editable_headers = ["name", "comment", "minor", "medium"],
data = data, data = data,
undo = self._undo_stack, 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_del").triggered.connect(self.delete)
self.find(QAction, "action_sort").triggered.connect(self.sort) 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): def index_selected_rows(self):
table = self.find(QTableView, f"tableView_study") table = self.find(QTableView, f"tableView_study")
return list( return list(
@@ -139,14 +124,14 @@ class StricklersWindow(ASubMainWindow, ListedSubWindow):
def sort(self): def sort(self):
self._table['study'].sort(False) self._table['study'].sort(False)
def copy(self): def _copy(self):
logger.info("TODO: copy") logger.info("TODO: copy")
def paste(self): def _paste(self):
logger.info("TODO: paste") logger.info("TODO: paste")
def undo(self): def _undo(self):
self._table['study'].undo() self._table['study'].undo()
def redo(self): def _redo(self):
self._table['study'].redo() self._table['study'].redo()
+11 -14
View File
@@ -18,21 +18,18 @@
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from Model.LateralContribution.LateralContributionTypes import ( from View.Tools.PamhyrTranslate import PamhyrTranslate
NotDefined, LateralContrib, Rain, Evaporation,
)
_translate = QCoreApplication.translate _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(): class StricklersTranslate(PamhyrTranslate):
table_headers["name"] = _translate("LateralContribution", "Name") def __init__(self):
table_headers["minor"] = _translate("LateralContribution", "Minor bed") super(StricklersTranslate, self).__init__()
table_headers["medium"] = _translate("LateralContribution", "Medium bed")
table_headers["comment"] = _translate("LateralContribution", "Comment") 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 -*- # -*- coding: utf-8 -*-
from Model.Study import Study from Model.Study import Study
from View.ASubWindow import ASubWindow from View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
@@ -27,27 +27,37 @@ from PyQt5.QtWidgets import (
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class NewStudyWindow(ASubWindow): class NewStudyWindow(PamhyrDialog):
def __init__(self, study=None, title="New Study", parent=None): _pamhyr_ui = "NewStudy"
super(NewStudyWindow, self).__init__(name=title, ui="NewStudy", parent=parent) _pamhyr_name = "Edit/New Study"
self.ui.setWindowTitle(title)
self.parent = parent def __init__(self, study=None, config = None, parent=None):
self.study = study if study is not None:
name = f"Edit study - {study.name}"
else:
name = "New study"
if not self.study is None: super(NewStudyWindow, self).__init__(
self.set_line_edit_text("lineEdit_name", self.study.name) title = name,
self.set_text_edit_text("textEdit_description", self.study.description) study = study,
self.set_datetime_edit("dateTimeEdit_date", self.study.date) 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.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.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.set_radio_button("radioButton_date", True)
self.find(QLabel, "label_date").setEnabled(True) self.find(QLabel, "label_date").setEnabled(True)
self.find(QDateTimeEdit, "dateTimeEdit_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") name = self.get_line_edit_text("lineEdit_name")
description = self.get_text_edit_text("textEdit_description") description = self.get_text_edit_text("textEdit_description")
if self.study is None: if self._study is None:
study = Study.new(name, description) study = Study.new(name, description)
if self.get_radio_button("radioButton_date"): if self.get_radio_button("radioButton_date"):
date = self.get_datetime_edit("dateTimeEdit_date") date = self.get_datetime_edit("dateTimeEdit_date")
study.use_date(date) study.use_date(date)
self.parent.set_model(study) self.parent.set_model(study)
else: else:
self.study.name = name self._study.name = name
self.study.description = description self._study.description = description
if self.get_radio_button("radioButton_date"): if self.get_radio_button("radioButton_date"):
date = self.get_datetime_edit("dateTimeEdit_date") date = self.get_datetime_edit("dateTimeEdit_date")
self.study.use_date(date) self._study.use_date(date)
else: else:
self.study.use_time() self._study.use_time()
self.done(True) self.done(True)
@@ -463,11 +463,16 @@ class ASubWindowFeatures(object):
# Top level interface # Top level interface
class ASubMainWindow(QMainWindow, ASubWindowFeatures, WindowToolKit): 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) super(ASubMainWindow, self).__init__(parent=parent)
if ui is not None: if ui is not None:
self.ui = loadUi( 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
) )
@@ -496,10 +501,15 @@ class ASubMainWindow(QMainWindow, ASubWindowFeatures, WindowToolKit):
return self.ui.findChild(qtype, name) return self.ui.findChild(qtype, name)
class ASubWindow(QDialog, ASubWindowFeatures, WindowToolKit): 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) super(ASubWindow, self).__init__(parent=parent)
self.ui = loadUi( 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
) )
self.name = name self.name = name
@@ -530,7 +540,12 @@ class AWidget(QWidget, ASubWindowFeatures):
def __init__(self, ui="", parent=None): def __init__(self, ui="", parent=None):
super(AWidget, self).__init__(parent=parent) super(AWidget, self).__init__(parent=parent)
self.ui = loadUi( 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
) )
self.parent = parent self.parent = parent
Loaded 100 of 117 files, more files were not shown because too many files have changed in this diff. Show more