Compare commits

...
64 Commits
Author SHA1 Message Date
Pierre-Antoine Rouby a603c3a63f git: Update gitignore. 2023-10-10 09:51:57 +02:00
Pierre-Antoine Rouby d0ea629c10 pamhyr: Fix execution without argument. 2023-10-10 09:36:45 +02:00
Pierre-Antoine Rouby b35be16268 ci: Fix windows exe generator script. 2023-10-10 09:30:40 +02:00
Pierre-Antoine Rouby 7644927de9 pamhyr: Allow Pamhyr2 script run on tty mode. 2023-10-09 17:03:23 +02:00
Pierre-Antoine Rouby 242b1a4e50 pamhyr: Put debug info as logger debug handler. 2023-10-09 16:55:54 +02:00
Pierre-Antoine Rouby 397b5b0cab debug: Display qt5 path in terminal. 2023-10-09 16:22:16 +02:00
Pierre-Antoine Rouby 8da1cb622f ci: Install and update pip packages. 2023-10-09 15:22:28 +02:00
Pierre-Antoine Rouby 7365bf70b6 doc: Add mage documentation open action. 2023-10-09 14:51:19 +02:00
Pierre-Antoine Rouby 2825d02cb2 doc: Fix path for build version. 2023-10-09 14:29:40 +02:00
Pierre-Antoine Rouby 24cb32c96c ci: Fix linux ci. 2023-10-09 13:44:15 +02:00
Pierre-Antoine Rouby 820adf2bb7 ci: Fix linux ci. 2023-10-09 12:08:58 +02:00
Pierre-Antoine Rouby 4211855732 ci: Update ci build instruction. 2023-10-09 12:05:29 +02:00
Pierre-Antoine Rouby 44b057c522 Merge branch 'doc-dev' with refactoring and user/dev documentation. 2023-10-09 11:17:13 +02:00
Pierre-Antoine Rouby f4d580a000 doc: Doc in format html or pdf, back/forward button and firefox button. 2023-10-09 11:11:23 +02:00
Pierre-Antoine Rouby a77c342e69 doc: Fix window display for version PyQt5 > 5.5 2023-10-06 16:21:23 +02:00
Pierre-Antoine Rouby 559d7dc006 doc: Keep doc html and add doc window in Pamhyr2. 2023-10-06 15:54:27 +02:00
Pierre-Antoine Rouby 1a47bbe19d Results: Allow to open last results from mainwindow. 2023-10-06 14:54:17 +02:00
Pierre-Antoine Rouby b1c658d711 refactoring: Delete deprecated unused files. 2023-10-06 14:34:15 +02:00
Pierre-Antoine Rouby 2ff4f63d23 refactoring: refactor Results. 2023-10-06 14:25:44 +02:00
Pierre-Antoine Rouby ba087f12a5 refactoring: Apply table refacto on checklist. 2023-10-06 10:40:18 +02:00
Pierre-Antoine Rouby a64a9867ef refactoring: refacto solver parameters 2023-10-04 17:01:31 +02:00
Pierre-Antoine Rouby 63d6c114c0 refactoring: refacto SL reach and profile window. 2023-10-04 16:23:06 +02:00
Pierre-Antoine Rouby 1d45ccb8b8 refactoring: refacto SL list & edit. 2023-10-04 15:19:27 +02:00
Pierre-Antoine Rouby 4ce597a2a0 refactoring: refacto frictions & stricklers. 2023-10-04 14:34:07 +02:00
Pierre-Antoine Rouby b430cbb62b refactoring: refacto IC. 2023-10-04 13:51:01 +02:00
Pierre-Antoine Rouby 500885ec4d refactoring: refacto LC. 2023-10-04 11:26:43 +02:00
Pierre-Antoine Rouby ea3654f1f8 refactoring: refacto BC. 2023-10-04 10:35:54 +02:00
Pierre-Antoine Rouby 7a5b4779e9 refactoring: Minor fix in geometry. 2023-10-03 17:11:06 +02:00
Pierre-Antoine Rouby c744797c6f refactoring: Minor fix in geometry. 2023-10-03 16:39:31 +02:00
Pierre-Antoine Rouby 11a7486a9c Refactoring: Use ui file in Geometry profile edit window. 2023-10-03 16:26:50 +02:00
Pierre-Antoine Rouby 44ccf99d48 Refactoring: Use ui file for geometry reach window. 2023-10-03 15:10:46 +02:00
Pierre-Antoine Rouby ef672798ef refactoring: Start refactoring plot. 2023-09-29 11:17:08 +02:00
Pierre-Antoine Rouby 245a5057c3 refactoring: Update BC. 2023-09-29 10:14:40 +02:00
Pierre-Antoine Rouby e06610756a model: geometry: Fix 'sl' setter. 2023-09-29 08:33:23 +02:00
Pierre-Antoine Rouby dbc256be1a ui, doc: Update Pamhyr2 debug repl. 2023-09-27 16:49:00 +02:00
Pierre-Antoine Rouby e589fcdd3d doc: dev: Complete dev documentation. 2023-09-27 16:42:42 +02:00
Pierre-Antoine Rouby d20cdfc47f doc: dev: Complete Architecture section. 2023-09-27 15:55:45 +02:00
Pierre-Antoine Rouby ab2e307e3d doc: dev: Update graphs. 2023-09-27 12:10:47 +02:00
Pierre-Antoine Rouby a81564e582 doc: dev: Write Plot section. 2023-09-27 09:20:17 +02:00
Pierre-Antoine Rouby f93f3fe122 doc: dev: Update Table and UndoCommand. 2023-09-27 09:00:18 +02:00
Pierre-Antoine Rouby 2e94348bb8 refactoring: Add PamhyrTranslate class for GUI translation and document it. 2023-09-26 17:16:53 +02:00
Pierre-Antoine Rouby e7fd2077bd doc: dev: Update with PamhyrWindow, and minor change in hash computation. 2023-09-26 14:19:22 +02:00
Pierre-Antoine Rouby 624e9b6f71 refactoring: Apply PamhyrWindow on Debug window. 2023-09-26 12:07:10 +02:00
Pierre-Antoine Rouby ca10f19fe5 refactoring: Continue apply PamhyrWindow. 2023-09-26 12:03:41 +02:00
Pierre-Antoine Rouby 1a36d78ee2 refactoring: Apply PamhyrWindow to SL. 2023-09-26 09:34:26 +02:00
Pierre-Antoine Rouby 809a0dd9cb refarctoring: Apply PamhyrWindow to frictions. 2023-09-25 17:01:59 +02:00
Pierre-Antoine Rouby b2b5c971c3 refactoring: Apply new Pamhyr tools on IC. 2023-09-25 16:38:14 +02:00
Pierre-Antoine Rouby 7c4ba10871 refactoring: Continue refacto using PamhyrWindow. 2023-09-25 15:57:53 +02:00
Pierre-Antoine Rouby cc9f853a34 refactoring: Add PamhyrWidget and continue refacto using PamhyrWindow. 2023-09-25 15:31:41 +02:00
Pierre-Antoine Rouby fa32e42933 refactoring: Add PamhyrWindow and PamhyrDialog (WIP). 2023-09-25 15:10:30 +02:00
Pierre-Antoine Rouby 9c7f1f7ba9 doc: Try with system package. 2023-09-22 11:51:00 +02:00
Pierre-Antoine Rouby 3842e689ac doc: Fix build package missing. 2023-09-22 11:45:12 +02:00
Pierre-Antoine Rouby d461cb8001 doc: Fix htmlize into html build. 2023-09-22 11:29:04 +02:00
Pierre-Antoine Rouby 2bb783b5d4 ci: Add HTML documentation. 2023-09-22 11:09:55 +02:00
Pierre-Antoine Rouby edc5b65234 Scripts: Convert plot_3DST.py to Pamhyr2 script. 2023-09-22 11:03:07 +02:00
Pierre-Antoine Rouby 0237c5a80a MainWindow: Connect menu close model. 2023-09-22 09:25:47 +02:00
Pierre-Antoine Rouby 1201184669 packages: windows: Add Desktop shortcuts and update wine script. 2023-09-22 09:05:35 +02:00
Pierre-Antoine Rouby 36adba84e7 config: Fix arguments in default mage solver. 2023-09-20 17:25:34 +02:00
Pierre-Antoine Rouby afa21c9057 doc: dev: View section (UI, window). 2023-09-20 16:46:37 +02:00
Pierre-Antoine Rouby 42dfdcc3b1 doc: dev: Complete Model section. 2023-09-20 15:32:04 +02:00
Pierre-Antoine Rouby 6c9481296b doc: dev: Add SQL section with examples. 2023-09-20 15:21:46 +02:00
Pierre-Antoine Rouby 89353b656f doc: dev: Some minor change. 2023-09-20 11:52:53 +02:00
Pierre-Antoine Rouby 48851c7d71 ci: Fix documentations dependencies. 2023-09-20 10:10:41 +02:00
Pierre-Antoine Rouby d30028c57d ci: Disable package building at master branch. 2023-09-20 09:34:12 +02:00
125 changed files with 4373 additions and 3244 deletions

No files matched your search

+334
View File
@@ -1,6 +1,7 @@
### CUSTOM ### ### CUSTOM ###
*.exe *.exe
*.msi
*.tar.xz *.tar.xz
*.zip *.zip
*.spec *.spec
@@ -9,15 +10,33 @@
tmp tmp
*.tar
*.tar.* *.tar.*
*.tgz
*.zip *.zip
*.html
*.pdf
*.odt
doc/dev/images/auto_*
doc/dev/documentation.*
!doc/dev/*.org
doc/dev/images/auto_*
doc/users/documentation.*
!doc/users/*.org
TAGS
pamhyrBuild pamhyrBuild
wine-pamhyr-build* wine-pamhyr-build*
_PAMHYR_ _PAMHYR_
__old__ __old__
*-venv
### END CUSTOM ### ### END CUSTOM ###
# Created by https://www.toptal.com/developers/gitignore/api/python # Created by https://www.toptal.com/developers/gitignore/api/python
@@ -309,3 +328,318 @@ compile_commands.json
*_qmlcache.qrc *_qmlcache.qrc
# End of https://www.toptal.com/developers/gitignore/api/qt # End of https://www.toptal.com/developers/gitignore/api/qt
# Created by https://www.toptal.com/developers/gitignore/api/latex
# Edit at https://www.toptal.com/developers/gitignore?templates=latex
### LaTeX ###
## Core latex/pdflatex auxiliary files:
*.aux
*.lof
*.log
*.lot
*.fls
*.out
*.toc
*.fmt
*.fot
*.cb
*.cb2
.*.lb
## Intermediate documents:
*.dvi
*.xdv
*-converted-to.*
# these rules might exclude image files for figures etc.
# *.ps
# *.eps
# *.pdf
## Generated if empty string is given at "Please type another file name for output:"
.pdf
## Bibliography auxiliary files (bibtex/biblatex/biber):
*.bbl
*.bcf
*.blg
*-blx.aux
*-blx.bib
*.run.xml
## Build tool auxiliary files:
*.fdb_latexmk
*.synctex
*.synctex(busy)
*.synctex.gz
*.synctex.gz(busy)
*.pdfsync
## Build tool directories for auxiliary files
# latexrun
latex.out/
## Auxiliary and intermediate files from other packages:
# algorithms
*.alg
*.loa
# achemso
acs-*.bib
# amsthm
*.thm
# beamer
*.nav
*.pre
*.snm
*.vrb
# changes
*.soc
# comment
*.cut
# cprotect
*.cpt
# elsarticle (documentclass of Elsevier journals)
*.spl
# endnotes
*.ent
# fixme
*.lox
# feynmf/feynmp
*.mf
*.mp
*.t[1-9]
*.t[1-9][0-9]
*.tfm
#(r)(e)ledmac/(r)(e)ledpar
*.end
*.?end
*.[1-9]
*.[1-9][0-9]
*.[1-9][0-9][0-9]
*.[1-9]R
*.[1-9][0-9]R
*.[1-9][0-9][0-9]R
*.eledsec[1-9]
*.eledsec[1-9]R
*.eledsec[1-9][0-9]
*.eledsec[1-9][0-9]R
*.eledsec[1-9][0-9][0-9]
*.eledsec[1-9][0-9][0-9]R
# glossaries
*.acn
*.acr
*.glg
*.glo
*.gls
*.glsdefs
*.lzo
*.lzs
*.slg
*.slo
*.sls
# uncomment this for glossaries-extra (will ignore makeindex's style files!)
# *.ist
# gnuplot
*.gnuplot
*.table
# gnuplottex
*-gnuplottex-*
# gregoriotex
*.gaux
*.glog
*.gtex
# htlatex
*.4ct
*.4tc
*.idv
*.lg
*.trc
*.xref
# hyperref
*.brf
# knitr
*-concordance.tex
# TODO Uncomment the next line if you use knitr and want to ignore its generated tikz files
# *.tikz
*-tikzDictionary
# listings
*.lol
# luatexja-ruby
*.ltjruby
# makeidx
*.idx
*.ilg
*.ind
# minitoc
*.maf
*.mlf
*.mlt
*.mtc[0-9]*
*.slf[0-9]*
*.slt[0-9]*
*.stc[0-9]*
# minted
_minted*
*.pyg
# morewrites
*.mw
# newpax
*.newpax
# nomencl
*.nlg
*.nlo
*.nls
# pax
*.pax
# pdfpcnotes
*.pdfpc
# sagetex
*.sagetex.sage
*.sagetex.py
*.sagetex.scmd
# scrwfile
*.wrt
# svg
svg-inkscape/
# sympy
*.sout
*.sympy
sympy-plots-for-*.tex/
# pdfcomment
*.upa
*.upb
# pythontex
*.pytxcode
pythontex-files-*/
# tcolorbox
*.listing
# thmtools
*.loe
# TikZ & PGF
*.dpth
*.md5
*.auxlock
# titletoc
*.ptc
# todonotes
*.tdo
# vhistory
*.hst
*.ver
# easy-todo
*.lod
# xcolor
*.xcp
# xmpincl
*.xmpi
# xindy
*.xdy
# xypic precompiled matrices and outlines
*.xyc
*.xyd
# endfloat
*.ttt
*.fff
# Latexian
TSWLatexianTemp*
## Editors:
# WinEdt
*.bak
*.sav
# Texpad
.texpadtmp
# LyX
*.lyx~
# Kile
*.backup
# gummi
.*.swp
# KBibTeX
*~[0-9]*
# TeXnicCenter
*.tps
# auto folder when using emacs and auctex
./auto/*
*.el
# expex forward references with \gathertags
*-tags.tex
# standalone packages
*.sta
# Makeindex log files
*.lpz
# xwatermark package
*.xwm
# REVTeX puts footnotes in the bibliography by default, unless the nofootinbib
# option is specified. Footnotes are the stored in a file with suffix Notes.bib.
# Uncomment the next line to have this generated file ignored.
#*Notes.bib
### LaTeX Patch ###
# LIPIcs / OASIcs
*.vtc
# glossaries
*.glstex
# End of https://www.toptal.com/developers/gitignore/api/latex
+42 -16
View File
@@ -89,23 +89,41 @@ build-users-doc:
stage: build stage: build
tags: tags:
- linux - linux
needs:
- job: set-version
artifacts: true
script: script:
- cd ./doc/users/ - cd ./doc/users/
- ./build.sh - ./build.sh
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
tags: tags:
- linux - linux
needs:
- job: set-version
artifacts: true
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
@@ -130,39 +148,47 @@ build-linux:
# Setup virtual env # Setup virtual env
- python3 -m venv linux-venv - python3 -m venv linux-venv
- . linux-venv/bin/activate - . linux-venv/bin/activate
- pip3 install -r ../requirements.txt - pip3 install -U -r ../requirements.txt
# Run Pyinstaller # Run Pyinstaller
- pyinstaller -y --paths linux-venv/lib/python3.8/site-packages ../src/pamhyr.py - pyinstaller -y --paths linux-venv/lib/python3.8/site-packages ../src/pamhyr.py
# Create directory # Create directory
- mkdir -p pamhyr - mkdir -p pamhyr
- mkdir -p pamhyr/pamhyr - mkdir -p pamhyr/pamhyr
- mkdir -p pamhyr/pamhyr/_internal
# Copy Pamhyr info # Copy Pamhyr info
- cp -v ../VERSION pamhyr/pamhyr/ - cp -v ../VERSION pamhyr/pamhyr/_internal/
- cp -v ../AUTHORS pamhyr/pamhyr/ - cp -v ../AUTHORS pamhyr/pamhyr/_internal/
- cp -v ../LICENSE pamhyr/pamhyr/ - cp -v ../LICENSE pamhyr/pamhyr/_internal/
# Copy mage # Copy mage
- mkdir -p pamhyr/mage - mkdir -p pamhyr/mage
- cp -v ../mage-linux/* pamhyr/mage/ - cp -v ../mage-linux/* pamhyr/mage/
# Copy Pamhyr # Copy Pamhyr
- cp -r dist/pamhyr pamhyr/ - cp -r dist/pamhyr pamhyr/
# Copy Pamhyr resources # Copy Pamhyr resources
- mkdir -p pamhyr/pamhyr/View - mkdir -p pamhyr/pamhyr/_internal/View
- mkdir -p pamhyr/pamhyr/View/ui - mkdir -p pamhyr/pamhyr/_internal/View/ui
- mkdir -p pamhyr/pamhyr/View/ui/Widgets - mkdir -p pamhyr/pamhyr/_internal/View/ui/Widgets
- cp -r ../src/View/ui/*.ui pamhyr/pamhyr/View/ui/ - cp -r ../src/View/ui/*.ui pamhyr/pamhyr/_internal/View/ui/
- cp -r ../src/View/ui/ressources/ pamhyr/pamhyr/View/ui - cp -r ../src/View/ui/ressources/ pamhyr/pamhyr/_internal/View/ui
- cp -r ../src/View/ui/Widgets/*.ui pamhyr/pamhyr/View/ui/Widgets - cp -r ../src/View/ui/Widgets/*.ui pamhyr/pamhyr/_internal/View/ui/Widgets
# Copy lang # Copy lang
- mkdir -p pamhyr/pamhyr/lang - mkdir -p pamhyr/pamhyr/_internal/lang
- cp -r ../src/lang/*.qm pamhyr/pamhyr/lang - cp -r ../src/lang/*.qm pamhyr/pamhyr/_internal/lang
# Copy tests cases # Copy tests cases
- mkdir -p pamhyr/tests_cases/ - mkdir -p pamhyr/tests_cases/
- mkdir -p pamhyr/tests_cases/Saar - mkdir -p pamhyr/tests_cases/Saar
- 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/images/
- 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/users/documentation.html pamhyr/doc/Pamhyr2-users.html
- 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/Pamhyr2-dev.html
#- cp ../doc/users/images/* pamhyr/doc/images
- cp ../doc/dev/images/* pamhyr/doc/images
- cp ../doc/images/* pamhyr/doc/images
# 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
@@ -192,7 +218,7 @@ build-windows:
- mkdir windows - mkdir windows
- cd windows - cd windows
# Setup env # Setup env
- python -m pip install -r ..\requirements.txt - python -m pip install -U -r ..\requirements.txt
# Run Pyinstaller # Run Pyinstaller
- pyinstaller -y ..\src\pamhyr.py - pyinstaller -y ..\src\pamhyr.py
# Create directory # Create directory
@@ -248,7 +274,7 @@ linux-package-tar:
- job: build-linux - job: build-linux
artifacts: true artifacts: true
rules: rules:
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG - if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_TAG
artifacts: artifacts:
paths: paths:
- linux/pamhyr-gnulinux.tar.xz - linux/pamhyr-gnulinux.tar.xz
@@ -266,7 +292,7 @@ windows-package-zip:
- job: build-windows - job: build-windows
artifacts: true artifacts: true
rules: rules:
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG - if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_TAG
artifacts: artifacts:
paths: paths:
- windows/pamhyr-windows.zip - windows/pamhyr-windows.zip
@@ -284,7 +310,7 @@ windows-package-exe:
- job: build-windows - job: build-windows
artifacts: true artifacts: true
rules: rules:
- if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG - if: $CI_COMMIT_BRANCH == 'ci-test' || $CI_COMMIT_TAG
artifacts: artifacts:
paths: paths:
- windows/pamhyr-windows.exe - windows/pamhyr-windows.exe
+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
+906 -122
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"
+17 -11
View File
@@ -16,26 +16,26 @@ rem along with this program. If not, see <https://www.gnu.org/licenses/>.
@ECHO ON @ECHO ON
mkdir pamhyr\pamhyr mkdir pamhyr\pamhyr\_internal
xcopy /s /e /y dist\pamhyr pamhyr\pamhyr xcopy /s /e /y dist\pamhyr pamhyr\pamhyr
rem Copy data rem Copy data
mkdir pamhyr\pamhyr\lang mkdir pamhyr\pamhyr\_internal\lang
mkdir pamhyr\pamhyr\View\ui\ressources mkdir pamhyr\pamhyr\_internal\View\ui\ressources
mkdir pamhyr\pamhyr\View\ui\Widgets mkdir pamhyr\pamhyr\_internal\View\ui\Widgets
rem UI rem UI
copy /y ..\src\View\ui\ressources\ pamhyr\pamhyr\View\ui\ressources copy /y ..\src\View\ui\ressources\ pamhyr\pamhyr\_internal\View\ui\ressources
copy /y ..\src\View\ui\Widgets\*.ui pamhyr\pamhyr\View\ui\Widgets copy /y ..\src\View\ui\Widgets\*.ui pamhyr\pamhyr\_internal\View\ui\Widgets
copy /y ..\src\View\ui\*.ui pamhyr\pamhyr\View\ui\ copy /y ..\src\View\ui\*.ui pamhyr\pamhyr\_internal\View\ui\
rem Lang rem Lang
copy /y ..\src\lang\*.qm pamhyr\pamhyr\lang\ copy /y ..\src\lang\*.qm pamhyr\pamhyr\_internal\lang\
rem Information rem Information
copy /y ..\VERSION pamhyr\pamhyr copy /y ..\VERSION pamhyr\pamhyr\_internal
copy /y ..\AUTHORS pamhyr\pamhyr copy /y ..\AUTHORS pamhyr\pamhyr\_internal
copy /y ..\LICENSE pamhyr\pamhyr copy /y ..\LICENSE pamhyr\pamhyr\_internal
rem MAGE rem MAGE
mkdir pamhyr\mage mkdir pamhyr\mage
@@ -50,5 +50,11 @@ copy /y ..\tests_cases\Saar\Saar.pamhyr pamhyr\tests_cases\Saar\
rem Documentations rem Documentations
mkdir pamhyr\doc mkdir pamhyr\doc
mkdir pamhyr\doc\images
copy /y ..\doc\users\documentation.pdf pamhyr\doc\Pamhyr2-users.pdf copy /y ..\doc\users\documentation.pdf pamhyr\doc\Pamhyr2-users.pdf
copy /y ..\doc\dev\documentation.pdf pamhyr\doc\Pamhyr2-dev.pdf copy /y ..\doc\dev\documentation.pdf pamhyr\doc\Pamhyr2-dev.pdf
copy /y ..\doc\users\documentation.html pamhyr\doc\Pamhyr2-users.html
copy /y ..\doc\dev\documentation.html pamhyr\doc\Pamhyr2-dev.html
copy /y ..\doc\users\images\* pamhyr\doc\images
copy /y ..\doc\dev\images\* pamhyr\doc\images
copy /y ..\doc\images\* pamhyr\doc\images
+6 -2
View File
@@ -5,7 +5,7 @@
Name "Pamhyr2" Name "Pamhyr2"
OutFile "pamhyr-windows.exe" OutFile "pamhyr-windows.exe"
LicenseData "pamhyr\pamhyr\LICENSE" LicenseData "pamhyr\pamhyr\_internal\LICENSE"
LicenseText "I Agree" LicenseText "I Agree"
RequestExecutionLevel admin RequestExecutionLevel admin
@@ -39,11 +39,14 @@ Section "Pamhyr2"
SectionEnd SectionEnd
Section "Start Menu Shortcuts" Section "Start Menu Shortcuts"
CreateDirectory "$SMPROGRAMS\Pamhyr2" CreateDirectory "$SMPROGRAMS\Pamhyr2"
CreateShortcut "$SMPROGRAMS\Pamhyr2\Uninstall.lnk" "$INSTDIR\uninstall.exe" CreateShortcut "$SMPROGRAMS\Pamhyr2\Uninstall.lnk" "$INSTDIR\uninstall.exe"
CreateShortcut "$SMPROGRAMS\Pamhyr2\Pamhyr2.lnk" "$INSTDIR\pamhyr\pamhyr.exe" CreateShortcut "$SMPROGRAMS\Pamhyr2\Pamhyr2.lnk" "$INSTDIR\pamhyr\pamhyr.exe"
SectionEnd
Section "Desktop Shortcuts"
SetShellVarContext all
CreateShortcut "$desktop\Pamhyr2.lnk" "$instdir\pamhyr\pamhyr.exe"
SectionEnd SectionEnd
Section "Uninstall" Section "Uninstall"
@@ -51,6 +54,7 @@ Section "Uninstall"
DeleteRegKey HKLM SOFTWARE\NSIS_Pamhyr2 DeleteRegKey HKLM SOFTWARE\NSIS_Pamhyr2
Delete "$SMPROGRAMS\Pamhyr2\*.lnk" Delete "$SMPROGRAMS\Pamhyr2\*.lnk"
Delete "$desktop\Pamhyr2.lnk"
RMDir "$SMPROGRAMS\Pamhyr2" RMDir "$SMPROGRAMS\Pamhyr2"
RMDir /R "$INSTDIR" RMDir /R "$INSTDIR"
+45 -16
View File
@@ -81,13 +81,42 @@ wine pyinstaller ../src/pamhyr.py -y
echo " *** COPY DATA" echo " *** COPY DATA"
mkdir -p dist/pamhyr/View/ui mkdir -p pamhyr
cp -r ../src/View/ui/ressources/ dist/pamhyr/View/ui/ mkdir -p pamhyr/pamhyr
cp -r ../src/View/ui/Widgets/*.ui dist/pamhyr/View/ui/
cp -r ../src/View/ui/*.ui dist/pamhyr/View/ui/
cp ../VERSION dist/pamhyr/ # Copy Pamhyr info
cp ../AUTHORS dist/pamhyr/ cp -v ../VERSION pamhyr/pamhyr/
cp -v ../AUTHORS pamhyr/pamhyr/
cp -v ../LICENSE pamhyr/pamhyr/
# Copy mage
mkdir -p pamhyr/mage
cp -v ../mage/* pamhyr/mage/
# Copy Pamhyr
cp -r dist/pamhyr pamhyr/
# Copy Pamhyr resources
mkdir -p pamhyr/pamhyr/View
mkdir -p pamhyr/pamhyr/View/ui
mkdir -p pamhyr/pamhyr/View/ui/Widgets
cp -r ../src/View/ui/*.ui pamhyr/pamhyr/View/ui/
cp -r ../src/View/ui/ressources/ pamhyr/pamhyr/View/ui
cp -r ../src/View/ui/Widgets/*.ui pamhyr/pamhyr/View/ui/Widgets
# Copy lang
mkdir -p pamhyr/pamhyr/lang
cp -r ../src/lang/*.qm pamhyr/pamhyr/lang
# Copy tests cases
mkdir -p pamhyr/tests_cases/
mkdir -p pamhyr/tests_cases/Saar
cp ../tests_cases/Saar/Saar.pamhyr pamhyr/tests_cases/Saar/
# Copy documentations
mkdir -p pamhyr/doc/
cp ../doc/users/documentation.pdf pamhyr/doc/Pamhyr2-users.pdf
cp ../doc/dev/documentation.pdf pamhyr/doc/Pamhyr2-dev.pdf
# Update TS and build QM files # Update TS and build QM files
OLD_PWD=$PWD OLD_PWD=$PWD
@@ -102,19 +131,19 @@ echo " *** MAKE PACKAGES"
echo " TAR pamhyr-win-amd64.tar.xz" echo " TAR pamhyr-win-amd64.tar.xz"
OLD_PWD=$PWD # OLD_PWD=$PWD
cd dist/ # cd dist/
tar --xz -cf pamhyr-win-amd64.tar.xz pamhyr --checkpoint=.100 # tar --xz -cf pamhyr-win-amd64.tar.xz pamhyr --checkpoint=.100
cd $OLD_PWD # cd $OLD_PWD
mv dist/pamhyr-win-amd64.tar.xz ./ # mv dist/pamhyr-win-amd64.tar.xz ./
echo " ZIP pamhyr-win-amd64.zip" echo " ZIP pamhyr-win-amd64.zip"
OLD_PWD=$PWD # OLD_PWD=$PWD
cd dist/ # cd dist/
zip -r pamhyr-win-amd64.zip pamhyr/ # zip -r pamhyr-win-amd64.zip pamhyr/
cd $OLD_PWD # cd $OLD_PWD
mv dist/pamhyr-win-amd64.zip ./ # mv dist/pamhyr-win-amd64.zip ./
echo " *** MAKE INSTALLER" echo " *** MAKE INSTALLER"
+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
+2 -2
View File
@@ -40,8 +40,8 @@ class Point(object):
def sl(self, sl): def sl(self, sl):
if sl == self._profile.sl: if sl == self._profile.sl:
self._sl = None self._sl = None
else:
self._sl = sl self._sl = sl
@property @property
def name(self): def name(self):
+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 = []
+106
View File
@@ -0,0 +1,106 @@
# 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, sys
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"
@classmethod
def _path_file(cls, filename):
if ".py" in sys.argv[0]:
return os.path.abspath(
os.path.join(
os.path.dirname(__file__),
"..", "..", "..", "doc", 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)")
}
+99 -55
View File
@@ -23,11 +23,11 @@ from queue import Queue
from PyQt5 import QtGui from PyQt5 import QtGui
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QKeySequence, QKeySequence, QDesktopServices,
) )
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QTranslator, QEvent QTranslator, QEvent, QUrl,
) )
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QMainWindow, QApplication, QAction, QMainWindow, QApplication, QAction,
@@ -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):
@@ -180,7 +183,14 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
"action_menu_run_solver": self.run_solver, "action_menu_run_solver": self.run_solver,
"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_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_mage": self.open_doc_mage,
"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,
@@ -216,7 +226,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)
@@ -233,7 +243,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()
@@ -291,16 +301,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()
@@ -314,7 +324,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)
@@ -325,9 +335,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 #
############ ############
@@ -342,7 +355,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):
@@ -354,22 +367,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
@@ -386,11 +399,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 #
@@ -456,7 +469,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):
@@ -476,7 +489,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")
@@ -494,7 +507,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()
@@ -504,8 +517,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):
@@ -514,9 +527,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()
@@ -527,14 +540,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()
@@ -548,7 +561,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()
@@ -560,7 +573,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()
@@ -573,7 +586,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
) )
@@ -582,17 +595,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()
@@ -602,15 +615,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()
@@ -627,7 +641,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()
@@ -636,31 +650,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
@@ -669,7 +683,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
@@ -693,7 +707,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
@@ -702,24 +716,54 @@ 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)
#################
# DOCUMENTATION #
#################
def open_doc(self, filename):
if ".odt" in filename:
url = QUrl(f"file://{DocWindow._path_file(filename)}")
QDesktopServices.openUrl(url)
else:
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}")
def open_doc_mage(self):
self.open_doc("Mage-8.odt")
######### #########
# 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
# ) # )
# ) # )
Loaded 100 of 125 files, more files were not shown because too many files have changed in this diff. Show more