From e9f490f076af946f3f985dbea406fc17d1c33223 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 26 Jul 2023 08:57:12 +0200 Subject: [PATCH 01/64] ci: Add windows.bat and change gitlab-ci for build with wine runner. --- .gitlab-ci.yml | 86 +++++++++++++++++++++++++------------------- packages/windows.bat | 20 +++++++++++ 2 files changed, 70 insertions(+), 36 deletions(-) create mode 100644 packages/windows.bat diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5e670bc1..90bc7c9e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,7 @@ stages: - build - test + - package - release ######### @@ -12,11 +13,16 @@ build: script: - echo "TODO build pamhyr" -# build-lang: -# stage: build -# script: -# - cd ./src/lang/ -# - ./create_ts.sh +build-lang: + stage: build + tags: + - linux + script: + - cd ./src/lang/ + - ./create_ts.sh + artifacts: + paths: + - src/lang/*.qm ######### # TESTS # @@ -32,56 +38,64 @@ test: ############ linux-package: - stage: release + stage: package tags: - release - linux - rules: - - if: $CI_COMMIT_BRANCH == 'master' - - if: $CI_COMMIT_TAG - when: never + needs: + - job: build-lang + artifacts: true + # rules: + # - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG + # when: never artifacts: paths: - # - packages/pamhyr-src.tar.gz - packages/pamhyr-gnulinux-amd64.tar.xz script: - cd packages - ./linux.sh -# windows-package: -# stage: release -# tags: -# - release -# - wine -# rules: -# - if: $CI_COMMIT_BRANCH == 'master' -# - if: $CI_COMMIT_TAG -# when: never -# artifacts: -# paths: -# - packages/pamhyr-win-amd64.zip -# - packages/pamhyr-win-amd64.exe -# script: -# - cd packages -# - ./wine.sh ci +windows-package: + stage: package + tags: + - release + - wine + needs: + - job: build-lang + artifacts: true + # rules: + # - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG + # when: never + artifacts: + paths: + - packages/pamhyr-win-amd64.exe + script: + - cd packages + - ./windows.bat + +########### +# RELEASE # +########### tag-release: stage: release tags: - release - linux - - wine + needs: + - job: linux-package + artifacts: true + - job: windows-package + artifacts: true rules: - if: $CI_COMMIT_TAG artifacts: paths: - packages/pamhyr-gnulinux-amd64.tar.xz - # - packages/pamhyr-win-amd64.zip - # - packages/pamhyr-win-amd64.exe script: - cd packages - - ./linux.sh - # - ./wine.sh ci + # - ./linux.sh + # # - ./wine.sh ci release: name: '$CI_COMMIT_TAG' description: 'Automatic release from tag $CI_COMMIT_TAG' @@ -97,7 +111,7 @@ tag-release: # url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/packages/pamhyr-win-amd64.zip' # filepath: '/packages/pamhyr-win-amd64.zip' # link_type: 'Packages' - # - name: 'Windows amd64 (exe)' - # url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/packages/pamhyr-win-amd64.exe' - # filepath: '/packages/pamhyr-win-amd64.exe' - # link_type: 'Packages' + - name: 'Windows amd64 (exe)' + url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/packages/pamhyr-win-amd64.exe' + filepath: '/packages/pamhyr-win-amd64.exe' + link_type: 'other' diff --git a/packages/windows.bat b/packages/windows.bat new file mode 100644 index 00000000..42c46ba0 --- /dev/null +++ b/packages/windows.bat @@ -0,0 +1,20 @@ +rem Windows batch for pamhyr windows version building +@ECHO ON + +rem Python environment +python -m pip install -r ..\requirements.txt + +rem Build windows version +pyinstaller ..\src\pamhyr.py -y + +rem Copy data +mkdir dist\pamhyr\View\ui\ressources +mkdir dist\pamhyr\View\ui\Widgets + +copy /y ..\src\View\ui\ressources\ dist\pamhyr\View\ui\ressources +copy /y ..\src\View\ui\Widgets\*.ui dist\pamhyr\View\ui\Widgets +copy /y ..\src\View\ui\*.ui dist\pamhyr\View\ui\ +copy /y ..\src\lang\*.qm dist\pamhyr\lang\ + +rem Make installer +"C:\Program Files (x86)\NSIS\makensis.exe" pamhyr.nsi From 41961a786e6fb43728153f640ddb4ae30c8d9dbf Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 26 Jul 2023 11:41:23 +0200 Subject: [PATCH 02/64] ci: Disable windows build. --- .gitlab-ci.yml | 51 ++++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 90bc7c9e..ec641795 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -55,23 +55,23 @@ linux-package: - cd packages - ./linux.sh -windows-package: - stage: package - tags: - - release - - wine - needs: - - job: build-lang - artifacts: true - # rules: - # - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG - # when: never - artifacts: - paths: - - packages/pamhyr-win-amd64.exe - script: - - cd packages - - ./windows.bat +# windows-package: +# stage: package +# tags: +# - release +# - wine +# needs: +# - job: build-lang +# artifacts: true +# # rules: +# # - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG +# # when: never +# artifacts: +# paths: +# - packages/pamhyr-win-amd64.exe +# script: +# - cd packages +# - ./windows.bat ########### # RELEASE # @@ -85,13 +85,14 @@ tag-release: needs: - job: linux-package artifacts: true - - job: windows-package - artifacts: true + # - job: windows-package + # artifacts: true rules: - if: $CI_COMMIT_TAG artifacts: paths: - packages/pamhyr-gnulinux-amd64.tar.xz + - packages/pamhyr-win-amd64.exe script: - cd packages # - ./linux.sh @@ -107,11 +108,7 @@ tag-release: url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/packages/pamhyr-gnulinux-amd64.tar.xz' filepath: '/packages/pamhyr-gnulinux-amd64.tar.xz' link_type: 'other' - # - name: 'Windows amd64 (zip)' - # url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/packages/pamhyr-win-amd64.zip' - # filepath: '/packages/pamhyr-win-amd64.zip' - # link_type: 'Packages' - - name: 'Windows amd64 (exe)' - url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/packages/pamhyr-win-amd64.exe' - filepath: '/packages/pamhyr-win-amd64.exe' - link_type: 'other' + # - name: 'Windows amd64 (exe)' + # url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/packages/pamhyr-win-amd64.exe' + # filepath: '/packages/pamhyr-win-amd64.exe' + # link_type: 'other' From 3f41a2e9d9ab46afeeb1b52f8419baa938dc1f92 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 26 Jul 2023 16:37:01 +0200 Subject: [PATCH 03/64] Trans: Update partial french translate and minor change in mainwindow. --- src/View/ui/MainWindow.ui | 55 +- src/lang/fr.ts | 2083 +++++++++++++++++++++++++++---------- 2 files changed, 1538 insertions(+), 600 deletions(-) diff --git a/src/View/ui/MainWindow.ui b/src/View/ui/MainWindow.ui index b63f032c..6913d02a 100644 --- a/src/View/ui/MainWindow.ui +++ b/src/View/ui/MainWindow.ui @@ -85,17 +85,12 @@ - - - - - @@ -117,32 +112,8 @@ &Geometry - - - Comparer - - - - Profil en travers - - - - - - - - - - - - - - - - - @@ -152,8 +123,8 @@ &Execute + - @@ -166,14 +137,9 @@ - - - - - @@ -264,8 +230,6 @@ - - @@ -290,12 +254,8 @@ - - - - @@ -729,10 +689,10 @@ ressources/exit_bis.pngressources/exit_bis.png - Quit application + Quit - Quitter l'application (Ctrl+Q) + Quit the application (Ctrl+Q) Ctrl+Q @@ -747,7 +707,7 @@ Run solver - Run solver on current study + Run a solver @@ -828,7 +788,7 @@ Mesh - Afficher le maillage + Display meshed reach @@ -863,7 +823,7 @@ Friction - Edit friction frictions and lateral contributions + Edit friction frictions @@ -908,6 +868,9 @@ Initial conditions + + Define initial conditions + diff --git a/src/lang/fr.ts b/src/lang/fr.ts index d44729f7..9eabd6ef 100644 --- a/src/lang/fr.ts +++ b/src/lang/fr.ts @@ -1,1101 +1,2076 @@ - + - Dialog + BoundaryCondition - - Dialog + + Not associate + Non associer + + + + X - + + Y + + + + + Time + Temps + + + + Date + Date + + + + Z (m) + Z (m) + + + + days + jours + + + + day + jour + + + + Not defined + Non définie + + + + Ponctual contribution + Contributions ponctuelles + + + + Time over Z + + + + + Time over Discharge + + + + + Z over Discharge + + + + Name Nom - + Type Type - + + Node + Nœud + + + + Discharge (m³/s) + Débit (m³/s) + + + + Discharge (m³/s) + + + + + Checker + + + Mage network graph {mode} checker + + + + + Check if the network graph is valid + Vérifie si le graph réseau est valide + + + + Study network reach checker + + + + + Check if exists at least one reach for study + Vérifie si il exists au moins un Bief dans l'étude + + + + Study geometry checker + Vérificateur de géometrie de l'étude + + + + Check if exists geometry for each reach of study + Vérifie si la géométrie exists pour chaque bief de l'étude + + + + Dummy ok + + + + + Dummy warning + + + + + Dummy error + + + + + Dialog + + + Dialog + + + + + Name + Nom + + + + Type + Type + + + Description Description - + Solver - Solveur + Solver - + Path Chemin - + Output formater - Formateur de resultat + Formateur de sortie - + Command line Ligne de commande - + Input formater Formateur d'entrée - - Reverse - Retourner + + Cancel + Annuler - + + Run + Lancer + + + + Draft + Débit (m³/s) + + + Solvers - Solveurs + Solvers - + Meshing tool Mailleur - + Meshing tool path Chemin du mailleur - + Constants Constantes - + Segment number - Nombre de segment + Nombre se segments - + Listing maximum size - Taille maximum des listings + Taille maximal du listing - + 1000 - 1000 + - + 500000 - 500000 + - + Backup - Backup + Archive - + Auto save - Sauvegarde automatique + Sauvegarde auto - + Frequence Fréquence - + Max. archives - Nombre maximum de sauvegarde + Nombre max d'archive - + Enable Activé - + HH:mm:ss - + + Stricklers + + + + + Editor + Éditeur + + + + This value must be used for reading or editing files in speficic case. + Cette valeur peut être utiliser dans des cas spécifique pour lire ou écrire dans un fichier. + + + + Editor command + Commande de l'éditeur + + + + - The "@file" keyworkd is replace by the path of file to open. + - Le mot clef "@file" sera remplacer par le chemin du fichier à ouvrir. + + + Language Langage - + Please restart application after language modification - Please restart application after language modification + Please restart application after language modification - + MyNewStudy - MaNouvelleÉtude + Ma nouvelle étude + + + + Time system + Système de temps + + + + Time + Temps + + + + Date + Date + + + + Staring date + Date de départ + + + + dd/MM/yyyy HH:mm:ss + + + + + Creation date : + Date de création : + + + + Last modification : + Dernière modification : + + + + Discharge + Débit (m³/s) + + + + Exception + + + Generic error message + + + + + Undefined error message + + + + + Method not implemented + + + + + Method + + + + + not implemented + + + + + for class + + + + + Not implemented method + + + + + FileFormatError + + + + + Invalid file format: + + + + + File format error + + + + + Invalid file format + + + + + Invalid file + + + + + format because of + + + + + Clipboard format error + + + + + without header + + + + + with header + + + + + Invalid clipboard data format: + + + + + Clipboard format unknown + Form - + Form - + PamHyr - + Version en developpement: - - - MainWindow - - PAMHYR + + dd/MM/yyyy HH:mm:ss - + + days + jours + + + + HH:mm:ss + + + + + Frictions + + + Not defined + Non définie + + + + Name + Nom + + + + Begin kp (m) + Pk de départ (m) + + + + End kp (m) + Pk de fin (m) + + + + Begin strickler + strickler de départ + + + + End strickler + Strickler de fin + + + + Geometry + + + Name + Nom + + + + Kp (m) + Pk (m) + + + + Type + Type + + + + upstream + amont + + + + downstream + aval + + + + LateralContribution + + + Name + Nom + + + + Minor bed + Lit mineur + + + + Medium bed + Lit moyen + + + + Comment + Commentaire + + + + Not associate + Non associer + + + + X + + + + + Y + + + + + Time + Temps + + + + Date + Date + + + + Z (m) + + + + + days + jours + + + + day + jour + + + + Not defined + Non définie + + + + Lateral contribution + Contribution laterale + + + + Rain + Pluie + + + + Evaporation + Évaporation + + + + Type + Type + + + + Reach + Bief + + + + Begin kp (m) + Pk de départ (m) + + + + End kp (m) + Pk de fin (m) + + + + KP (m) + PK (m) + + + + Elevation (m) + Altitude (m) + + + + Height (m) + Hauteur (m) + + + + Discharge (m³/s) + Débit (m³/s) + + + + Discharge (m³/s) + + + + + MainWindow + + + MainWindow + Fenêtre principale + + + + toolBar + Bar d'outils + + + + Add node or edge + Ajouter un nœud ou une arête + + + + Remove node or edge + Supprimer un nœud ou une arête + + + + PAMHYR + PAMHYR + + + &File &Fichier - + &River Network &Réseau - + &Geometry &Géométrie - + Comparer - Comparer + Comparer - - Profil en travers - - - - + &Execute - &Exécuter + &Executer - + &Hydraulics - &Hydrolique + &Hydraulique - + &Plots - &Graphiques + Gra&phique - + &Cartography &Cartographie - + &Help &Aide - - toolBar - - - - + toolBar_2 - + - + New study Nouvelle étude - + Ctrl+N - + - + Open a study Ouvrir une étude - + Ctrl+O - + - + Import data from MAGE - Importer un jeu de données MAGE + Importer des données d'une étude MAGE - + Import data from RubarBE - Importer un jeu de données RubarBE + Importer des données d'une étude RubarBE - + Close Fermer - + Close current study - Fermer l'étude courante + Fermer l'étude en cours - + Save mesh Sauvegarder le maillage - + Save Sauvegarder - + Ctrl+S - + - + Save as ... - Sauvegarder sous ... + Sauvegarder sous... - + Ctrl+Shift+S - + - + Archive - + Archive - + Pamhyr configuration - Configuration de PamHyr + Configuration de PAMHYR - + Quit Quitter - + Ctrl+F4 - + - + Edit river network Éditer le réseau - + Edit geometry Éditer la géométrie - + Import geometry - Importer une géometrie + Importer une géométrie - + Export geometry - + Exporter la géométrie - + Run extrenal meshing tool - + Lancer le mailler externe - + choose meshing tool by reach - + View meshed geometry - + Voir la géométrie mailler - + Export mesh - + Exporter le maillage - + Delete mesh of current reach - + Supprimer le maillage - + Delete all mesh - + - + Abscisse - Cote - + XYZ - + - - Numerical parameter for MAGE solver - + + Numerical parameter for solvers + Paramètre numerique des solvers - + Boundary conditions and one-time contributions - + Condition aux limites et apports ponctuels - + Initial conditions - + Conditions initiales - + Export initial conditions - + Exporter les conditions initiales - + Import final state as initial condition - + Importer un état final comme conditions initiales - + Edit friction - + Éditer les frottements - + Edit lateral contributions - + Éditer les apports latéraux - + Edit spills - + Edit cross building - + Éditer les ouvrages - + Run solver - + Lancer un solver - + + F5 + + + + Stop solver - + Stopper le solver - + Display listings - + Simulation directory management - + Open - Ouvrir + Ouvrir - + Hydrograph - + Hydrogramme - + Limnigram - + Limnigramme - + Map current reach - + Cartographier le bief sélectionné - + Help PAMHYR - + Aide de PAMHYR - - help MAGE - + + Help MAGE + Aide de MAGE - + About - + A propos - + ouvrir - + Save current study - + Sauvegarder l'étude - + Ctrl+F - + - + Quit application - + Quitter l'application - - Quitter l'application (Ctrl+Q) - - - - + Ctrl+Q - + - - Run solver on current study - - - - - Ctrl+X - - - - + stop solver - + Interrompt la simulation en cours - + Ctrl+C - + - + Run external meshing tool - + Lancer le mailler externe - + Run meshing tool on current reach geometry - + Lancer le mailler externe sur le bief selectionné - + Display simulation listing - + Display current simulation listing - + River network - + Réseau - + Geometry - + Géométrie - + Edit reach geometry - + Éditer la géométrie - + Mesh - + Maillage - - Afficher le maillage - - - - + Boundary conditions - + Conditions aux limites - + Edit boundary conditions and one-time contributions - + Éditer les conditions aux limites et les apports ponctuels - + Lateral contribution - + Contributions latérales - + Edit lateral contribution - + Éditer les contributions latérales - + Spills - + Edit lateral spills - - Sections - + + Friction + Frottements - - Edit section frictions and lateral contributions - + + Stricklers + - - Frictions - + + Edit the study stricklers + Éditer les Stricklers de l'étude - - Edit friction at the bottom - - - - + Building - + Ouvrages - + Edit building (valve, ...), singularity and pump - + Éditer les ouvrages - + Edit study - + Éditer l'étude - + English - + - + French + + + + + Revert + Retourner + + + + Open in editor + Ouvrir dans l'éditeur + + + + Eval + Évaluer + + + + Ctrl+Return + + + + + Liquid + Liquide + + + + Solid + Solide + + + + Suspenssion + Suspenssion + + + + Add + Ajouter + + + + Add a new boundary condition or lateral contribution + Ajouter une condition aux limites ou un apport ponctuel + + + + Delete + Supprimer + + + + Delete current selected rows + Supprimer les lignes selectionnées + + + + Ctrl+D + + + + + Edit + Éditer + + + + Edit boundary condition or lateral contribution + Éditer une condition aux limites ou un apport ponctuel + + + + Ctrl+E + + + + + Sort + Trier + + + + Sort boundary condition by name + Trié par nom + + + + Study stricklers + Stricklers de l'étude + + + + Application stricklers + Stricklers de l'application + + + + Add new stricklers + Ajouter un stricklers + + + + Delete selected stricklers + Supprimer les stricklers selectionnés + + + + Sort stricklers + Trier les stricklers + + + + delete + Supprimer + + + + Edit stricklers + Éditer les stricklers + + + + Cancel + Annuler + + + + Retry + Ressayer + + + + Run + Lancer + + + + Retry check + Ressayer la vérification + + + + Stop + Stopper + + + + Start + Commencer + + + + Pause + Pause + + + + LogFile + Fichier de log + + + + Generate minimal height + Généré une hauteur minimale + + + + Generate constant discharge + Généré un debit constant + + + + Add new initial condition + Ajouter une nouvelle condition initiale + + + + Delete inital condition + Supprimer une condition initiale + + + + sort + Trier + + + + Sort inital condition + Trier les conditions initiales + + + + Add a new point in boundary condition or lateral contribution + Ajouter un nouveau point + + + + Sort boundary condition point + Trier les points des conditions aux limites + + + + Quit the application (Ctrl+Q) - - &Fichier + + Run a solver + Lancer un solver + + + + Display meshed reach - - &Hydraulique - + + Edit friction frictions + Éditer les frottements - - &Graphiques - - - - - &Cartographie - - - - - &Aide - - - - - Ctrl+R - - - - - Fermer - - - - - Enregistrer le maillage - - - - - Enregistrer - - - - - Enregistrer sous ... - - - - - Archiver - - - - - Configuration de Pamhyr - - - - - Quitter - - - - - Lancer le mailleur externe - - - - - Choix du mailleur par bief - - - - - Exporter le maillage - - - - - Supprimer le maillage du bief courant - - - - - Supprimer l'ensemble des maillages - - - - - Conditions aux Limites & Apports Ponctuels - - - - - Conditions initiales - - - - - Solveur MAGE - - - - - Stop Solveur - - - - - Afficher les listings - - - - - Ouvrir - - - - - Hydrogramme - - - - - Limnigramme - - - - - Ligne d'eau - - - - - Ligne d'eau finale - - - - - Ligne d'eau enveloppe - - - - - Voir l'animation (MAGE) - - - - - Cartographier le bief courant - - - - - Aide de PAMHYR - - - - - Aide de MAGE - - - - - enregistrer_etude_en_cours - - - - - fermer_etude_en_cours - - - - - quitter_application - - - - - lancer_solveur - - - - - interrompt_simulation_en_cours - - - - - lancer_mailleur_externe - - - - - afficher_listings_simulation - - - - - Aficher les listings de la simulation courante - - - - - Maillage - - - - - Cond. Limites - - - - - Frottements - - - - - Ouvrages - + + Define initial conditions + Définire les conditions initiales - + Édition des Tronçons - + Ouvrir une étude - + Enrégistrer étude en cours (Ctrl+S) - + Fermer étude en cours (Ctrl+F) - - - &Réseau + + + MainWindowProfile + + + Profile + + + + + (no name) + + + + + Quittez ? + + + + + MainWindowProfile + + + + + Trier les points par ordre croissant de X + + + + + Trier les points par ordre croissant de Y + + + + + Nom + + + + + Abs en travers (m) + + + + + La cote du fond + Z minimale + + + + + La cote maximale + Z maximale + + + + + Rive gauche + + + + + Rive droite + + + + + Abscisse en travers (m) + + + + + Cote (m) - - &Géométrie + + Suppression les lignes incomplètes - - &Exécuter + + Supprimer les lignes des cellules non renseignées ? - - Sous-étude Rubar3 + + Suppression des noms répétés - - Nouvelle étude MAGE + + Etes-vous sûr de vouloir quitter ? - - Nouvelle étude RubarBE + + Insérer un point - - Importer un jeu de données MAGE + + Supprimer le/les point(s) sélectionnés - - Importer un jeu de données RubarBE + + Trier les points par ordre décroissant de X - - Éditer le réseau + + Trier les points par ordre décroissant de Y - - Éditer la géométrie + + Décaler le point sélectionné vers le haut - - Importer une géométrie + + Décaler le point sélectionné vers le bas - - Exporter la géométrie + + Exporter (dans un fichier) les points du profil au format tabulé - - Visualiser la géométrie maillée + + Copier la sélection au format tabulé - - Paramètres numériques du solveur MAGE + + Coller la sélection depuis le presse-papier au format tabulé - - Activer/Désactiver l'export des conditions initiales + + Vérifier la validité de la saisie et garder ou pas les modifications apportées - - Importer l'état final comme état initial + + Annuler toutes les modifications depuis la dernière validation - - Édition des Frottements + + Annuler toutes les modifications et revenir à l'état initial - - Édition des Apports Latéraux + + Ligne d'eau : + Z : Cote (m) + A : Aire mouillée (mu00B2) + p : Périmètre mouillé (m) + L : Largeur au miroir (m) - - Édition des déversements + + 'Maj + Clic' : Ligne d'eau & 'Ctrl + Clic' : Sélectionner des points - - Édition des ouvrages en travers + + Abscisse en travers calculée en projétant les points +sur le plan défini par les deux points nommés extrêmes + + + + + MainWindow_reach + + + Stricklers + + + + + Kp (m) + Pk (m) + + + + Ouvrir un fichier + + + + + Fichiers .ST (*.ST) + + + + + Fichiers .M (*.M) + + + + + Tous les fichiers (*) + + + + + Kp : + + + + + Files .ST(*.ST or *.st) + + + + + All files (*) + + + + + Abscisse en travers (m) + + + + + Cote (m) + + + + + Profil suivant + + + + + Jeu de sections du Bief + + + + + +Ordre des sections : Amont --> Aval + + + + + Pk = + + + + + Nouveau profil + + + + + Trier les profils par ordre croissant des Pk + + + + + Name + Nom + + + + Type + Type + + + + Alt+Z + + + + + Alt+E + + + + + Alt+R + + + + + Vue globale automatique (Alt+S) + + + + + Vue globale automatique (Alt+D) + + + + + Vue globale automatique (Alt+F) + + + + + X (m) + + + + + Y (m) + + + + + Draft (m) + + + + + KP (m) + + + + + Discharge (m^3/s) + Débit (m³/s) + + + + Choisissez un nom de fichier à sauvegarder - - Gestion des répertoires de simulation + + Édition des profils sélectionnés - - Vitesse(Pk) à t fixé + + Vous avez sélectionné plus de 5 profils. +Seuls les 5 premiers seront édités. - - Vitesse(t) à Pk fixé + + Profil N° : - - Charge hydraulique(Pk) à t fixé + + Profil précédent - - Charge hydraulique(t) à Pk fixé + + Profil sélectionné - - Autres résulats MAGE + + Importer une géométrie - - À propos + + Supprimer le profil sélectionné - - Lancer le solveur pour réaliser une simulation + + Éditer le profil sélectionné - - Lancer le mailleur externe sur la géométrie du bief courant + + Copier le profil sélectionné - - Réseau + + Coller le profil en fin de liste (penser à modifier le Pk avant de trier) - - Ouvrir l'éditeur de la topologie du réseau + + Dupliquer la section sélectionnée - - Géométrie + + Trier les profils par ordre décroissant des Pk - - Ouvrir l'éditeur de géométrie + + Changer l'ordre des profils (en décalant le profil sélectionné vers le haut) - - Ouvir l'éditeur des Conditions aux Limites & Apports Ponctuels + + Changer l'ordre des profils (en décalant le profil sélectionné vers le bas) - - App. Latéraux + + Terminer l'édition - - Ouvrir l'éditeur des Apports Latéraux Distribués + + Vue isométrique (Alt+Z) - - Déversements + + Vue isométrique (Alt+E) - - Ouvrir l'éditeur des Déversements Latéraux + + Vue isométrique (Alt+R) + + + + + Network + + + Add node + Ajouter un nœud + + + + Delete the node + Supprimer un nœud + + + + Disable the node + Déactiver un nœud + + + + Delete the reach + Supprimer un bief + + + + Disable the reach + Déactiver un bief + + + + Enable the reach + Activer un bief + + + + Reverse the reach orientation + Inverser l'orientation du bief + + + + SolverParameters + + + Name + Nom + + + + Value + Valeur + + + + Yes + Oui + + + + No + Non + + + + Y + O + + + + N + N + + + + Initial time (jj:hh:mm:ss) + Temps initial (jj:hh:mm:ss) + + + + Final time (jj:hh:mm:ss) + Temps final (jj:hh:mm:ss) + + + + Timestep (second) + Pas de temps (en second) + + + + Minimum timestep (second) + Pas de temps minimal (en second) + + + + Time step of writing on .TRA + Pas de temps d'écriture dans le fichier .TRA + + + + Time step of writing on .BIN + Pas de temps d'écriture dans le fichier .BIN + + + + Implicitation parameter + + + + + Continuity discretization type (S/L) + + + + + QSJ discretization (A/B) + + + + + Stop criterion iterations (G/A/R) + + + + + Iteration type + + + + + Smoothing coefficient + + + + + Maximun accepted number of CFL + + + + + Minimum water height (meter) + + + + + Maximun number of iterations (< 100) + + + + + Timestep reduction factor + + + + + Reduction precision factor of Z + + + + + Reduction precision factor of Q + + + + + Reduction precision factor of residue + + + + + Number of iteration at maximum precision + + + + + Number of iteration before switch + + + + + Maximum accepted Froude number + + + + + Diffluence node height balance + + + + + Compute reach volume balance (Y/N) + + + + + Maximum reach volume balance + + + + + Minimum reach volume to check + + + + + Solvers + + + Generic + Générique + + + + Mage version 8 + Mage en version 8 + + + + Toolbar + + + Vue originale + + + + + Panoramique des axes avec la souris gauche, zoom avec la droite + + + + + Zoom + + + + + Vue globale automatique (Shift+X) + + + + + Enregistrer la figure - - Tronçons + + Retour à la vue précédente - - Ouvrir l'éditeur des tronçons pour les frottements et Apports Latéraux + + Passer à la vue suivante - - Ouvrir l'éditeur des frottements au fond - - - - - Ouvrir l'éditeur des ouvrages (seuils, vannes, etc.), singularités et pompes + + Vue isométrique (Shift+W) From 25a01682d400c83636fbce7ae76cd9c4022e20e7 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 26 Jul 2023 17:03:18 +0200 Subject: [PATCH 04/64] ci: Enable windows package. --- .gitlab-ci.yml | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ec641795..da4feb5c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -55,23 +55,23 @@ linux-package: - cd packages - ./linux.sh -# windows-package: -# stage: package -# tags: -# - release -# - wine -# needs: -# - job: build-lang -# artifacts: true -# # rules: -# # - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG -# # when: never -# artifacts: -# paths: -# - packages/pamhyr-win-amd64.exe -# script: -# - cd packages -# - ./windows.bat +windows-package: + stage: package + tags: + - release + - wine + needs: + - job: build-lang + artifacts: true + # rules: + # - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG + # when: never + artifacts: + paths: + - packages/pamhyr-win-amd64.exe + script: + - cd packages + - ./windows.bat ########### # RELEASE # @@ -85,8 +85,8 @@ tag-release: needs: - job: linux-package artifacts: true - # - job: windows-package - # artifacts: true + - job: windows-package + artifacts: true rules: - if: $CI_COMMIT_TAG artifacts: @@ -108,7 +108,7 @@ tag-release: url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/packages/pamhyr-gnulinux-amd64.tar.xz' filepath: '/packages/pamhyr-gnulinux-amd64.tar.xz' link_type: 'other' - # - name: 'Windows amd64 (exe)' - # url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/packages/pamhyr-win-amd64.exe' - # filepath: '/packages/pamhyr-win-amd64.exe' - # link_type: 'other' + - name: 'Windows amd64 (exe)' + url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/packages/pamhyr-win-amd64.exe' + filepath: '/packages/pamhyr-win-amd64.exe' + link_type: 'other' From 86d022dc9368df087502c33436792db62ab3e609 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 26 Jul 2023 17:14:05 +0200 Subject: [PATCH 05/64] ci: Active rules for packages. --- .gitlab-ci.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index da4feb5c..5bb9624c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -45,9 +45,8 @@ linux-package: needs: - job: build-lang artifacts: true - # rules: - # - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG - # when: never + rules: + - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG artifacts: paths: - packages/pamhyr-gnulinux-amd64.tar.xz @@ -63,9 +62,8 @@ windows-package: needs: - job: build-lang artifacts: true - # rules: - # - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG - # when: never + rules: + - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG artifacts: paths: - packages/pamhyr-win-amd64.exe @@ -95,8 +93,6 @@ tag-release: - packages/pamhyr-win-amd64.exe script: - cd packages - # - ./linux.sh - # # - ./wine.sh ci release: name: '$CI_COMMIT_TAG' description: 'Automatic release from tag $CI_COMMIT_TAG' From a22a7606100874273076c7aec9e73971c468890c Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 28 Jul 2023 09:56:47 +0200 Subject: [PATCH 06/64] About: Update about window and add VERSION file. --- .gitlab-ci.yml | 12 +++- VERSION | 1 + packages/linux.sh | 1 + packages/version.sh | 10 +++ packages/windows.bat | 1 + src/VERSION | 1 + src/View/ASubWindow.py | 25 +++++++ src/View/About/Window.py | 20 ++++++ src/View/ui/about.ui | 92 +++++++++++++++++--------- src/View/ui/ressources/Logo-INRAE.png | Bin 0 -> 8635 bytes 10 files changed, 131 insertions(+), 32 deletions(-) create mode 100644 VERSION create mode 100755 packages/version.sh create mode 120000 src/VERSION create mode 100644 src/View/ui/ressources/Logo-INRAE.png diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5bb9624c..014dde47 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,8 +10,14 @@ stages: build: stage: build + tags: + - linux script: - - echo "TODO build pamhyr" + - cd packages + - ./version.sh "$CI_COMMIT_BRANCH" "$CI_COMMIT_TAG" "$CI_COMMIT_SHORT_SHA" + artifacts: + paths: + - VERSION build-lang: stage: build @@ -45,6 +51,8 @@ linux-package: needs: - job: build-lang artifacts: true + - job: build + artifacts: true rules: - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG artifacts: @@ -62,6 +70,8 @@ windows-package: needs: - job: build-lang artifacts: true + - job: build + artifacts: true rules: - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG artifacts: diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..5664e303 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +git diff --git a/packages/linux.sh b/packages/linux.sh index 1cd72d28..9924eb0b 100755 --- a/packages/linux.sh +++ b/packages/linux.sh @@ -35,6 +35,7 @@ cp -r ../src/View/ui/*.ui dist/pamhyr/View/ui/ mkdir -p dist/pamhyr/lang cp -r ../src/lang/*.qm dist/pamhyr/lang/ +cp ../VERSION dist/pamhyr/ echo " *** MAKE SRC PACKAGE" diff --git a/packages/version.sh b/packages/version.sh new file mode 100755 index 00000000..aa769b83 --- /dev/null +++ b/packages/version.sh @@ -0,0 +1,10 @@ +#! /bin/sh + +# ./version BRANCH TAG COMMIT + +if [ -z $2 ]; +then + echo "$1-$3" > ../VERSION +else + echo "$2" > ../VERSION +fi diff --git a/packages/windows.bat b/packages/windows.bat index 42c46ba0..c5d150df 100644 --- a/packages/windows.bat +++ b/packages/windows.bat @@ -15,6 +15,7 @@ copy /y ..\src\View\ui\ressources\ dist\pamhyr\View\ui\ressources copy /y ..\src\View\ui\Widgets\*.ui dist\pamhyr\View\ui\Widgets copy /y ..\src\View\ui\*.ui dist\pamhyr\View\ui\ copy /y ..\src\lang\*.qm dist\pamhyr\lang\ +copy /y ..\VERSION dist\pamhyr\ rem Make installer "C:\Program Files (x86)\NSIS\makensis.exe" pamhyr.nsi diff --git a/src/VERSION b/src/VERSION new file mode 120000 index 00000000..6ff19de4 --- /dev/null +++ b/src/VERSION @@ -0,0 +1 @@ +../VERSION \ No newline at end of file diff --git a/src/View/ASubWindow.py b/src/View/ASubWindow.py index 478993cf..17ae4a07 100644 --- a/src/View/ASubWindow.py +++ b/src/View/ASubWindow.py @@ -19,6 +19,7 @@ from PyQt5.QtWidgets import ( QRadioButton, QComboBox, QFileDialog, QMessageBox, QTableView, QAction, QDateTimeEdit, QWidget, QPlainTextEdit, + QLabel, ) from PyQt5.QtCore import ( QTime, QDateTime, @@ -130,6 +131,30 @@ class ASubWindowFeatures(object): return qtype + def get_label_text(self, name:str): + """Get text of label component + + Args: + label: The label component name + + Returns: + Text + """ + return self.find(QLabel, name).text() + + def set_label_text(self, name:str, text:str): + """Set text of label component + + Args: + text_edit: The label component name + text: The text + + Returns: + Nothing + """ + self.find(QLabel, name).setText(text) + + def set_line_edit_text(self, name:str, text:str): """Set text of line edit component diff --git a/src/View/About/Window.py b/src/View/About/Window.py index 9f84ad86..2ff5f3ce 100644 --- a/src/View/About/Window.py +++ b/src/View/About/Window.py @@ -1,8 +1,28 @@ # -*- coding: utf-8 -*- +import os +import logging + from View.ASubWindow import ASubWindow +logger = logging.getLogger() + class AboutWindow(ASubWindow): def __init__(self, title="About", parent=None): super(AboutWindow, self).__init__(name=title, ui="about", parent=parent) self.ui.setWindowTitle(title) + + with open( + os.path.abspath( + os.path.join( + os.path.dirname(__file__), + "..", "..", "VERSION" + ) + ), "r" + ) as f: + version = f.readline() + logger.info(version) + + label = self.get_label_text("label_version") + label = label.replace("@version", version.strip()) + self.set_label_text("label_version", label) diff --git a/src/View/ui/about.ui b/src/View/ui/about.ui index 6b4f6957..25d11617 100644 --- a/src/View/ui/about.ui +++ b/src/View/ui/about.ui @@ -6,8 +6,8 @@ 0 0 - 362 - 98 + 553 + 262 @@ -15,44 +15,74 @@ - + - + - ressources/logoCemagref.gif - - - true + ressources/Logo-INRAE.png - - - - - - 16 - 75 - true - - - - PamHyr - - - - - - - Version en developpement: - - - - + + + + 16 + 75 + true + + + + About PAMHYR + + + + + + + © Pierre-Antoine ROUBY - INRAE -2023 + + + + + + + Version: @version + + + + + + + License: GPLv3+ + + + + + + + <a href="https://gitlab.irstea.fr/theophile.terraz/pamhyr">Source code</a> + + + Qt::RichText + + + + + + + Qt::Vertical + + + + 20 + 40 + + + diff --git a/src/View/ui/ressources/Logo-INRAE.png b/src/View/ui/ressources/Logo-INRAE.png new file mode 100644 index 0000000000000000000000000000000000000000..0cd93142e9ad2127cf167eac4acf97afed6be74b GIT binary patch literal 8635 zcmbtaRa9Kdwrwo9yEhIA?hu^d5J+Q<(=?LCx^W3E9fCIQ1Og<%B_t4nyIXKba0?JD zxINCj=iK)`-grN6f9z3Jd(F9Kt+i^5s!{um-g7lVJUTo806?gr{tN^Fpz%Jmb#Wd& zyk9t8hyeh2$}nYRJq=}LAi^DP4|BEy0DR|j^?ks}=Tve_=XS(KO0$PG>CT}5RcUH#1==#=Wqm_U-v!43zkZUEpA z!_PO!vs(TJtqKl62Oy^S*~xlW?!z1PIE?|oM8GmD*%m$;3IyomH|V1P^w9vS^*`C- z0a5?}XTJa?RzN8sVDFEH92Q`&mS`#7^4XI;vKF5d4t1PP>&NWI9Y911M+;!HR^lUbA^(_qT5dr{!?sB~S zPEsDVwYk2sX}{%s@TdFTozo$lRgUFo>8>dj9TPzEeDq-6YGY#>1JR3C?bYg3Vg{Hu z0=!(hv=CXq%{Rpx^S_Mole|%2$}7<8lVN1Q!^hv}uqkL3T#J#r7g>QX#{``{e7#%n zKLogCDP&f(6^7rsL0r8nLGfFIm`Xyf=UZ%dy^+DU@jT5C*&gnlwdPgEr||%+J*rbor!ND)--t? zG)+icOvOGNatMob6sb-8Eb9mkb!I#!D@0v1DWnLv6GicYwY$%~2)#tfG0{Su?U>J< zLMqN&;R?0T2NaIJiEdI8N(rrffia2hrSSD5GhK8~zQ?$yD6vII+B>Ilx;iG=kT35( zjB9Osc>)5XJK=wP2ndmc z;l1iM+_X-#uV_Ee)YA%NYQM+&o}SrfAUGpTpXrc6oB=lkKR$aLK$$o|mMWcUlp2(} zRcc`9VJJW4SBh^?W=LFSX%zTg)$o(vS_$qXRoPStqv5v_@yZd94=6!z^o3Pni`8w| z6_l_R8L66&R4+7u*7wlHu~790+Z}Ls*srXpKqDB*>~Tk+TWc& z@IvG&UH@;|$Y+Udf{U!Guy6d-tdpdARwDV(J?bPK@;VJd6gXx2D zW(h%29B~w_vyde8a0mt6cFKS?j2}jR|ch_aw*jbO>IGZ3_I(zWT z$BOKVF7IrYC5lyw1fB_=Q+?NYp}m_uyuGZwNBdG|kTZ@mm$OmEAqFzW>8GAg1Kd5m zhP<5-O}j-aqMapOC7nCQ4)hKM9=RuC)bF)WgJkL6>D2lzAEH0FzV#nW-Jtv3IPv-W zX<_!a?8S;Xm&qSPvfY7Y*E;;!^!*l{vImNP4$r}>ZbNIiAF@AmoS?P@EWIsFEU%lH zbU)>A=1mK_^euFmEjJIovX+*UwYwVG!I0~bLx1c4_I1nq7S<)%7Pg@2pv)lbo4o6% zSA(|+7p*IP$5cnpv8>VB(KgVUL+L_4VK`whV`gF&V~b(MVSRffKp;n{M1V_Z!t9<5 zZ=*h@zl4e`I`C$VQx4$dQkv3V2@Y{;Gfk7mBS&$TNP^(+FSU1uzTiYHt2swCFvDmw zsV@U5cpeLv^8b2Kr|;?JdCogszHV~u&>Vl1P!jv~>4M`IcW;MsM`w^TbT7Lhq@lDS z)c5s;%27I*CpkOr{+so#*)G{PYaZxZ&RHTk>sbbAp3usT#dlw+H+Mz`^L%7X#7s~D zl93r?>9z73;Xoxl0UF(n53V|l1 z(2T0qYpDJ-+u&<*w9MM7@{NiuMxWY;U&sQ~XzL3*oCq9zIar%^tG5aU86G?OEgr{% z!Y7K0m7jzei>8*O^bfjL{xSUurG%u~8Xh>NPnj77Kc-H#Do2!mth}gJZP;8jer`1t zaO&qWKmSv+eqeuBeYa@Wwfx+qwMw(uQE_Svc}Q46e-yVtZ{?!-)3d9cpQ_uG-4w= z1U{d=pXKuzVfvV;Lvf>>Yw3N!t2Mptf|1U}&f%rZ;QCXXU3I@F6Vk0-<$Q%M`LYGg z2iviQxr~;KYAyBmK?g!>P_JIG1mnE?TyEK;%k{A2wGXx*@^YWc%T8u4`kiavWI9>A zuxNHr9?g@d_WZ3~Z*|^(@^dS};;;$vhxOcMfumllLbg&?EeLVDqF!YN-?cj*+&7k~ z^!%f<`*i%^d+?QG+my%5#SFj2TfgRmo;~_{SI!>{4IGW97v5+4)INB>wHGb?6MU;~ zTIO$mVP6sd3a-1Wv1@Z#zOZhy9_=(CJ|Mz0Y*8=B5!p z*`xP26(b9Q2Mq^}OTEp^ncO!DcX}t|SJ2)MW4h;ZTLE`B0_PDY*CA3Iqz}7FT2B?Q zr#{@?(+A>i2T-(y+t>j$Tp$j1AUlYypIg733;=+k2{QnDf_1c|p>P*|$X_=6zAlId zGyotY?~8yyo$Ne;Hg*m$S6SABZ>_9An5`_Uv6zma4no=PB~0Dl-A>>CxdGJQ2`XjF zDlZ3=@s)lcaIy1*0DWDYT|K0IWm*5lEB(;^Ygm94_%9PrCt22iivsKD0hQtIc0e(H zaXzS!s4!4MieE@vP)b;o7bq+!Bq1OuAs{5eCnzK>C@w7`1^oMAeemXPYcCCYruw(9 zhn_6!OHWUPw19w*j}O0(2tVB2K|n}KN=iUbSU^~q@4+ji!S)ZsGdmBc zI}G6ogS!I%VuaYhy*y=EAC&%k3N8p8o&ONKdi))zhmZ;QLJ$H%{DJ~5E`QDIU)CO; zAiMvT@xNMo82BOV1VDBka4&c0Lq6=;{sBM4?*Df5m*ImN>1S}Lmy4aNr^Yi`)`t;( zTbQl1q@b|GGeHpv6%jEhAt4nhNr{JAi$|!aZKX5x|F&%R{y#f!xM0S6jG`2hU&O{adY_JIve8 zR@EKu0{mBeq+$Oo}Z!2*93!2c+Se}*2a?62m3%KM@7p9Ny)`mie8AIhI| zzhMRdAaBrkrfA?hzh{A+L8(GkX+fo^r$EZ_I1G0*$3v1ln(5=meEjmANfC%7`6B}0 zrU-*gLo!Av7TX7!k%%1%0}9d?B$!wPA$Xi5w);yZT!X(~UH>#V?V7nipX$YK%G=r5 zsVp()5Dllz^?n?gNguCcKDVzhD zMt3zorlct#E-^XKdyr0>wS98SfmU(B;M(a_TT_sR%%XQpvV$+jj!K9Qj)^KCoHX** z3T2ia=d}b`*>B4#JK_F54J*J1ytyM&HpYEhmR^9(=HLE`-d{!X%vssz^5V9LH=9$N zS3-1j?6vkRy#Rey_M!58ynOX(K>V)L_F07dbrzCHe6o8?5jlTNvk+0j_BK2Veb57$ zCn_q(+hfUTYt-g17rdk`G`c__Yqy<^W9jSB4Q_RsWM3V&cq<{gUF~=;_k9ek%mxMS zYs&kcVy->c7VMl)-wLi1S5D=$J#ssQv%mfrBCvOf{Au66 zOQB3iCVG#z(%?eqlAga60hs6=vrY5A!t5${d>2{ZL7)S9)8tVj!n+@|oKNI7BA6q#!SgW2A(??_IReDaH5G*k$IGCrd5LQ3ZN z858uFCs*9PZ%IyMv0sm6Bk#yRomb=giC6X#dT|>eKNlC^GgL)UdUK7MAj}E2rpG#( ztmC)IzB_z-lR3pN^pn}5|C3WLRGCgdXBq8l(v6=qLl|}rRw|M|dakLF*3ofA+D#w- zXa#w)))A2d@qN6~q+qK!XafcNUbM%nb&*MQX`_GXe%Xi$PJrueD_Sy4rr|C!U(@@i z7azZafZGa?jZg1Lv=+M@6((QmSS}_Kwq1J%bd6$o{lYu$z^3E!4OZv~<9e~K@I>b@ zeChdkFQ1gHJeaL7CO@8RBkkNrrOOGgVl^veFYyXwDBDkfZ#A~d5FEt;L|aTI^AZf- z=gC5#VKxzoc=|`5^%}4Hk;Ftp&>ZOI$B$lv(SL#Kqka=snS8($Y*!L{bDXkI7-7wu z{%cc1l_$7Aap=;CR0KPq#vg~Hz{?~s{7*=JD;3pN8>KL#A;jROE76KXBuY=H5h zniMxM(+}@ns&}k@osvETuaW8itIOM^hdET7>i3&wM5`yl1dnJp{swfwZG((-#9!kJ z1fbThB$Rtma;}eHeAlK~W(5iZdU`^T-Q;xd<7YUdZtQdQCKZBzVhe&cbu?Ryu2&%VD-XW5|H;9Ot zQRc}ALe3vw5l{<0SteKZNix1&aau7q2vaeonVwI%5eB+-(w957erS4rj^enC4yj7O zSdwYmRaUB_Y&`r_FxZb@$JF;8gT5i9Sf@4Q>arXPE+guJ#E*izSuOQ-Ao3A;dn6M9 zW}uK%bQ&j`U$o1oiTyRrk-PZ}|1LDoTAxV=QI#j>A7?XdUWBI%^$pp<%y zBgU4{D%2+4f@U+xZ}Jq1*H@tVKb*5AC>MmJAJTInL~~Y8kZ3bfXg>Qx9OUzsKuWj; zki;|1CIBo}{8*`xm_gReq=l1#;hcMFt9!k;by2h3*FM2UmAl<*NSm>$S2AYGX{rYCMm#XPd+7ogld z-&jL!qgX=eE%L80GG$5WHDJ^cM?0A2g1AQX9;(5VnLs1s%P&uW2z)_pnRRnpTJYLM zr%1FLn?P*Y3>D7TrotcBjN8~4Qg<^bdAuiAsFe20aaCqxb_TEkD*3O+g+E}G2`T)fAesU}VKN&S=BLU*pI;&z$r&+(p>c>iB!^o3*s`HFuf8?whJITBWVRXb;nH7M3 zBr=-5cv@6Z9JZ^FyPzbA%}%DpK!(#nQ2TTC=S@L6`sd0n2!U#&bjasI0&lVVX%-Cv zeAQM7inYXxuW#0*9`6;=T$?C(C}}Wg&<)m`7_>2if8iy=H1+$J^-M{}vfdfp1Z(`9 zcNQx9`mW8eGb10}{?j019y=0ip&!Pcu<N_mQ(ROu|I~SKUR$JFY;44-(&mOzDk5e?!v+ipTXi*zRkQwav<_@HE&4RoMBbJo z8pq-uDFlT0zFGE9LQ-?b&R8M@*4J*y+Wb5GLVfE9DQ5tk)DF*Rc1kPF2bzcPXSA}$ zn_EH64ThJe+(!BCAA17jo2nvo-Ch9ven=h#>TTzLV!O1u&$GhedD zBWfyxCpl<+U*=c7H?qVq1mfWyY-boCu>>OC|DO7SypnD)z~7E{|6DMK|@!fR7~HR;R?GYvg5V+xqpYJ))u$lBuo)3T+{kE?fwbtXBPu}v5I~yh4YbSuj zDHZVNhB~g;K2oXRyBLV`afC{75fV7z?htHqlT0ri(LTxOr}uYLm`N`Uuddgoj7>(` z<~w;1RfU#VFyYqDph3z4y1zYT0+= zJZ_%Sfq@w7en}Fa`jB%s49OV2Z zG_gL^@l)RP(?wKM-L_l!mGy>c%JL~3?fhvoHx`yBJ7~@N8snW(FerF16$H|sNUi31 z6wr(Pq5g1e&Zz2GXj*flnI*TGgJGeJNTidX{Zv@0df^azjmO&KxzJzOzMR;#pX*AGfyV!~{<)&({<)?^LlF*q1JGT2x|Fte3e(zH!IjpK$| z^N9lXG+bIj>_>GY)_O0a#uLKc6qFHttV$Z$Oa4AkJ@#cssrw@SW|g59qkm0SsWIJv z@fm8PFl|#X;n>)(4{Lp)B6nkHDQf&WqU#Hr$=+BFb}wE}{^oR%=(nR6rCv=S&D|7~ zLwD%>ELTBOAE;ZlipAs&wY8RTJ<1Ck#&k4?m20Gis#o3Ck zSwsszSub`yZ2z^s4^;!F^AwM-W}K=W!AT(w7VX$=#Ld0ghHQ~}bcY@*`C4mldcb*u zh3r+@dKQ`yKX93ZXElSP5u(8t7!a8itju`iFo136I|KPeh zG^awCd_pOv;wD5BT6LJ{-*s#btY`)@#N?Y!M!)UYm5t;0@{!%Q4yD%ldP}KAz!~uY zzc-%kaeQgEAPKYX@jx`Jaud+o43nFlzSi249xfPF$3{d56Og|or|V%mt%nbx#K;cs1fbP z&6IAO;mdL$XFGFlSTu(Z(WBWHu1oe<=!$ToSZruR*Kv*}s51I>q_!%$Fji#($|Utj z<`@3kmC%Qcc$;5Dryvg!V+S{k9Q)2l{Eq=?&rmi=!I3I>4{!`t!ic+LgDbs{q?f%!9 z4_|&-#``DYt1*wj8Q2+y&~xbk3<#cEG%e;QrGEN2htFv)bu{?X&ANHRJq6;+``Cxx0^RzsErD?8Mfdi+N z^LJ>+$B@BmSxX*HC9(Y%R1nFsz?9xX@aX5 zBbuGZ4ziWCtnwMYiN;A!V$8`8-&^W59(Nql$SFk{OMcW_+!ad8=u~w|dZkMLi9L(& z@`gN3+yw?0_RG5^d^pLn9D}BA(w1POzk-O3Ze2a==HUAR?zo1LqD)?zL54uH`;~d&)|}llM?YB8*qGK?aF3UnL1u~wB{}Iz~CLB zKC7tI?gEJp5Crxy!zo%K+UZ#yJBbvAPsU8<$ZHKObK80(djFgvfi*Rq z&R(n>#oX9az%=&Fwb~46>TBLlAiUv#C)GfwA*dN^6sv;RK>7uRGt5GGenKT^>uuHBRPf&|LPb}b4f>TZ3FJi(MGMh9amC$=JeI$o~9aF zS|JF^zWCmkn?2eEQH6OftY5U^b$hLW*0k9+3SOP$Vck(3x#9R-$hE)1jbtJg_H4DS zhJrtb&Og`sAzY3;>e2y3^ce;{`e7<=XkIVOxf}iyEz4S0UYmYcP|wWK5&e9;4CyWS zC+QD*JY=dzdqU0s1F11j?_2e}SBq($k#tKUHg$4zuu-^A{?58eDshpm0h5Vp9-l|> z1jo!%WGV(Xt;{fAr=!AbFM0Hl*x;zbuL)6TMeN+w%gyk+7&W{M1^F}(SC{WnTUXe? z2Z?#>%6Nz!b}3cPW?Fk=%GAR(#ej;6woYNxxR6=)oMsP8s`wITRmZm5dUsJb7LK}# z*3}3vsc9$_?6tc<++YVLJVnIF^g3$}HM1quv1 z%O7iE@!_s~eF3u(T=Ee(K9(*EYapdb69rGehuL9JE%wzQrtwFZpC-EOFDWCpBLDD< zD*T+&>-O#Xmddk7E8mj=DR??8*?pl(wG}q|HMxIKJme}aXGE9Jl3D!c!ewVT`=LlD zYESd!g*rQ=l8fePI^Jm4Xn-Q{c$(aK42u-rMc5atQ()B>{EB1eTgK=)KE7}IegxT- z#Lbjdx(xJ_Re;)&>kJZeO}vBn#QaV~z0O_($5PeTMZ(sx=ep|Z(!9d~E+_I-kS7AJ nU0v*Fkb3^-^m+-C29U;?tG)Il@!{_U06;_K`LjwT>#+X<5{Uoq literal 0 HcmV?d00001 From 0a87261d94484c1946bacbbcbe7e86243a824cf6 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 28 Jul 2023 10:54:17 +0200 Subject: [PATCH 07/64] MainWindow: Diable unused help action. --- src/View/ui/MainWindow.ui | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/View/ui/MainWindow.ui b/src/View/ui/MainWindow.ui index 6913d02a..217bd2b4 100644 --- a/src/View/ui/MainWindow.ui +++ b/src/View/ui/MainWindow.ui @@ -627,11 +627,17 @@ + + false + Help PAMHYR + + false + Help MAGE From 02394cc2265d4aec31a47d50854822c11daf6704 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 28 Jul 2023 11:14:18 +0200 Subject: [PATCH 08/64] Trans: Update french translate. --- src/View/ui/about.ui | 3 + src/lang/fr.ts | 156 ++++++++++++++++++++++--------------------- 2 files changed, 84 insertions(+), 75 deletions(-) diff --git a/src/View/ui/about.ui b/src/View/ui/about.ui index 25d11617..7d9ab7b6 100644 --- a/src/View/ui/about.ui +++ b/src/View/ui/about.ui @@ -13,6 +13,9 @@ Form + + + diff --git a/src/lang/fr.ts b/src/lang/fr.ts index 9eabd6ef..63008b40 100644 --- a/src/lang/fr.ts +++ b/src/lang/fr.ts @@ -1,5 +1,6 @@ - + + BoundaryCondition @@ -83,14 +84,9 @@ Nœud - - Discharge (m³/s) - Débit (m³/s) - - Discharge (m³/s) - + Débit (m³/s) @@ -276,7 +272,7 @@ Stricklers - + Stricklers @@ -454,16 +450,6 @@ Form - - - PamHyr - - - - - Version en developpement: - - dd/MM/yyyy HH:mm:ss @@ -472,13 +458,38 @@ days - jours + jours HH:mm:ss + + + About PAMHYR + À propos de PAMHYR + + + + © Pierre-Antoine ROUBY - INRAE -2023 + + + + + Version: @version + + + + + License: GPLv3+ + Licence: GPLv3+ + + + + <a href="https://gitlab.irstea.fr/theophile.terraz/pamhyr">Source code</a> + <a href="https://gitlab.irstea.fr/theophile.terraz/pamhyr">Code source</a> + Frictions @@ -659,14 +670,9 @@ Hauteur (m) - - Discharge (m³/s) - Débit (m³/s) - - Discharge (m³/s) - + Débit (m³/s) @@ -1371,28 +1377,28 @@ Define initial conditions Définire les conditions initiales - + Édition des Tronçons - + Ouvrir une étude - + Enrégistrer étude en cours (Ctrl+S) - + Fermer étude en cours (Ctrl+F) - + MainWindowProfile @@ -1466,101 +1472,101 @@ Cote (m) - + Suppression les lignes incomplètes - + Supprimer les lignes des cellules non renseignées ? - + Suppression des noms répétés - + Etes-vous sûr de vouloir quitter ? - + Insérer un point - + Supprimer le/les point(s) sélectionnés - + Trier les points par ordre décroissant de X - + Trier les points par ordre décroissant de Y - + Décaler le point sélectionné vers le haut - + Décaler le point sélectionné vers le bas - + Exporter (dans un fichier) les points du profil au format tabulé - + Copier la sélection au format tabulé - + Coller la sélection depuis le presse-papier au format tabulé - + Vérifier la validité de la saisie et garder ou pas les modifications apportées - + Annuler toutes les modifications depuis la dernière validation - + Annuler toutes les modifications et revenir à l'état initial - + Ligne d'eau : - Z : Cote (m) - A : Aire mouillée (mu00B2) - p : Périmètre mouillé (m) - L : Largeur au miroir (m) + Z : Cote (m) + A : Aire mouillée (mu00B2) + p : Périmètre mouillé (m) + L : Largeur au miroir (m) - + 'Maj + Clic' : Ligne d'eau & 'Ctrl + Clic' : Sélectionner des points - + Abscisse en travers calculée en projétant les points sur le plan défini par les deux points nommés extrêmes @@ -1720,98 +1726,98 @@ Ordre des sections : Amont --> Aval Discharge (m^3/s) Débit (m³/s) - + Choisissez un nom de fichier à sauvegarder - + Édition des profils sélectionnés - + Vous avez sélectionné plus de 5 profils. Seuls les 5 premiers seront édités. - + Profil N° : - + Profil précédent - + Profil sélectionné - + Importer une géométrie - + Supprimer le profil sélectionné - + Éditer le profil sélectionné - + Copier le profil sélectionné - + Coller le profil en fin de liste (penser à modifier le Pk avant de trier) - + Dupliquer la section sélectionnée - + Trier les profils par ordre décroissant des Pk - + Changer l'ordre des profils (en décalant le profil sélectionné vers le haut) - + Changer l'ordre des profils (en décalant le profil sélectionné vers le bas) - + Terminer l'édition - + Vue isométrique (Alt+Z) - + Vue isométrique (Alt+E) - + Vue isométrique (Alt+R) @@ -2058,17 +2064,17 @@ Seuls les 5 premiers seront édités. Enregistrer la figure - + Retour à la vue précédente - + Passer à la vue suivante - + Vue isométrique (Shift+W) From a5a712d6ad7f66c77cce2cfbf74cbfef29cd8e48 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 31 Jul 2023 10:17:44 +0200 Subject: [PATCH 09/64] About: Add AUTHORS files and authors list into about window. --- AUTHORS | 3 +++ packages/linux.sh | 1 + packages/windows.bat | 1 + src/AUTHORS | 1 + src/View/About/Window.py | 36 +++++++++++++++++++++++++++--------- src/View/ui/about.ui | 2 +- 6 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 AUTHORS create mode 120000 src/AUTHORS diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..0ce9cdac --- /dev/null +++ b/AUTHORS @@ -0,0 +1,3 @@ +Sylvain COULIBALY, INRAE, 2020 - 2022 +Théophile TERRAZ, INRAE, 2022 - 2023 +Pierre-Antoine ROUBY, INRAE, 2023 \ No newline at end of file diff --git a/packages/linux.sh b/packages/linux.sh index 9924eb0b..938e4ff9 100755 --- a/packages/linux.sh +++ b/packages/linux.sh @@ -36,6 +36,7 @@ mkdir -p dist/pamhyr/lang cp -r ../src/lang/*.qm dist/pamhyr/lang/ cp ../VERSION dist/pamhyr/ +cp ../AUTHORS dist/pamhyr/ echo " *** MAKE SRC PACKAGE" diff --git a/packages/windows.bat b/packages/windows.bat index c5d150df..84d55613 100644 --- a/packages/windows.bat +++ b/packages/windows.bat @@ -16,6 +16,7 @@ copy /y ..\src\View\ui\Widgets\*.ui dist\pamhyr\View\ui\Widgets copy /y ..\src\View\ui\*.ui dist\pamhyr\View\ui\ copy /y ..\src\lang\*.qm dist\pamhyr\lang\ copy /y ..\VERSION dist\pamhyr\ +copy /y ..\AUTHORS dist\pamhyr\ rem Make installer "C:\Program Files (x86)\NSIS\makensis.exe" pamhyr.nsi diff --git a/src/AUTHORS b/src/AUTHORS new file mode 120000 index 00000000..9eadf712 --- /dev/null +++ b/src/AUTHORS @@ -0,0 +1 @@ +../AUTHORS \ No newline at end of file diff --git a/src/View/About/Window.py b/src/View/About/Window.py index 2ff5f3ce..a1784509 100644 --- a/src/View/About/Window.py +++ b/src/View/About/Window.py @@ -5,24 +5,42 @@ import logging from View.ASubWindow import ASubWindow +from PyQt5.QtCore import QCoreApplication + +_translate = QCoreApplication.translate logger = logging.getLogger() class AboutWindow(ASubWindow): + def _path_file(self, filename): + return os.path.abspath( + os.path.join( + os.path.dirname(__file__), + "..", "..", filename + ) + ) + + def __init__(self, title="About", parent=None): super(AboutWindow, self).__init__(name=title, ui="about", parent=parent) self.ui.setWindowTitle(title) - with open( - os.path.abspath( - os.path.join( - os.path.dirname(__file__), - "..", "..", "VERSION" - ) - ), "r" - ) as f: + # Version + with open(self._path_file("VERSION"), "r") as f: version = f.readline() - logger.info(version) + logger.info(f"version: {version}") label = self.get_label_text("label_version") label = label.replace("@version", version.strip()) self.set_label_text("label_version", label) + + # Authors + with open(self._path_file("AUTHORS"), "r") as f: + label = "" + try: + while True: + author = next(f).strip() + logger.info(f"author: {author}") + label = f"\n © {author}" + label + except StopIteration: + label = _translate("About", "Contributors: ") + label + self.set_label_text("label_copyright", label) diff --git a/src/View/ui/about.ui b/src/View/ui/about.ui index 7d9ab7b6..579e0095 100644 --- a/src/View/ui/about.ui +++ b/src/View/ui/about.ui @@ -46,7 +46,7 @@ - © Pierre-Antoine ROUBY - INRAE -2023 + ... From 5f0a915ac6d20325fec678ce1331c2cb8ca93252 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 31 Jul 2023 10:29:02 +0200 Subject: [PATCH 10/64] Network: Draw reach as black color when is current reach. --- src/View/Network/GraphWidget.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/View/Network/GraphWidget.py b/src/View/Network/GraphWidget.py index 2569497a..737ca6ba 100644 --- a/src/View/Network/GraphWidget.py +++ b/src/View/Network/GraphWidget.py @@ -158,7 +158,7 @@ class EdgeItem(QGraphicsItem): if self.graph.selected_item() == self: color = Qt.red elif self.graph.current_edge() == self: - color = Qt.blue + color = Qt.black elif not self.graph.graph.is_enable_edge(self.edge): color = Qt.darkGray From 75dba77dec09b37a9e201af4ae9e3fee073a1643 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 31 Jul 2023 10:30:58 +0200 Subject: [PATCH 11/64] Trans: Minor change. --- src/lang/fr.ts | 116 ++++++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 54 deletions(-) diff --git a/src/lang/fr.ts b/src/lang/fr.ts index 63008b40..07808a3c 100644 --- a/src/lang/fr.ts +++ b/src/lang/fr.ts @@ -1,6 +1,14 @@ + + About + + + Contributors: + Contributeurs : + + BoundaryCondition @@ -466,30 +474,30 @@ - + About PAMHYR À propos de PAMHYR - - © Pierre-Antoine ROUBY - INRAE -2023 - - - - + Version: @version - + License: GPLv3+ Licence: GPLv3+ - + <a href="https://gitlab.irstea.fr/theophile.terraz/pamhyr">Source code</a> <a href="https://gitlab.irstea.fr/theophile.terraz/pamhyr">Code source</a> + + + ... + + Frictions @@ -788,7 +796,7 @@ Fermer - + Close current study Fermer l'étude en cours @@ -828,7 +836,7 @@ Configuration de PAMHYR - + Quit Quitter @@ -838,7 +846,7 @@ - + Edit river network Éditer le réseau @@ -908,7 +916,7 @@ Condition aux limites et apports ponctuels - + Initial conditions Conditions initiales @@ -943,7 +951,7 @@ Éditer les ouvrages - + Run solver Lancer un solver @@ -988,32 +996,32 @@ Cartographier le bief sélectionné - + Help PAMHYR Aide de PAMHYR - + Help MAGE Aide de MAGE - + About A propos - + ouvrir - + Save current study Sauvegarder l'étude - + Ctrl+F @@ -1023,132 +1031,132 @@ Quitter l'application - + Ctrl+Q - + stop solver - + Interrompt la simulation en cours - + Ctrl+C - + Run external meshing tool Lancer le mailler externe - + Run meshing tool on current reach geometry Lancer le mailler externe sur le bief selectionné - + Display simulation listing - + Display current simulation listing - + River network Réseau - + Geometry Géométrie - + Edit reach geometry Éditer la géométrie - + Mesh Maillage - + Boundary conditions Conditions aux limites - + Edit boundary conditions and one-time contributions Éditer les conditions aux limites et les apports ponctuels - + Lateral contribution Contributions latérales - + Edit lateral contribution Éditer les contributions latérales - + Spills - + Edit lateral spills - + Friction Frottements - + Stricklers - + Edit the study stricklers Éditer les Stricklers de l'étude - + Building Ouvrages - + Edit building (valve, ...), singularity and pump Éditer les ouvrages - + Edit study Éditer l'étude - + English - + French @@ -1353,27 +1361,27 @@ Trier les points des conditions aux limites - + Quit the application (Ctrl+Q) - + Run a solver Lancer un solver - + Display meshed reach - + Edit friction frictions Éditer les frottements - + Define initial conditions Définire les conditions initiales @@ -1383,17 +1391,17 @@ - + Ouvrir une étude - + Enrégistrer étude en cours (Ctrl+S) - + Fermer étude en cours (Ctrl+F) From e4df36b5f3fc06c4fa3ba00c6902aba12b3ada64 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 31 Jul 2023 10:40:30 +0200 Subject: [PATCH 12/64] About: Minor change. --- src/View/About/Window.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/View/About/Window.py b/src/View/About/Window.py index a1784509..f4a98121 100644 --- a/src/View/About/Window.py +++ b/src/View/About/Window.py @@ -26,11 +26,11 @@ class AboutWindow(ASubWindow): # Version with open(self._path_file("VERSION"), "r") as f: - version = f.readline() + version = f.readline().strip() logger.info(f"version: {version}") label = self.get_label_text("label_version") - label = label.replace("@version", version.strip()) + label = label.replace("@version", version) self.set_label_text("label_version", label) # Authors From 61f0ba7b1827a3c5882da32c1179f1208071e190 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 31 Jul 2023 10:40:41 +0200 Subject: [PATCH 13/64] Packages: wine: Add version/authors files copy. --- packages/wine.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/wine.sh b/packages/wine.sh index 1a769f51..07c43b6b 100755 --- a/packages/wine.sh +++ b/packages/wine.sh @@ -70,6 +70,9 @@ cp -r ../src/View/ui/ressources/ dist/pamhyr/View/ui/ 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/ +cp ../AUTHORS dist/pamhyr/ + # Update TS and build QM files OLD_PWD=$PWD cd ../src/lang/ From 334e7b58222fdcbb21d8d52d192d2d3ee399a49a Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 31 Jul 2023 10:43:50 +0200 Subject: [PATCH 14/64] Network: Remove "enable" column from reach table. --- src/View/Network/Table.py | 12 ++++++------ src/View/Network/Window.py | 7 ++++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/View/Network/Table.py b/src/View/Network/Table.py index a8254745..4dad50f5 100644 --- a/src/View/Network/Table.py +++ b/src/View/Network/Table.py @@ -148,12 +148,12 @@ class GraphTableModel(QAbstractTableModel): node ) ) - elif self.headers[index.column()] == "enable": - self._undo.push( - EnableEdgeCommand( - self.rows[index.row()], value - ) - ) + # elif self.headers[index.column()] == "enable": + # self._undo.push( + # EnableEdgeCommand( + # self.rows[index.row()], value + # ) + # ) else: self._undo.push( SetCommand( diff --git a/src/View/Network/Window.py b/src/View/Network/Window.py index 8fdf3988..19a5d856 100644 --- a/src/View/Network/Window.py +++ b/src/View/Network/Window.py @@ -71,7 +71,8 @@ class NetworkWindow(ASubMainWindow): # Edges table self._reachs_model = GraphTableModel( - headers = ["name", "enable", "node1", "node2"], + headers = ["name", # "enable", + "node1", "node2"], graph = self._graph, rows_type = "edges", undo = self._undo_stack, @@ -86,9 +87,9 @@ class NetworkWindow(ASubMainWindow): table = self.find(QTableView, "tableView_reachs") table.setModel(self._reachs_model) - table.setItemDelegateForColumn(1, self.delegate_true_false_combobox) + # table.setItemDelegateForColumn(1, self.delegate_true_false_combobox) + table.setItemDelegateForColumn(1, self.delegate_combobox) table.setItemDelegateForColumn(2, self.delegate_combobox) - table.setItemDelegateForColumn(3, self.delegate_combobox) table.setSelectionBehavior(QAbstractItemView.SelectRows) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) #table.resizeColumnsToContents() From a3f3fca6b629dacea4791ce9350868ec66ac8023 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 31 Jul 2023 11:05:11 +0200 Subject: [PATCH 15/64] tools: ssh: Minor change on ssh run tool script. --- tools/ssh-run.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/ssh-run.sh b/tools/ssh-run.sh index 9c59bb9f..a7ca1af7 100755 --- a/tools/ssh-run.sh +++ b/tools/ssh-run.sh @@ -1,10 +1,14 @@ #! /bin/sh -# > ssh-run.sh SERVER DESTDIR SOLVER INPUT +# > ssh-run.sh SERVER DESTDIR SOLVER ARGS INPUT # First argument is the server name/addr # The second argument is the destination directory to copy input data # The third argument is the solver path -# The fourth argument is the input name +# The fourth argument is an solver args separate by ',' or input name +# The sixth argument is the input name or nothing -ssh $1 "cd $2; $3 $4" +args=$(echo $4 | tr ',' ' ') + +echo "ssh $1 \"cd $2; $3 $args $5\"" +ssh $1 "cd $2; $3 $args $5" From 216bb3dd4cad484c08f048891de017592bb04b01 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 31 Jul 2023 11:25:06 +0200 Subject: [PATCH 16/64] git: Add submodule mage. --- .gitlab-ci.yml | 23 +++++++++++++++++++++++ .gitmodules | 3 +++ mage | 1 + packages/linux.sh | 4 ++++ 4 files changed, 31 insertions(+) create mode 100644 .gitmodules create mode 160000 mage diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 014dde47..183337a4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,6 +8,27 @@ stages: # BUILD # ######### +build-mage: + stage: build + tags: + - linux + rules: + - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG + variables: + GIT_SUBMODULE_STRATEGY: recursive + GIT_SUBMODULE_DEPTH: 1 + script: + - cd mage/src/ + - mkdir -p build + - cd build + - cmake .. + - make + artifacts: + paths: + - mage/src/build/mage + - mage/src/build/mage_extraire + - mage/src/build/mailleurPF + build: stage: build tags: @@ -53,6 +74,8 @@ linux-package: artifacts: true - job: build artifacts: true + - job: build-mage + artifacts: true rules: - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG artifacts: diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..0aad7c1d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "mage"] + path = mage + url = https://gitlab.irstea.fr/jean-baptiste.faure/mage.git diff --git a/mage b/mage new file mode 160000 index 00000000..18aa9a7e --- /dev/null +++ b/mage @@ -0,0 +1 @@ +Subproject commit 18aa9a7e0f8415a94a40fe647d329268c6932663 diff --git a/packages/linux.sh b/packages/linux.sh index 938e4ff9..899aa4b8 100755 --- a/packages/linux.sh +++ b/packages/linux.sh @@ -38,6 +38,10 @@ cp -r ../src/lang/*.qm dist/pamhyr/lang/ cp ../VERSION dist/pamhyr/ cp ../AUTHORS dist/pamhyr/ +cp ../mage/src/build/mage dist/pamhyr/ +cp ../mage/src/build/mage_extraire dist/pamhyr/ +cp ../mage/src/build/mailleurPF dist/pamhyr/ + echo " *** MAKE SRC PACKAGE" OLD_PWD=$PWD From 099ed29d0675a2d50e39e3d97a4a61ac11a5dbde Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 31 Jul 2023 15:16:19 +0200 Subject: [PATCH 17/64] ci: Add MAGE build for windows. --- .gitlab-ci.yml | 31 +++++++++++++++++++++++++++++-- packages/windows.bat | 10 ++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 183337a4..87578db8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,7 +8,7 @@ stages: # BUILD # ######### -build-mage: +build-mage-linux: stage: build tags: - linux @@ -29,6 +29,31 @@ build-mage: - mage/src/build/mage_extraire - mage/src/build/mailleurPF +build-mage-windows: + stage: build + tags: + - wine + rules: + - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG + variables: + GIT_SUBMODULE_STRATEGY: recursive + GIT_SUBMODULE_DEPTH: 1 + script: + - cd mage/src/ + - sed s/add_compile_definitions(win)/add_compile_definitions(windows)/ CMakeLists.txt > __tmp__ + - echo set(CMAKE_Fortran_COMPILER "C:/Program\ Files/gcc/bin/gfortran.exe") > CMakeLists.txt + - echo set(CMAKE_MAKE_PROGRAM "C:/Program Files\ \(x86\)/GnuWin32/bin/make.exe") >> CMakeLists.txt + - type __tmp__ >> CMakeLists.txt + - mkdir build + - cd build + - cmake -G "MinGW Makefiles" .. + - make + artifacts: + paths: + - mage/src/build/mage.exe + - mage/src/build/mage_extraire.exe + - mage/src/build/mailleurPF.exe + build: stage: build tags: @@ -74,7 +99,7 @@ linux-package: artifacts: true - job: build artifacts: true - - job: build-mage + - job: build-mage-linux artifacts: true rules: - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG @@ -95,6 +120,8 @@ windows-package: artifacts: true - job: build artifacts: true + - job: build-mage-windows + artifacts: true rules: - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG artifacts: diff --git a/packages/windows.bat b/packages/windows.bat index 84d55613..453b0d03 100644 --- a/packages/windows.bat +++ b/packages/windows.bat @@ -11,12 +11,22 @@ rem Copy data mkdir dist\pamhyr\View\ui\ressources mkdir dist\pamhyr\View\ui\Widgets +rem UI copy /y ..\src\View\ui\ressources\ dist\pamhyr\View\ui\ressources copy /y ..\src\View\ui\Widgets\*.ui dist\pamhyr\View\ui\Widgets copy /y ..\src\View\ui\*.ui dist\pamhyr\View\ui\ + +rem Lang copy /y ..\src\lang\*.qm dist\pamhyr\lang\ + +rem Information copy /y ..\VERSION dist\pamhyr\ copy /y ..\AUTHORS dist\pamhyr\ +rem MAGE +copy /y ..\mage\src\build\mage.exe dist\pamhyr\ +copy /y ..\mage\src\build\mage_extraire.exe dist\pamhyr\ +copy /y ..\mage\src\build\mailleurPF.exe dist\pamhyr\ + rem Make installer "C:\Program Files (x86)\NSIS\makensis.exe" pamhyr.nsi From 3d4750217975be847eb4f5eb3a2059566b2fb010 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 1 Aug 2023 11:08:28 +0200 Subject: [PATCH 18/64] ci: Disable mage build for windows. --- .gitlab-ci.yml | 54 ++++++++++++++++++++++---------------------- packages/windows.bat | 6 ++--- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 87578db8..2cbfbd42 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,7 +16,7 @@ build-mage-linux: - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG variables: GIT_SUBMODULE_STRATEGY: recursive - GIT_SUBMODULE_DEPTH: 1 + GIT_SUBMODULE_DEPTH: 20 script: - cd mage/src/ - mkdir -p build @@ -29,30 +29,30 @@ build-mage-linux: - mage/src/build/mage_extraire - mage/src/build/mailleurPF -build-mage-windows: - stage: build - tags: - - wine - rules: - - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG - variables: - GIT_SUBMODULE_STRATEGY: recursive - GIT_SUBMODULE_DEPTH: 1 - script: - - cd mage/src/ - - sed s/add_compile_definitions(win)/add_compile_definitions(windows)/ CMakeLists.txt > __tmp__ - - echo set(CMAKE_Fortran_COMPILER "C:/Program\ Files/gcc/bin/gfortran.exe") > CMakeLists.txt - - echo set(CMAKE_MAKE_PROGRAM "C:/Program Files\ \(x86\)/GnuWin32/bin/make.exe") >> CMakeLists.txt - - type __tmp__ >> CMakeLists.txt - - mkdir build - - cd build - - cmake -G "MinGW Makefiles" .. - - make - artifacts: - paths: - - mage/src/build/mage.exe - - mage/src/build/mage_extraire.exe - - mage/src/build/mailleurPF.exe +# build-mage-windows: +# stage: build +# tags: +# - wine +# rules: +# - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG +# variables: +# GIT_SUBMODULE_STRATEGY: recursive +# GIT_SUBMODULE_DEPTH: 20 +# script: +# - cd mage/src/ +# - sed s/add_compile_definitions(win)/add_compile_definitions(windows)/ CMakeLists.txt > __tmp__ +# - echo set(CMAKE_Fortran_COMPILER "C:/Program\ Files/gcc/bin/gfortran.exe") > CMakeLists.txt +# - echo set(CMAKE_MAKE_PROGRAM "C:/Program Files\ \(x86\)/GnuWin32/bin/make.exe") >> CMakeLists.txt +# - type __tmp__ >> CMakeLists.txt +# - mkdir build +# - cd build +# - cmake -G "MinGW Makefiles" .. +# - make +# artifacts: +# paths: +# - mage/src/build/mage.exe +# - mage/src/build/mage_extraire.exe +# - mage/src/build/mailleurPF.exe build: stage: build @@ -120,8 +120,8 @@ windows-package: artifacts: true - job: build artifacts: true - - job: build-mage-windows - artifacts: true + # - job: build-mage-windows + # artifacts: true rules: - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG artifacts: diff --git a/packages/windows.bat b/packages/windows.bat index 453b0d03..0b276812 100644 --- a/packages/windows.bat +++ b/packages/windows.bat @@ -24,9 +24,9 @@ copy /y ..\VERSION dist\pamhyr\ copy /y ..\AUTHORS dist\pamhyr\ rem MAGE -copy /y ..\mage\src\build\mage.exe dist\pamhyr\ -copy /y ..\mage\src\build\mage_extraire.exe dist\pamhyr\ -copy /y ..\mage\src\build\mailleurPF.exe dist\pamhyr\ +rem copy /y ..\mage\src\build\mage.exe dist\pamhyr\ +rem copy /y ..\mage\src\build\mage_extraire.exe dist\pamhyr\ +rem copy /y ..\mage\src\build\mailleurPF.exe dist\pamhyr\ rem Make installer "C:\Program Files (x86)\NSIS\makensis.exe" pamhyr.nsi From a8c68ba575ae4e5e4920925467dd6f7be686320f Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 1 Aug 2023 14:27:56 +0200 Subject: [PATCH 19/64] ci: Minor change. --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2cbfbd42..7c67faec 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -163,8 +163,8 @@ tag-release: - name: 'GNU/Linux amd64 (tar.xz)' url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/packages/pamhyr-gnulinux-amd64.tar.xz' filepath: '/packages/pamhyr-gnulinux-amd64.tar.xz' - link_type: 'other' + link_type: 'package' - name: 'Windows amd64 (exe)' url: '${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/raw/packages/pamhyr-win-amd64.exe' filepath: '/packages/pamhyr-win-amd64.exe' - link_type: 'other' + link_type: 'package' From 34eb3e1d53bbebed95d5a91fc6f14f0bee6db8b1 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 1 Aug 2023 16:03:33 +0200 Subject: [PATCH 20/64] LICENSE: Add LICENSE file and files headers. --- .gitlab-ci.yml | 16 + LICENSE | 674 ++++++++++++++++++ packages/linux.sh | 17 + packages/pamhyr.nsi | 7 +- packages/version.sh | 18 +- packages/windows.bat | 18 +- packages/wine.sh | 16 + src/Checker/Checker.py | 16 + src/Checker/Mage.py | 16 + src/Checker/Study.py | 16 + .../BoundaryCondition/BoundaryCondition.py | 16 + .../BoundaryConditionList.py | 16 + .../BoundaryConditionTypes.py | 16 + src/Model/DB.py | 16 + src/Model/Except.py | 16 + src/Model/Friction/Friction.py | 16 + src/Model/Friction/FrictionList.py | 16 + src/Model/Geometry/Point.py | 16 + src/Model/Geometry/PointXY.py | 16 + src/Model/Geometry/PointXYZ.py | 16 + src/Model/Geometry/Profile.py | 16 + src/Model/Geometry/ProfileXYZ.py | 16 + src/Model/Geometry/Reach.py | 16 + src/Model/Geometry/Vector_1d.py | 16 + .../InitialConditions/InitialConditions.py | 16 + .../InitialConditionsDict.py | 16 + .../LateralContribution.py | 16 + .../LateralContributionList.py | 16 + .../LateralContributionTypes.py | 16 + src/Model/Network/Edge.py | 16 + src/Model/Network/Graph.py | 16 + src/Model/Network/Node.py | 16 + src/Model/Network/Point.py | 16 + src/Model/River.py | 16 + src/Model/Saved.py | 16 + src/Model/Serializable.py | 16 + .../SolverParameters/SolverParametersList.py | 16 + src/Model/Stricklers/Stricklers.py | 16 + src/Model/Stricklers/StricklersList.py | 16 + src/Model/Study.py | 16 + src/Scripts/plot_3DST.py | 16 + src/Solver/ASolver.py | 16 + src/Solver/GenericSolver.py | 16 + src/Solver/Mage.py | 16 + src/Solver/Solvers.py | 16 + src/View/ASubWindow.py | 16 + src/View/About/Window.py | 19 +- src/View/BoundaryCondition/Edit/Plot.py | 16 + src/View/BoundaryCondition/Edit/Table.py | 16 + .../BoundaryCondition/Edit/UndoCommand.py | 16 + src/View/BoundaryCondition/Edit/Window.py | 16 + src/View/BoundaryCondition/Edit/translate.py | 16 + src/View/BoundaryCondition/Table.py | 16 + src/View/BoundaryCondition/UndoCommand.py | 16 + src/View/BoundaryCondition/Window.py | 16 + src/View/BoundaryCondition/translate.py | 16 + src/View/CheckList/Table.py | 16 + src/View/CheckList/Window.py | 16 + src/View/CheckList/Worker.py | 16 + src/View/Configure/Solver/Window.py | 16 + src/View/Configure/Window.py | 16 + src/View/Debug/Window.py | 16 + src/View/DummyWindow.py | 16 + src/View/Frictions/PlotStricklers.py | 16 + src/View/Frictions/Table.py | 16 + src/View/Frictions/UndoCommand.py | 16 + src/View/Frictions/Window.py | 16 + src/View/Frictions/translate.py | 16 + src/View/Geometry/PlotAC.py | 16 + src/View/Geometry/PlotKPC.py | 16 + src/View/Geometry/PlotXY.py | 16 + src/View/Geometry/Profile/Plot.py | 16 + src/View/Geometry/Profile/Table.py | 16 + src/View/Geometry/Profile/UndoCommand.py | 16 + src/View/Geometry/Profile/Window.py | 16 + .../Geometry/Profile/mainwindow_ui_profile.py | 16 + src/View/Geometry/Table.py | 16 + src/View/Geometry/UndoCommand.py | 16 + src/View/Geometry/Window.py | 16 + src/View/Geometry/mainwindow_ui_reach.py | 16 + src/View/InitialConditions/DialogDischarge.py | 16 + src/View/InitialConditions/DialogHeight.py | 16 + src/View/InitialConditions/PlotDKP.py | 16 + src/View/InitialConditions/PlotDischarge.py | 16 + src/View/InitialConditions/Table.py | 16 + src/View/InitialConditions/UndoCommand.py | 16 + src/View/InitialConditions/Window.py | 16 + src/View/InitialConditions/translate.py | 16 + src/View/LateralContribution/Edit/Plot.py | 16 + src/View/LateralContribution/Edit/Table.py | 16 + .../LateralContribution/Edit/UndoCommand.py | 16 + src/View/LateralContribution/Edit/Window.py | 16 + .../LateralContribution/Edit/translate.py | 16 + src/View/LateralContribution/Table.py | 16 + src/View/LateralContribution/UndoCommand.py | 16 + src/View/LateralContribution/Window.py | 16 + src/View/LateralContribution/translate.py | 16 + src/View/ListedSubWindow.py | 16 + src/View/MainWindow.py | 16 + src/View/Network/GraphWidget.py | 16 + src/View/Network/Table.py | 16 + src/View/Network/UndoCommand.py | 16 + src/View/Network/Window.py | 16 + src/View/Plot/APlot.py | 16 + src/View/Plot/MplCanvas.py | 16 + src/View/Plot/mpl_canvas_onpick_event.py | 16 + src/View/Plot/navigation_toolbar_2qt.py | 16 + src/View/RunSolver/Log/Window.py | 16 + src/View/RunSolver/Window.py | 16 + src/View/SolverParameters/Table.py | 16 + src/View/SolverParameters/UndoCommand.py | 16 + src/View/SolverParameters/Window.py | 16 + src/View/SolverParameters/translate.py | 16 + src/View/Stricklers/Table.py | 16 + src/View/Stricklers/UndoCommand.py | 16 + src/View/Stricklers/Window.py | 16 + src/View/Stricklers/translate.py | 16 + src/View/Study/Window.py | 16 + src/View/ui/ui_to_py.sh | 16 + src/config.py | 16 + src/lang/constant_string.py | 16 + src/lang/create_ts.sh | 16 + src/pamhyr.py | 25 + src/tools.py | 16 + tools/license.el | 41 ++ 125 files changed, 2687 insertions(+), 4 deletions(-) create mode 100644 LICENSE create mode 100644 tools/license.el diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7c67faec..8fc82ee9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,3 +1,19 @@ +# .gitlab-ci.yml -- Pamhyr gitlab-ci +# 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 . + stages: - build - test diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..001d0883 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + pamhyr Copyright (C) 2023 INRAE + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/packages/linux.sh b/packages/linux.sh index 899aa4b8..fb48c881 100755 --- a/packages/linux.sh +++ b/packages/linux.sh @@ -1,5 +1,21 @@ #! /bin/sh +# linux.sh -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + echo " *** RM OLD ENV" rm dist/ -rf @@ -37,6 +53,7 @@ cp -r ../src/lang/*.qm dist/pamhyr/lang/ cp ../VERSION dist/pamhyr/ cp ../AUTHORS dist/pamhyr/ +cp ../LICENSE dist/pamhyr/ cp ../mage/src/build/mage dist/pamhyr/ cp ../mage/src/build/mage_extraire dist/pamhyr/ diff --git a/packages/pamhyr.nsi b/packages/pamhyr.nsi index 35be24ad..ccd25a76 100644 --- a/packages/pamhyr.nsi +++ b/packages/pamhyr.nsi @@ -1,8 +1,12 @@ !include "x64.nsh" -Name "PAMHYR" +!define LIC_NAME "LICENSE" +!define APP_NAME "PAMHYR" +Name "PAMHYR" OutFile "pamhyr-win-amd64.exe" +LicenseData "..\LICENSE" +LicenseText "I Agree" RequestExecutionLevel admin @@ -11,6 +15,7 @@ InstallDir $PROGRAMFILES\PAMHYR InstallDirRegKey HKLM "Software\PAMHYR" "Install_Dir" +Page license Page components Page directory Page instfiles diff --git a/packages/version.sh b/packages/version.sh index aa769b83..8f5e8bcf 100755 --- a/packages/version.sh +++ b/packages/version.sh @@ -1,6 +1,22 @@ #! /bin/sh -# ./version BRANCH TAG COMMIT +# version.sh -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ./version.sh BRANCH TAG COMMIT if [ -z $2 ]; then diff --git a/packages/windows.bat b/packages/windows.bat index 0b276812..eee8394f 100644 --- a/packages/windows.bat +++ b/packages/windows.bat @@ -1,4 +1,19 @@ -rem Windows batch for pamhyr windows version building +rem windows.bat -- Pamhyr Windows batch for windows version building +rem Copyright (C) 2023 INRAE +rem +rem This program is free software: you can redistribute it and/or modify +rem it under the terms of the GNU General Public License as published by +rem the Free Software Foundation, either version 3 of the License, or +rem (at your option) any later version. +rem +rem This program is distributed in the hope that it will be useful, +rem but WITHOUT ANY WARRANTY; without even the implied warranty of +rem MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +rem GNU General Public License for more details. +rem +rem You should have received a copy of the GNU General Public License +rem along with this program. If not, see . + @ECHO ON rem Python environment @@ -22,6 +37,7 @@ copy /y ..\src\lang\*.qm dist\pamhyr\lang\ rem Information copy /y ..\VERSION dist\pamhyr\ copy /y ..\AUTHORS dist\pamhyr\ +copy /y ..\LICENSE dist\pamhyr\ rem MAGE rem copy /y ..\mage\src\build\mage.exe dist\pamhyr\ diff --git a/packages/wine.sh b/packages/wine.sh index 07c43b6b..4f794c51 100755 --- a/packages/wine.sh +++ b/packages/wine.sh @@ -1,5 +1,21 @@ #! /bin/sh +# wine.sh -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + echo " *** SETUP ENV" export WINARCH=win64 diff --git a/src/Checker/Checker.py b/src/Checker/Checker.py index 6e87a601..d10a8c4d 100644 --- a/src/Checker/Checker.py +++ b/src/Checker/Checker.py @@ -1,3 +1,19 @@ +# Checker.py -- Pamhyr abstract checker class +# 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 . + # -*- coding: utf-8 -*- from enum import Enum diff --git a/src/Checker/Mage.py b/src/Checker/Mage.py index 4e121d51..edb0c349 100644 --- a/src/Checker/Mage.py +++ b/src/Checker/Mage.py @@ -1,3 +1,19 @@ +# Mage.py -- Pamhyr MAGE checkers +# 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 . + # -*- coding: utf-8 -*- import time diff --git a/src/Checker/Study.py b/src/Checker/Study.py index c6c41fed..868ac104 100644 --- a/src/Checker/Study.py +++ b/src/Checker/Study.py @@ -1,3 +1,19 @@ +# Study.py -- Pamhyr study checkers +# 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 . + # -*- coding: utf-8 -*- import time diff --git a/src/Model/BoundaryCondition/BoundaryCondition.py b/src/Model/BoundaryCondition/BoundaryCondition.py index 152a6269..7df962d2 100644 --- a/src/Model/BoundaryCondition/BoundaryCondition.py +++ b/src/Model/BoundaryCondition/BoundaryCondition.py @@ -1,3 +1,19 @@ +# BoundaryCondition.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 . + # -*- coding: utf-8 -*- from tools import trace, timer, old_pamhyr_date_to_timestamp diff --git a/src/Model/BoundaryCondition/BoundaryConditionList.py b/src/Model/BoundaryCondition/BoundaryConditionList.py index d14a870b..1a342dc7 100644 --- a/src/Model/BoundaryCondition/BoundaryConditionList.py +++ b/src/Model/BoundaryCondition/BoundaryConditionList.py @@ -1,3 +1,19 @@ +# BoundaryConditionList.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 . + # -*- coding: utf-8 -*- from copy import copy diff --git a/src/Model/BoundaryCondition/BoundaryConditionTypes.py b/src/Model/BoundaryCondition/BoundaryConditionTypes.py index c87e5b83..b2c73f11 100644 --- a/src/Model/BoundaryCondition/BoundaryConditionTypes.py +++ b/src/Model/BoundaryCondition/BoundaryConditionTypes.py @@ -1,3 +1,19 @@ +# BoundaryConditionTypes.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 . + # -*- coding: utf-8 -*- from Model.Except import NotImplementedMethodeError diff --git a/src/Model/DB.py b/src/Model/DB.py index 90869740..ef7d729d 100644 --- a/src/Model/DB.py +++ b/src/Model/DB.py @@ -1,3 +1,19 @@ +# DB.py -- Pamhyr abstract model database classes +# 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 . + # -*- coding: utf-8 -*- import os diff --git a/src/Model/Except.py b/src/Model/Except.py index ad311666..7d5e3959 100644 --- a/src/Model/Except.py +++ b/src/Model/Except.py @@ -1,3 +1,19 @@ +# Except.py -- Pamhyr model exceptions +# 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 . + # -*- coding: utf-8 -*- from PyQt5.QtCore import ( diff --git a/src/Model/Friction/Friction.py b/src/Model/Friction/Friction.py index f7328dd4..18167a86 100644 --- a/src/Model/Friction/Friction.py +++ b/src/Model/Friction/Friction.py @@ -1,3 +1,19 @@ +# Friction.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 . + # -*- coding: utf-8 -*- from tools import trace, timer diff --git a/src/Model/Friction/FrictionList.py b/src/Model/Friction/FrictionList.py index a82c9f22..21e10695 100644 --- a/src/Model/Friction/FrictionList.py +++ b/src/Model/Friction/FrictionList.py @@ -1,3 +1,19 @@ +# FrictionList.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 . + # -*- coding: utf-8 -*- import logging diff --git a/src/Model/Geometry/Point.py b/src/Model/Geometry/Point.py index 2108d962..b3b51e7d 100644 --- a/src/Model/Geometry/Point.py +++ b/src/Model/Geometry/Point.py @@ -1,3 +1,19 @@ +# Point.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 . + # -*- coding: utf-8 -*- from Model.Except import NotImplementedMethodeError diff --git a/src/Model/Geometry/PointXY.py b/src/Model/Geometry/PointXY.py index 9b84ef7c..7448d045 100644 --- a/src/Model/Geometry/PointXY.py +++ b/src/Model/Geometry/PointXY.py @@ -1,3 +1,19 @@ +# PointXY.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 . + # -*- coding: utf-8 -*- from math import dist diff --git a/src/Model/Geometry/PointXYZ.py b/src/Model/Geometry/PointXYZ.py index 0fecd1ea..cffcee97 100644 --- a/src/Model/Geometry/PointXYZ.py +++ b/src/Model/Geometry/PointXYZ.py @@ -1,3 +1,19 @@ +# PointXYZ.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 . + # -*- coding: utf-8 -*- from math import dist diff --git a/src/Model/Geometry/Profile.py b/src/Model/Geometry/Profile.py index b0328f80..c95d2282 100644 --- a/src/Model/Geometry/Profile.py +++ b/src/Model/Geometry/Profile.py @@ -1,3 +1,19 @@ +# 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 . + # -*- coding: utf-8 -*- import logging diff --git a/src/Model/Geometry/ProfileXYZ.py b/src/Model/Geometry/ProfileXYZ.py index d368b981..9cf15da4 100644 --- a/src/Model/Geometry/ProfileXYZ.py +++ b/src/Model/Geometry/ProfileXYZ.py @@ -1,3 +1,19 @@ +# ProfileXYZ.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 . + # -*- coding: utf-8 -*- import numpy as np diff --git a/src/Model/Geometry/Reach.py b/src/Model/Geometry/Reach.py index b18f2ade..d2a573f1 100644 --- a/src/Model/Geometry/Reach.py +++ b/src/Model/Geometry/Reach.py @@ -1,3 +1,19 @@ +# 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 . + # -*- coding: utf-8 -*- import logging diff --git a/src/Model/Geometry/Vector_1d.py b/src/Model/Geometry/Vector_1d.py index 51fef7f2..a3da9358 100644 --- a/src/Model/Geometry/Vector_1d.py +++ b/src/Model/Geometry/Vector_1d.py @@ -1,3 +1,19 @@ +# Vector_1d.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 . + # -*- coding: utf-8 -*- import numpy as np diff --git a/src/Model/InitialConditions/InitialConditions.py b/src/Model/InitialConditions/InitialConditions.py index bb106662..3bf747b0 100644 --- a/src/Model/InitialConditions/InitialConditions.py +++ b/src/Model/InitialConditions/InitialConditions.py @@ -1,3 +1,19 @@ +# InitialConditions.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 . + # -*- coding: utf-8 -*- from copy import copy, deepcopy diff --git a/src/Model/InitialConditions/InitialConditionsDict.py b/src/Model/InitialConditions/InitialConditionsDict.py index 5e8d5fba..48da56a0 100644 --- a/src/Model/InitialConditions/InitialConditionsDict.py +++ b/src/Model/InitialConditions/InitialConditionsDict.py @@ -1,3 +1,19 @@ +# InitialConditionsDict.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 . + # -*- coding: utf-8 -*- from copy import copy diff --git a/src/Model/LateralContribution/LateralContribution.py b/src/Model/LateralContribution/LateralContribution.py index 5098e9ba..e95733bf 100644 --- a/src/Model/LateralContribution/LateralContribution.py +++ b/src/Model/LateralContribution/LateralContribution.py @@ -1,3 +1,19 @@ +# LateralContribution.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 . + # -*- coding: utf-8 -*- from tools import trace, timer, old_pamhyr_date_to_timestamp diff --git a/src/Model/LateralContribution/LateralContributionList.py b/src/Model/LateralContribution/LateralContributionList.py index 4d6a8567..ca7c111e 100644 --- a/src/Model/LateralContribution/LateralContributionList.py +++ b/src/Model/LateralContribution/LateralContributionList.py @@ -1,3 +1,19 @@ +# LateralContributionList.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 . + # -*- coding: utf-8 -*- from copy import copy diff --git a/src/Model/LateralContribution/LateralContributionTypes.py b/src/Model/LateralContribution/LateralContributionTypes.py index 69d9946c..d669266a 100644 --- a/src/Model/LateralContribution/LateralContributionTypes.py +++ b/src/Model/LateralContribution/LateralContributionTypes.py @@ -1,3 +1,19 @@ +# LateralContributionTypes.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 . + # -*- coding: utf-8 -*- from Model.Except import NotImplementedMethodeError diff --git a/src/Model/Network/Edge.py b/src/Model/Network/Edge.py index f1ced151..12249943 100644 --- a/src/Model/Network/Edge.py +++ b/src/Model/Network/Edge.py @@ -1,3 +1,19 @@ +# Edge.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 . + # -*- coding: utf-8 -*- from Model.Network.Node import Node diff --git a/src/Model/Network/Graph.py b/src/Model/Network/Graph.py index e2d549fb..62948a2b 100644 --- a/src/Model/Network/Graph.py +++ b/src/Model/Network/Graph.py @@ -1,3 +1,19 @@ +# Graph.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 . + # -*- coding: utf-8 -*- from functools import reduce diff --git a/src/Model/Network/Node.py b/src/Model/Network/Node.py index 5f37101f..7b8f52ba 100644 --- a/src/Model/Network/Node.py +++ b/src/Model/Network/Node.py @@ -1,3 +1,19 @@ +# Node.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 . + # -*- coding: utf-8 -*- from Model.Network.Point import Point diff --git a/src/Model/Network/Point.py b/src/Model/Network/Point.py index 8ea0ecd9..0bb12609 100644 --- a/src/Model/Network/Point.py +++ b/src/Model/Network/Point.py @@ -1,3 +1,19 @@ +# Point.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 . + # -*- coding: utf-8 -*- class Point(object): diff --git a/src/Model/River.py b/src/Model/River.py index a19e6cc3..d0ae5b22 100644 --- a/src/Model/River.py +++ b/src/Model/River.py @@ -1,3 +1,19 @@ +# River.py -- Pamhyr river model +# 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 . + # -*- coding: utf-8 -*- from Model.DB import SQLSubModel diff --git a/src/Model/Saved.py b/src/Model/Saved.py index 3f672731..a1b91fd5 100644 --- a/src/Model/Saved.py +++ b/src/Model/Saved.py @@ -1,3 +1,19 @@ +# Saved.py -- Pamhyr model status class +# 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 . + # -*- coding: utf-8 -*- import logging diff --git a/src/Model/Serializable.py b/src/Model/Serializable.py index 57f2a4c1..0c083448 100644 --- a/src/Model/Serializable.py +++ b/src/Model/Serializable.py @@ -1,3 +1,19 @@ +# Serializable.py -- Pamhyr pickle abstract class +# 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 . + # -*- coding: utf-8 -*- import pickle diff --git a/src/Model/SolverParameters/SolverParametersList.py b/src/Model/SolverParameters/SolverParametersList.py index 88d1d567..a6471356 100644 --- a/src/Model/SolverParameters/SolverParametersList.py +++ b/src/Model/SolverParameters/SolverParametersList.py @@ -1,3 +1,19 @@ +# SolverParametersList.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 . + # -*- coding: utf-8 -*- from copy import copy diff --git a/src/Model/Stricklers/Stricklers.py b/src/Model/Stricklers/Stricklers.py index cbc10009..244df20b 100644 --- a/src/Model/Stricklers/Stricklers.py +++ b/src/Model/Stricklers/Stricklers.py @@ -1,3 +1,19 @@ +# Stricklers.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 . + # -*- coding: utf-8 -*- from tools import trace, timer diff --git a/src/Model/Stricklers/StricklersList.py b/src/Model/Stricklers/StricklersList.py index 049d9b83..82076bb1 100644 --- a/src/Model/Stricklers/StricklersList.py +++ b/src/Model/Stricklers/StricklersList.py @@ -1,3 +1,19 @@ +# StricklersList.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 . + # -*- coding: utf-8 -*- from tools import trace, timer diff --git a/src/Model/Study.py b/src/Model/Study.py index bdebce47..af594c90 100644 --- a/src/Model/Study.py +++ b/src/Model/Study.py @@ -1,3 +1,19 @@ +# Study.py -- Pamhyr Study class +# 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 . + # -*- coding: utf-8 -*- import os diff --git a/src/Scripts/plot_3DST.py b/src/Scripts/plot_3DST.py index 2647a32a..bcadf1f1 100644 --- a/src/Scripts/plot_3DST.py +++ b/src/Scripts/plot_3DST.py @@ -1,3 +1,19 @@ +# 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 . + # -*- coding: utf-8 -*- # a lancer depuis src diff --git a/src/Solver/ASolver.py b/src/Solver/ASolver.py index e94bac4b..5aaae4ff 100644 --- a/src/Solver/ASolver.py +++ b/src/Solver/ASolver.py @@ -1,3 +1,19 @@ +# ASolver.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 . + # -*- coding: utf-8 -*- import os diff --git a/src/Solver/GenericSolver.py b/src/Solver/GenericSolver.py index a80adf23..9e588bae 100644 --- a/src/Solver/GenericSolver.py +++ b/src/Solver/GenericSolver.py @@ -1,3 +1,19 @@ +# GenericSolver.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 . + # -*- coding: utf-8 -*- from Solver.ASolver import ( diff --git a/src/Solver/Mage.py b/src/Solver/Mage.py index 125fcfff..0d43d2ef 100644 --- a/src/Solver/Mage.py +++ b/src/Solver/Mage.py @@ -1,3 +1,19 @@ +# Mage.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 . + # -*- coding: utf-8 -*- import os diff --git a/src/Solver/Solvers.py b/src/Solver/Solvers.py index 58db6f49..221f1ff4 100644 --- a/src/Solver/Solvers.py +++ b/src/Solver/Solvers.py @@ -1,3 +1,19 @@ +# Solvers.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 . + # -*- coding: utf-8 -*- from PyQt5.QtCore import QCoreApplication diff --git a/src/View/ASubWindow.py b/src/View/ASubWindow.py index 17ae4a07..c07465f1 100644 --- a/src/View/ASubWindow.py +++ b/src/View/ASubWindow.py @@ -1,3 +1,19 @@ +# ASubWindow.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import os diff --git a/src/View/About/Window.py b/src/View/About/Window.py index f4a98121..7c269aaf 100644 --- a/src/View/About/Window.py +++ b/src/View/About/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import os @@ -40,7 +56,8 @@ class AboutWindow(ASubWindow): while True: author = next(f).strip() logger.info(f"author: {author}") - label = f"\n © {author}" + label + label = f"\n - {author}" + label except StopIteration: label = _translate("About", "Contributors: ") + label + label = "Copyright © 2023 INRAE\n" + label self.set_label_text("label_copyright", label) diff --git a/src/View/BoundaryCondition/Edit/Plot.py b/src/View/BoundaryCondition/Edit/Plot.py index 9f6df875..c9e36413 100644 --- a/src/View/BoundaryCondition/Edit/Plot.py +++ b/src/View/BoundaryCondition/Edit/Plot.py @@ -1,3 +1,19 @@ +# Plot.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from datetime import datetime diff --git a/src/View/BoundaryCondition/Edit/Table.py b/src/View/BoundaryCondition/Edit/Table.py index dfe805e1..d479ea46 100644 --- a/src/View/BoundaryCondition/Edit/Table.py +++ b/src/View/BoundaryCondition/Edit/Table.py @@ -1,3 +1,19 @@ +# Table.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import logging diff --git a/src/View/BoundaryCondition/Edit/UndoCommand.py b/src/View/BoundaryCondition/Edit/UndoCommand.py index b2eb09ac..d2b063c9 100644 --- a/src/View/BoundaryCondition/Edit/UndoCommand.py +++ b/src/View/BoundaryCondition/Edit/UndoCommand.py @@ -1,3 +1,19 @@ +# UndoCommand.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from copy import deepcopy diff --git a/src/View/BoundaryCondition/Edit/Window.py b/src/View/BoundaryCondition/Edit/Window.py index 4e8513fa..9ecd240c 100644 --- a/src/View/BoundaryCondition/Edit/Window.py +++ b/src/View/BoundaryCondition/Edit/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import timer, trace diff --git a/src/View/BoundaryCondition/Edit/translate.py b/src/View/BoundaryCondition/Edit/translate.py index 44ef5a46..4c09f5fc 100644 --- a/src/View/BoundaryCondition/Edit/translate.py +++ b/src/View/BoundaryCondition/Edit/translate.py @@ -1,3 +1,19 @@ +# translate.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from PyQt5.QtCore import QCoreApplication diff --git a/src/View/BoundaryCondition/Table.py b/src/View/BoundaryCondition/Table.py index 98890e0c..d1570c05 100644 --- a/src/View/BoundaryCondition/Table.py +++ b/src/View/BoundaryCondition/Table.py @@ -1,3 +1,19 @@ +# Table.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import trace, timer diff --git a/src/View/BoundaryCondition/UndoCommand.py b/src/View/BoundaryCondition/UndoCommand.py index 7b1c7f5e..9f8600c4 100644 --- a/src/View/BoundaryCondition/UndoCommand.py +++ b/src/View/BoundaryCondition/UndoCommand.py @@ -1,3 +1,19 @@ +# UndoCommand.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from copy import deepcopy diff --git a/src/View/BoundaryCondition/Window.py b/src/View/BoundaryCondition/Window.py index 2e7dd430..af314574 100644 --- a/src/View/BoundaryCondition/Window.py +++ b/src/View/BoundaryCondition/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import logging diff --git a/src/View/BoundaryCondition/translate.py b/src/View/BoundaryCondition/translate.py index e191d0be..661c1ad0 100644 --- a/src/View/BoundaryCondition/translate.py +++ b/src/View/BoundaryCondition/translate.py @@ -1,3 +1,19 @@ +# translate.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from PyQt5.QtCore import QCoreApplication diff --git a/src/View/CheckList/Table.py b/src/View/CheckList/Table.py index 071b4907..5810c4be 100644 --- a/src/View/CheckList/Table.py +++ b/src/View/CheckList/Table.py @@ -1,3 +1,19 @@ +# Table.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import trace, timer diff --git a/src/View/CheckList/Window.py b/src/View/CheckList/Window.py index d04c8913..4c40ad1f 100644 --- a/src/View/CheckList/Window.py +++ b/src/View/CheckList/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import trace, timer diff --git a/src/View/CheckList/Worker.py b/src/View/CheckList/Worker.py index 9137d26b..efd95ded 100644 --- a/src/View/CheckList/Worker.py +++ b/src/View/CheckList/Worker.py @@ -1,3 +1,19 @@ +# Worker.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import time diff --git a/src/View/Configure/Solver/Window.py b/src/View/Configure/Solver/Window.py index 71d4f798..c295481f 100644 --- a/src/View/Configure/Solver/Window.py +++ b/src/View/Configure/Solver/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from View.ASubWindow import ASubWindow diff --git a/src/View/Configure/Window.py b/src/View/Configure/Window.py index 818e5d9c..23a371ac 100644 --- a/src/View/Configure/Window.py +++ b/src/View/Configure/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import logging diff --git a/src/View/Debug/Window.py b/src/View/Debug/Window.py index 974eace3..346c2ce0 100644 --- a/src/View/Debug/Window.py +++ b/src/View/Debug/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import logging diff --git a/src/View/DummyWindow.py b/src/View/DummyWindow.py index 576b5188..05117bca 100644 --- a/src/View/DummyWindow.py +++ b/src/View/DummyWindow.py @@ -1,3 +1,19 @@ +# DummyWindow.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from View.ASubWindow import ASubWindow diff --git a/src/View/Frictions/PlotStricklers.py b/src/View/Frictions/PlotStricklers.py index 8f706782..71ff6e6f 100644 --- a/src/View/Frictions/PlotStricklers.py +++ b/src/View/Frictions/PlotStricklers.py @@ -1,3 +1,19 @@ +# PlotStricklers.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import timer, flatten diff --git a/src/View/Frictions/Table.py b/src/View/Frictions/Table.py index 2c96ef97..8a6171da 100644 --- a/src/View/Frictions/Table.py +++ b/src/View/Frictions/Table.py @@ -1,3 +1,19 @@ +# Table.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import trace, timer diff --git a/src/View/Frictions/UndoCommand.py b/src/View/Frictions/UndoCommand.py index 0d685ace..911ded8a 100644 --- a/src/View/Frictions/UndoCommand.py +++ b/src/View/Frictions/UndoCommand.py @@ -1,3 +1,19 @@ +# UndoCommand.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from copy import deepcopy diff --git a/src/View/Frictions/Window.py b/src/View/Frictions/Window.py index 71a3e8e1..d5761485 100644 --- a/src/View/Frictions/Window.py +++ b/src/View/Frictions/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import logging diff --git a/src/View/Frictions/translate.py b/src/View/Frictions/translate.py index c404f59c..21981ab1 100644 --- a/src/View/Frictions/translate.py +++ b/src/View/Frictions/translate.py @@ -1,3 +1,19 @@ +# translate.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from PyQt5.QtCore import QCoreApplication diff --git a/src/View/Geometry/PlotAC.py b/src/View/Geometry/PlotAC.py index 9709d3bc..fe6d933f 100644 --- a/src/View/Geometry/PlotAC.py +++ b/src/View/Geometry/PlotAC.py @@ -1,3 +1,19 @@ +# PlotAC.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import logging diff --git a/src/View/Geometry/PlotKPC.py b/src/View/Geometry/PlotKPC.py index f3e883f3..7fb31dae 100644 --- a/src/View/Geometry/PlotKPC.py +++ b/src/View/Geometry/PlotKPC.py @@ -1,3 +1,19 @@ +# PlotKPC.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import logging diff --git a/src/View/Geometry/PlotXY.py b/src/View/Geometry/PlotXY.py index 36de09cc..54e056a9 100644 --- a/src/View/Geometry/PlotXY.py +++ b/src/View/Geometry/PlotXY.py @@ -1,3 +1,19 @@ +# PlotXY.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import timer, trace diff --git a/src/View/Geometry/Profile/Plot.py b/src/View/Geometry/Profile/Plot.py index 2dc7f522..076c2703 100644 --- a/src/View/Geometry/Profile/Plot.py +++ b/src/View/Geometry/Profile/Plot.py @@ -1,3 +1,19 @@ +# Plot.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import logging diff --git a/src/View/Geometry/Profile/Table.py b/src/View/Geometry/Profile/Table.py index d55ebfcd..3d5f72df 100644 --- a/src/View/Geometry/Profile/Table.py +++ b/src/View/Geometry/Profile/Table.py @@ -1,3 +1,19 @@ +# Table.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import numpy as np diff --git a/src/View/Geometry/Profile/UndoCommand.py b/src/View/Geometry/Profile/UndoCommand.py index d0d45b99..166a004b 100644 --- a/src/View/Geometry/Profile/UndoCommand.py +++ b/src/View/Geometry/Profile/UndoCommand.py @@ -1,3 +1,19 @@ +# UndoCommand.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import trace, timer diff --git a/src/View/Geometry/Profile/Window.py b/src/View/Geometry/Profile/Window.py index 815cc2ec..cfcf6925 100644 --- a/src/View/Geometry/Profile/Window.py +++ b/src/View/Geometry/Profile/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import copy diff --git a/src/View/Geometry/Profile/mainwindow_ui_profile.py b/src/View/Geometry/Profile/mainwindow_ui_profile.py index 8de74df0..0b9443f8 100644 --- a/src/View/Geometry/Profile/mainwindow_ui_profile.py +++ b/src/View/Geometry/Profile/mainwindow_ui_profile.py @@ -1,3 +1,19 @@ +# mainwindow_ui_profile.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import os.path diff --git a/src/View/Geometry/Table.py b/src/View/Geometry/Table.py index 8cc29dc8..63ae8e45 100644 --- a/src/View/Geometry/Table.py +++ b/src/View/Geometry/Table.py @@ -1,3 +1,19 @@ +# Table.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import time diff --git a/src/View/Geometry/UndoCommand.py b/src/View/Geometry/UndoCommand.py index ed911c66..148f7db3 100644 --- a/src/View/Geometry/UndoCommand.py +++ b/src/View/Geometry/UndoCommand.py @@ -1,3 +1,19 @@ +# UndoCommand.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from copy import deepcopy diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index 8efea1c3..9fd0f6f2 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import os diff --git a/src/View/Geometry/mainwindow_ui_reach.py b/src/View/Geometry/mainwindow_ui_reach.py index f04ee9e8..747b6ca4 100644 --- a/src/View/Geometry/mainwindow_ui_reach.py +++ b/src/View/Geometry/mainwindow_ui_reach.py @@ -1,3 +1,19 @@ +# mainwindow_ui_reach.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import sys diff --git a/src/View/InitialConditions/DialogDischarge.py b/src/View/InitialConditions/DialogDischarge.py index 8d01ef0e..f8e7e32a 100644 --- a/src/View/InitialConditions/DialogDischarge.py +++ b/src/View/InitialConditions/DialogDischarge.py @@ -1,3 +1,19 @@ +# DialogDischarge.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from View.ASubWindow import ASubWindow diff --git a/src/View/InitialConditions/DialogHeight.py b/src/View/InitialConditions/DialogHeight.py index 91ceadb1..18ad67c8 100644 --- a/src/View/InitialConditions/DialogHeight.py +++ b/src/View/InitialConditions/DialogHeight.py @@ -1,3 +1,19 @@ +# DialogHeight.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from View.ASubWindow import ASubWindow diff --git a/src/View/InitialConditions/PlotDKP.py b/src/View/InitialConditions/PlotDKP.py index 247605b3..23752aef 100644 --- a/src/View/InitialConditions/PlotDKP.py +++ b/src/View/InitialConditions/PlotDKP.py @@ -1,3 +1,19 @@ +# PlotDKP.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import timer diff --git a/src/View/InitialConditions/PlotDischarge.py b/src/View/InitialConditions/PlotDischarge.py index 07664683..1fe05def 100644 --- a/src/View/InitialConditions/PlotDischarge.py +++ b/src/View/InitialConditions/PlotDischarge.py @@ -1,3 +1,19 @@ +# PlotDischarge.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import timer diff --git a/src/View/InitialConditions/Table.py b/src/View/InitialConditions/Table.py index 13eb5218..ebb9af85 100644 --- a/src/View/InitialConditions/Table.py +++ b/src/View/InitialConditions/Table.py @@ -1,3 +1,19 @@ +# Table.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import trace, timer diff --git a/src/View/InitialConditions/UndoCommand.py b/src/View/InitialConditions/UndoCommand.py index 215c299b..9d93f78b 100644 --- a/src/View/InitialConditions/UndoCommand.py +++ b/src/View/InitialConditions/UndoCommand.py @@ -1,3 +1,19 @@ +# UndoCommand.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from copy import deepcopy diff --git a/src/View/InitialConditions/Window.py b/src/View/InitialConditions/Window.py index 35822811..95f6004a 100644 --- a/src/View/InitialConditions/Window.py +++ b/src/View/InitialConditions/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import logging diff --git a/src/View/InitialConditions/translate.py b/src/View/InitialConditions/translate.py index 43890acb..370d4a22 100644 --- a/src/View/InitialConditions/translate.py +++ b/src/View/InitialConditions/translate.py @@ -1,3 +1,19 @@ +# translate.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from PyQt5.QtCore import QCoreApplication diff --git a/src/View/LateralContribution/Edit/Plot.py b/src/View/LateralContribution/Edit/Plot.py index d7c95ec0..df088405 100644 --- a/src/View/LateralContribution/Edit/Plot.py +++ b/src/View/LateralContribution/Edit/Plot.py @@ -1,3 +1,19 @@ +# Plot.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from datetime import datetime diff --git a/src/View/LateralContribution/Edit/Table.py b/src/View/LateralContribution/Edit/Table.py index 4101995c..0fabd5cb 100644 --- a/src/View/LateralContribution/Edit/Table.py +++ b/src/View/LateralContribution/Edit/Table.py @@ -1,3 +1,19 @@ +# Table.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import logging diff --git a/src/View/LateralContribution/Edit/UndoCommand.py b/src/View/LateralContribution/Edit/UndoCommand.py index b5963b76..a0a602bc 100644 --- a/src/View/LateralContribution/Edit/UndoCommand.py +++ b/src/View/LateralContribution/Edit/UndoCommand.py @@ -1,3 +1,19 @@ +# UndoCommand.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from copy import deepcopy diff --git a/src/View/LateralContribution/Edit/Window.py b/src/View/LateralContribution/Edit/Window.py index e9927710..c3459958 100644 --- a/src/View/LateralContribution/Edit/Window.py +++ b/src/View/LateralContribution/Edit/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import timer, trace diff --git a/src/View/LateralContribution/Edit/translate.py b/src/View/LateralContribution/Edit/translate.py index e44147e2..243d9ad8 100644 --- a/src/View/LateralContribution/Edit/translate.py +++ b/src/View/LateralContribution/Edit/translate.py @@ -1,3 +1,19 @@ +# translate.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from PyQt5.QtCore import QCoreApplication diff --git a/src/View/LateralContribution/Table.py b/src/View/LateralContribution/Table.py index 307fc56e..f5a8bdf1 100644 --- a/src/View/LateralContribution/Table.py +++ b/src/View/LateralContribution/Table.py @@ -1,3 +1,19 @@ +# Table.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import trace, timer diff --git a/src/View/LateralContribution/UndoCommand.py b/src/View/LateralContribution/UndoCommand.py index f7e680b3..6b688394 100644 --- a/src/View/LateralContribution/UndoCommand.py +++ b/src/View/LateralContribution/UndoCommand.py @@ -1,3 +1,19 @@ +# UndoCommand.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from copy import deepcopy diff --git a/src/View/LateralContribution/Window.py b/src/View/LateralContribution/Window.py index b87e9968..003ad48e 100644 --- a/src/View/LateralContribution/Window.py +++ b/src/View/LateralContribution/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import logging diff --git a/src/View/LateralContribution/translate.py b/src/View/LateralContribution/translate.py index c2b9e789..e9c6deeb 100644 --- a/src/View/LateralContribution/translate.py +++ b/src/View/LateralContribution/translate.py @@ -1,3 +1,19 @@ +# translate.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from PyQt5.QtCore import QCoreApplication diff --git a/src/View/ListedSubWindow.py b/src/View/ListedSubWindow.py index c88fd7b4..37d64234 100644 --- a/src/View/ListedSubWindow.py +++ b/src/View/ListedSubWindow.py @@ -1,3 +1,19 @@ +# ListedSubWindow.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import logging diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index 10a35a6e..8a94c469 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -1,3 +1,19 @@ +# MainWindow.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import os diff --git a/src/View/Network/GraphWidget.py b/src/View/Network/GraphWidget.py index 737ca6ba..aafca9e8 100644 --- a/src/View/Network/GraphWidget.py +++ b/src/View/Network/GraphWidget.py @@ -1,3 +1,19 @@ +# GraphWidget.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import math diff --git a/src/View/Network/Table.py b/src/View/Network/Table.py index 4dad50f5..1b771779 100644 --- a/src/View/Network/Table.py +++ b/src/View/Network/Table.py @@ -1,3 +1,19 @@ +# Table.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from Model.Network.Node import Node diff --git a/src/View/Network/UndoCommand.py b/src/View/Network/UndoCommand.py index d6d38125..c9cce895 100644 --- a/src/View/Network/UndoCommand.py +++ b/src/View/Network/UndoCommand.py @@ -1,3 +1,19 @@ +# UndoCommand.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from copy import deepcopy diff --git a/src/View/Network/Window.py b/src/View/Network/Window.py index 19a5d856..7099cea5 100644 --- a/src/View/Network/Window.py +++ b/src/View/Network/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from PyQt5.QtGui import ( diff --git a/src/View/Plot/APlot.py b/src/View/Plot/APlot.py index cca27087..cd9988cf 100644 --- a/src/View/Plot/APlot.py +++ b/src/View/Plot/APlot.py @@ -1,3 +1,19 @@ +# APlot.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- class APlot(object): diff --git a/src/View/Plot/MplCanvas.py b/src/View/Plot/MplCanvas.py index 5b3fc4a8..ee1f5373 100644 --- a/src/View/Plot/MplCanvas.py +++ b/src/View/Plot/MplCanvas.py @@ -1,3 +1,19 @@ +# MplCanvas.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg from matplotlib.figure import Figure diff --git a/src/View/Plot/mpl_canvas_onpick_event.py b/src/View/Plot/mpl_canvas_onpick_event.py index 010959bc..fdfa1de6 100644 --- a/src/View/Plot/mpl_canvas_onpick_event.py +++ b/src/View/Plot/mpl_canvas_onpick_event.py @@ -1,3 +1,19 @@ +# mpl_canvas_onpick_event.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + import logging from time import time diff --git a/src/View/Plot/navigation_toolbar_2qt.py b/src/View/Plot/navigation_toolbar_2qt.py index 37186450..1cca7cf0 100644 --- a/src/View/Plot/navigation_toolbar_2qt.py +++ b/src/View/Plot/navigation_toolbar_2qt.py @@ -1,3 +1,19 @@ +# navigation_toolbar_2qt.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import os diff --git a/src/View/RunSolver/Log/Window.py b/src/View/RunSolver/Log/Window.py index fb7ba631..93d42165 100644 --- a/src/View/RunSolver/Log/Window.py +++ b/src/View/RunSolver/Log/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import tempfile diff --git a/src/View/RunSolver/Window.py b/src/View/RunSolver/Window.py index 822f2bb7..dba5a16e 100644 --- a/src/View/RunSolver/Window.py +++ b/src/View/RunSolver/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import tempfile diff --git a/src/View/SolverParameters/Table.py b/src/View/SolverParameters/Table.py index 7b44159d..9aa3b55b 100644 --- a/src/View/SolverParameters/Table.py +++ b/src/View/SolverParameters/Table.py @@ -1,3 +1,19 @@ +# Table.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import trace, timer diff --git a/src/View/SolverParameters/UndoCommand.py b/src/View/SolverParameters/UndoCommand.py index 6a8dc1eb..3c917e4f 100644 --- a/src/View/SolverParameters/UndoCommand.py +++ b/src/View/SolverParameters/UndoCommand.py @@ -1,3 +1,19 @@ +# UndoCommand.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from copy import deepcopy diff --git a/src/View/SolverParameters/Window.py b/src/View/SolverParameters/Window.py index 4e154a54..9560251d 100644 --- a/src/View/SolverParameters/Window.py +++ b/src/View/SolverParameters/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import logging diff --git a/src/View/SolverParameters/translate.py b/src/View/SolverParameters/translate.py index 6085dbfb..76cb70ac 100644 --- a/src/View/SolverParameters/translate.py +++ b/src/View/SolverParameters/translate.py @@ -1,3 +1,19 @@ +# translate.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from PyQt5.QtCore import QCoreApplication diff --git a/src/View/Stricklers/Table.py b/src/View/Stricklers/Table.py index 29f8fd53..31dd4d9b 100644 --- a/src/View/Stricklers/Table.py +++ b/src/View/Stricklers/Table.py @@ -1,3 +1,19 @@ +# Table.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from tools import trace, timer diff --git a/src/View/Stricklers/UndoCommand.py b/src/View/Stricklers/UndoCommand.py index 07e782de..e7dc733e 100644 --- a/src/View/Stricklers/UndoCommand.py +++ b/src/View/Stricklers/UndoCommand.py @@ -1,3 +1,19 @@ +# UndoCommand.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from copy import deepcopy diff --git a/src/View/Stricklers/Window.py b/src/View/Stricklers/Window.py index 1d2bfe43..29f886cb 100644 --- a/src/View/Stricklers/Window.py +++ b/src/View/Stricklers/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- import logging diff --git a/src/View/Stricklers/translate.py b/src/View/Stricklers/translate.py index 4664e163..ccafd5d8 100644 --- a/src/View/Stricklers/translate.py +++ b/src/View/Stricklers/translate.py @@ -1,3 +1,19 @@ +# translate.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from PyQt5.QtCore import QCoreApplication diff --git a/src/View/Study/Window.py b/src/View/Study/Window.py index a90ed549..7218f9d3 100644 --- a/src/View/Study/Window.py +++ b/src/View/Study/Window.py @@ -1,3 +1,19 @@ +# Window.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + # -*- coding: utf-8 -*- from Model.Study import Study diff --git a/src/View/ui/ui_to_py.sh b/src/View/ui/ui_to_py.sh index 92b12ff2..f4d11a5d 100755 --- a/src/View/ui/ui_to_py.sh +++ b/src/View/ui/ui_to_py.sh @@ -1,5 +1,21 @@ #! /bin/sh +# ui_to_py.sh -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + for ui in $(ls *.ui) do python3 -m PyQt5.uic.pyuic -x $ui -o ${ui%.*}.py diff --git a/src/config.py b/src/config.py index 46e4ad2e..d18a8e34 100644 --- a/src/config.py +++ b/src/config.py @@ -1,3 +1,19 @@ +# config.py -- Pamhyr configuration manager +# 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 . + # -*- coding: utf-8 -*- import os diff --git a/src/lang/constant_string.py b/src/lang/constant_string.py index b599389a..8466a3b4 100644 --- a/src/lang/constant_string.py +++ b/src/lang/constant_string.py @@ -1,3 +1,19 @@ +# constant_string.py -- Pamhyr constant string definition for translate +# 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 . + # -*- coding: utf-8 -*- from PyQt5.QtCore import QCoreApplication diff --git a/src/lang/create_ts.sh b/src/lang/create_ts.sh index c3019916..1b30d684 100755 --- a/src/lang/create_ts.sh +++ b/src/lang/create_ts.sh @@ -1,5 +1,21 @@ #! /bin/sh +# create_ts.sh -- Pamhyr script to generate translate files +# 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 . + SOURCES=$(find ../ -name "*.py") FROM=$(find ../ -name "*.ui") diff --git a/src/pamhyr.py b/src/pamhyr.py index 8a832e18..0f957d70 100755 --- a/src/pamhyr.py +++ b/src/pamhyr.py @@ -1,4 +1,21 @@ #!/usr/bin/env python3 + +# pamhyr.py -- Pamhyr entrypoint +# 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 . + # -*- coding: utf-8 -*- import sys, os @@ -23,12 +40,20 @@ logging.basicConfig( logger = logging.getLogger() logger.setLevel(logging.INFO) +def license(): + logger.info("license: pamhyr Copyright (C) 2023 INRAE") + logger.info("license: This program comes with ABSOLUTELY NO WARRANTY.") + logger.info("license: This is free software, and you are welcome to redistribute it") + logger.info("license: under certain conditions.") + def main(): conf = Config.load() app = QApplication(sys.argv) translator = QTranslator() + license() + lang_file = "" if conf.lang == "": # System language diff --git a/src/tools.py b/src/tools.py index c71c91d1..d5707c56 100644 --- a/src/tools.py +++ b/src/tools.py @@ -1,3 +1,19 @@ +# tools.py -- Pamhyr tools function collection +# 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 . + # -*- coding: utf-8 -*- import os diff --git a/tools/license.el b/tools/license.el new file mode 100644 index 00000000..a35e4308 --- /dev/null +++ b/tools/license.el @@ -0,0 +1,41 @@ +;; license.el -- 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 . + +;; -*- coding: utf-8 -*- + +(defun pamhyr-current-filename () + (car (last (file-name-split (buffer-file-name))))) + +(defun pamhyr-insert-license () + (interactive) + (let ((filename (pamhyr-current-filename))) + (insert (format + "# %s -- 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 . +" filename)))) From 0f0a08dcbf7b97afbb61b16ebd4397dd11601149 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 1 Aug 2023 17:21:38 +0200 Subject: [PATCH 21/64] packages: Put mage in a sub directory. --- packages/linux.sh | 7 ++++--- packages/windows.bat | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/linux.sh b/packages/linux.sh index fb48c881..9bfddf54 100755 --- a/packages/linux.sh +++ b/packages/linux.sh @@ -55,9 +55,10 @@ cp ../VERSION dist/pamhyr/ cp ../AUTHORS dist/pamhyr/ cp ../LICENSE dist/pamhyr/ -cp ../mage/src/build/mage dist/pamhyr/ -cp ../mage/src/build/mage_extraire dist/pamhyr/ -cp ../mage/src/build/mailleurPF dist/pamhyr/ +mkdir -p dist/pamhyr/MAGE/ +cp ../mage/src/build/mage dist/pamhyr/MAGE/ +cp ../mage/src/build/mage_extraire dist/pamhyr/MAGE/ +cp ../mage/src/build/mailleurPF dist/pamhyr/MAGE/ echo " *** MAKE SRC PACKAGE" diff --git a/packages/windows.bat b/packages/windows.bat index eee8394f..451dc195 100644 --- a/packages/windows.bat +++ b/packages/windows.bat @@ -40,9 +40,10 @@ copy /y ..\AUTHORS dist\pamhyr\ copy /y ..\LICENSE dist\pamhyr\ rem MAGE -rem copy /y ..\mage\src\build\mage.exe dist\pamhyr\ -rem copy /y ..\mage\src\build\mage_extraire.exe dist\pamhyr\ -rem copy /y ..\mage\src\build\mailleurPF.exe dist\pamhyr\ +rem mkdir dist\pamhyr\MAGE +rem copy /y ..\mage\src\build\mage.exe dist\pamhyr\MAGE\ +rem copy /y ..\mage\src\build\mage_extraire.exe dist\pamhyr\MAGE\ +rem copy /y ..\mage\src\build\mailleurPF.exe dist\pamhyr\MAGE\ rem Make installer "C:\Program Files (x86)\NSIS\makensis.exe" pamhyr.nsi From 9c8af7b0a74d3fa97314df3d984ed46c310d5f4a Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 1 Aug 2023 17:31:24 +0200 Subject: [PATCH 22/64] Network: Fix 'previous_item' c++ object deleted. --- src/View/Network/GraphWidget.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/View/Network/GraphWidget.py b/src/View/Network/GraphWidget.py index aafca9e8..e715b388 100644 --- a/src/View/Network/GraphWidget.py +++ b/src/View/Network/GraphWidget.py @@ -17,6 +17,7 @@ # -*- coding: utf-8 -*- import math +import logging from tools import timer @@ -39,6 +40,8 @@ from Model.Network.Graph import Graph from View.Network.UndoCommand import * +logger = logging.getLogger() + _translate = QCoreApplication.translate @@ -571,14 +574,17 @@ class GraphWidget(QGraphicsView): Returns: Nothing """ - previous_item = self._selected_item - self._selected_item = item + try: + previous_item = self._selected_item + self._selected_item = item - if previous_item: - previous_item.update() + if previous_item: + previous_item.update() - if item: - item.update() + if item: + item.update() + except Exception as e: + logger.debug(str(e)) def selected_new_edge_src_node(self): """The current node item selected to add new edge From 6500c889d91eec6f71cc9ec7edde82d5609f07bb Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 2 Aug 2023 09:56:01 +0200 Subject: [PATCH 23/64] ci: Downloads mage from release Test5 and add mage to windows versions. --- .gitlab-ci.yml | 60 ++++++++++++++++++++++++++++++++++---------- packages/linux.sh | 6 ++--- packages/windows.bat | 8 +++--- 3 files changed, 54 insertions(+), 20 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8fc82ee9..19d0962c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -30,20 +30,54 @@ build-mage-linux: - linux rules: - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG - variables: - GIT_SUBMODULE_STRATEGY: recursive - GIT_SUBMODULE_DEPTH: 20 script: - - cd mage/src/ - - mkdir -p build - - cd build - - cmake .. - - make + - curl -L -o mage.tgz https://gitlab.irstea.fr/jean-baptiste.faure/mage/-/releases/Test5/downloads/packages/mage_linux.tgz + - mkdir -p mage + - cd mage + - tar xvf ../mage.tgz artifacts: paths: - - mage/src/build/mage - - mage/src/build/mage_extraire - - mage/src/build/mailleurPF + - mage/mage + - mage/mage_extraire + - mage/mailleurPF + +# build-mage-linux: +# stage: build +# tags: +# - linux +# rules: +# - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG +# variables: +# GIT_SUBMODULE_STRATEGY: recursive +# GIT_SUBMODULE_DEPTH: 20 +# script: +# - cd mage/src/ +# - mkdir -p build +# - cd build +# - cmake .. +# - make +# artifacts: +# paths: +# - mage/src/build/mage +# - mage/src/build/mage_extraire +# - mage/src/build/mailleurPF + +build-mage-windows: + stage: build + tags: + - linux + rules: + - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG + script: + - curl -L -o mage.tgz https://gitlab.irstea.fr/jean-baptiste.faure/mage/-/releases/Test5/downloads/packages/mage_windows.tgz + - mkdir -p mage + - cd mage + - tar xvf ../mage.tgz + artifacts: + paths: + - mage/mage.exe + - mage/mage_extraire.exe + - mage/mailleurPF.exe # build-mage-windows: # stage: build @@ -136,8 +170,8 @@ windows-package: artifacts: true - job: build artifacts: true - # - job: build-mage-windows - # artifacts: true + - job: build-mage-windows + artifacts: true rules: - if: $CI_COMMIT_BRANCH == 'master' || $CI_COMMIT_TAG artifacts: diff --git a/packages/linux.sh b/packages/linux.sh index 9bfddf54..023fa079 100755 --- a/packages/linux.sh +++ b/packages/linux.sh @@ -56,9 +56,9 @@ cp ../AUTHORS dist/pamhyr/ cp ../LICENSE dist/pamhyr/ mkdir -p dist/pamhyr/MAGE/ -cp ../mage/src/build/mage dist/pamhyr/MAGE/ -cp ../mage/src/build/mage_extraire dist/pamhyr/MAGE/ -cp ../mage/src/build/mailleurPF dist/pamhyr/MAGE/ +cp ../mage/mage dist/pamhyr/MAGE/ +cp ../mage/mage_extraire dist/pamhyr/MAGE/ +cp ../mage/mailleurPF dist/pamhyr/MAGE/ echo " *** MAKE SRC PACKAGE" diff --git a/packages/windows.bat b/packages/windows.bat index 451dc195..65ac8f61 100644 --- a/packages/windows.bat +++ b/packages/windows.bat @@ -40,10 +40,10 @@ copy /y ..\AUTHORS dist\pamhyr\ copy /y ..\LICENSE dist\pamhyr\ rem MAGE -rem mkdir dist\pamhyr\MAGE -rem copy /y ..\mage\src\build\mage.exe dist\pamhyr\MAGE\ -rem copy /y ..\mage\src\build\mage_extraire.exe dist\pamhyr\MAGE\ -rem copy /y ..\mage\src\build\mailleurPF.exe dist\pamhyr\MAGE\ +mkdir dist\pamhyr\MAGE +copy /y ..\mage\mage.exe dist\pamhyr\MAGE\ +copy /y ..\mage\mage_extraire.exe dist\pamhyr\MAGE\ +copy /y ..\mage\mailleurPF.exe dist\pamhyr\MAGE\ rem Make installer "C:\Program Files (x86)\NSIS\makensis.exe" pamhyr.nsi From c8a6d4ec747d53591b04fe1f0e6acb199c47bd88 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 2 Aug 2023 10:47:44 +0200 Subject: [PATCH 24/64] config: Add default mage version into config. --- src/Solver/ASolver.py | 11 +++++++++++ src/config.py | 24 +++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/Solver/ASolver.py b/src/Solver/ASolver.py index 5aaae4ff..bfb47aa7 100644 --- a/src/Solver/ASolver.py +++ b/src/Solver/ASolver.py @@ -168,12 +168,21 @@ class AbstractSolver(object): # Run # ####### + def _install_dir(self): + return os.path.abspath( + os.path.join( + os.path.dirname(__file__), + ".." + ) + ) + def run_input_data_fomater(self): if self._cmd_input == "": self._run_next() return True cmd = self._cmd_input + cmd = cmd.replace("@install_dir", self._install_dir()) cmd = cmd.replace("@path", self._path_input) cmd = cmd.replace("@input", self.input_param()) cmd = cmd.replace("@dir", self._process.workingDirectory()) @@ -196,6 +205,7 @@ class AbstractSolver(object): return True cmd = self._cmd_solver + cmd = cmd.replace("@install_dir", self._install_dir()) cmd = cmd.replace("@path", self._path_solver) cmd = cmd.replace("@input", self.input_param()) cmd = cmd.replace("@dir", self._process.workingDirectory()) @@ -219,6 +229,7 @@ class AbstractSolver(object): return True cmd = self._cmd_output + cmd = cmd.replace("@install_dir", self._install_dir()) cmd = cmd.replace("@path", self._path_output) cmd = cmd.replace("@input", self.input_param()) cmd = cmd.replace("@dir", self._process.workingDirectory()) diff --git a/src/config.py b/src/config.py index d18a8e34..5e98a7af 100644 --- a/src/config.py +++ b/src/config.py @@ -34,7 +34,7 @@ logger = logging.getLogger() class Config(SQL): def __init__(self): - self._version = '0.0.1' + self._version = '0.0.2' self.filename = Config.filename() self.set_default_value() @@ -79,12 +79,34 @@ class Config(SQL): self.commit() + def _update(self): version = self.execute(f"SELECT value FROM info WHERE key='version'")[0] if version != self._version: logger.info(f"Configuration file update from {version} to {self._version}...") + major, minor, release = version.strip().split(".") + + if major == minor == "0": + if int(release) < 2: + # Add default solver + posix = os.name == 'posix' + self.execute(f""" + INSERT INTO solver VALUES ( + 'mage8', + 'default-mage', + 'Default PAMHYR mage 8 version', + + '', '', '', + + '', + '@install_dir/mage/mage{"" if posix else ".exe"} -fp=1 @input', + '' + ) + """) + self.commit() + def _load_solver(self): self._solvers = [] From e5f93e1c851a82f10904e8a26b039cdc810ebec2 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 2 Aug 2023 10:53:32 +0200 Subject: [PATCH 25/64] Trans: Fix french translate shortcut. --- src/lang/fr.ts | 446 ++++++++++++++++++++++++------------------------- 1 file changed, 223 insertions(+), 223 deletions(-) diff --git a/src/lang/fr.ts b/src/lang/fr.ts index 07808a3c..e3581eb9 100644 --- a/src/lang/fr.ts +++ b/src/lang/fr.ts @@ -4,7 +4,7 @@ About - + Contributors: Contributeurs : @@ -12,82 +12,82 @@ BoundaryCondition - + Not associate Non associer - + X - + Y - + Time Temps - + Date Date - + Z (m) Z (m) - + days jours - + day jour - + Not defined Non définie - + Ponctual contribution Contributions ponctuelles - + Time over Z - + Time over Discharge - + Z over Discharge - + Name Nom - + Type Type - + Node Nœud @@ -100,47 +100,47 @@ Checker - + Mage network graph {mode} checker - + Check if the network graph is valid Vérifie si le graph réseau est valide - + Study network reach checker - + Check if exists at least one reach for study Vérifie si il exists au moins un Bief dans l'étude - + Study geometry checker Vérificateur de géometrie de l'étude - + Check if exists geometry for each reach of study Vérifie si la géométrie exists pour chaque bief de l'étude - + Dummy ok - + Dummy warning - + Dummy error @@ -240,7 +240,7 @@ 1000 - + 1000 @@ -361,92 +361,92 @@ Exception - + Generic error message - + Undefined error message - + Method not implemented - + Method - + not implemented - + for class - + Not implemented method - + FileFormatError - + Invalid file format: - + File format error - + Invalid file format - + Invalid file - + format because of - + Clipboard format error - + without header - + with header - + Invalid clipboard data format: - + Clipboard format unknown @@ -502,32 +502,32 @@ Frictions - + Not defined Non définie - + Name Nom - + Begin kp (m) Pk de départ (m) - + End kp (m) Pk de fin (m) - + Begin strickler strickler de départ - + End strickler Strickler de fin @@ -535,27 +535,27 @@ Geometry - + Name Nom - + Kp (m) Pk (m) - + Type Type - + upstream amont - + downstream aval @@ -563,117 +563,117 @@ LateralContribution - + Name Nom - + Minor bed Lit mineur - + Medium bed Lit moyen - + Comment Commentaire - + Not associate Non associer - + X - + Y - + Time Temps - + Date Date - + Z (m) - + days jours - + day jour - + Not defined Non définie - + Lateral contribution Contribution laterale - + Rain Pluie - + Evaporation Évaporation - + Type Type - + Reach Bief - + Begin kp (m) Pk de départ (m) - + End kp (m) Pk de fin (m) - + KP (m) PK (m) - + Elevation (m) Altitude (m) - + Height (m) Hauteur (m) @@ -768,7 +768,7 @@ Ctrl+N - + Ctrl+N @@ -778,7 +778,7 @@ Ctrl+O - + Ctrl+O @@ -813,7 +813,7 @@ Ctrl+S - + Ctrl+S @@ -823,7 +823,7 @@ Ctrl+Shift+S - + Ctrl+Shift+S @@ -843,7 +843,7 @@ Ctrl+F4 - + Ctrl+F4 @@ -958,7 +958,7 @@ F5 - + F5 @@ -1023,7 +1023,7 @@ Ctrl+F - + Ctrl+F @@ -1033,7 +1033,7 @@ Ctrl+Q - + Ctrl+Q @@ -1048,7 +1048,7 @@ Ctrl+C - + Ctrl+C @@ -1178,7 +1178,7 @@ Ctrl+Return - + Ctrl+Return @@ -1218,7 +1218,7 @@ Ctrl+D - + Ctrl+D @@ -1233,7 +1233,7 @@ Ctrl+E - + Ctrl+E @@ -1363,7 +1363,7 @@ Quit the application (Ctrl+Q) - + Quitter l'application (Ctrl+Q) @@ -1409,159 +1409,159 @@ MainWindowProfile - + Profile - + (no name) - + Quittez ? - + MainWindowProfile - + Trier les points par ordre croissant de X - + Trier les points par ordre croissant de Y - + Nom - + Abs en travers (m) - + La cote du fond Z minimale - + La cote maximale Z maximale - + Rive gauche - + Rive droite - + Abscisse en travers (m) - + Cote (m) - + Suppression les lignes incomplètes - + Supprimer les lignes des cellules non renseignées ? - + Suppression des noms répétés - + Etes-vous sûr de vouloir quitter ? - + Insérer un point - + Supprimer le/les point(s) sélectionnés - + Trier les points par ordre décroissant de X - + Trier les points par ordre décroissant de Y - + Décaler le point sélectionné vers le haut - + Décaler le point sélectionné vers le bas - + Exporter (dans un fichier) les points du profil au format tabulé - + Copier la sélection au format tabulé - + Coller la sélection depuis le presse-papier au format tabulé - + Vérifier la validité de la saisie et garder ou pas les modifications apportées - + Annuler toutes les modifications depuis la dernière validation - + Annuler toutes les modifications et revenir à l'état initial - + Ligne d'eau : Z : Cote (m) A : Aire mouillée (mu00B2) @@ -1570,12 +1570,12 @@ - + 'Maj + Clic' : Ligne d'eau & 'Ctrl + Clic' : Sélectionner des points - + Abscisse en travers calculée en projétant les points sur le plan défini par les deux points nommés extrêmes @@ -1584,249 +1584,249 @@ sur le plan défini par les deux points nommés extrêmes MainWindow_reach - + Stricklers - + Kp (m) Pk (m) - + Ouvrir un fichier - + Fichiers .ST (*.ST) - + Fichiers .M (*.M) - + Tous les fichiers (*) - + Kp : - + Files .ST(*.ST or *.st) - + All files (*) - + Abscisse en travers (m) - + Cote (m) - + Profil suivant - + Jeu de sections du Bief - + Ordre des sections : Amont --> Aval - + Pk = - + Nouveau profil - + Trier les profils par ordre croissant des Pk - + Name Nom - + Type Type - + Alt+Z - + Alt+E - + Alt+R - + Vue globale automatique (Alt+S) - + Vue globale automatique (Alt+D) - + Vue globale automatique (Alt+F) - + X (m) - + Y (m) - + Draft (m) - + KP (m) - + Discharge (m^3/s) Débit (m³/s) - + Choisissez un nom de fichier à sauvegarder - + Édition des profils sélectionnés - + Vous avez sélectionné plus de 5 profils. Seuls les 5 premiers seront édités. - + Profil N° : - + Profil précédent - + Profil sélectionné - + Importer une géométrie - + Supprimer le profil sélectionné - + Éditer le profil sélectionné - + Copier le profil sélectionné - + Coller le profil en fin de liste (penser à modifier le Pk avant de trier) - + Dupliquer la section sélectionnée - + Trier les profils par ordre décroissant des Pk - + Changer l'ordre des profils (en décalant le profil sélectionné vers le haut) - + Changer l'ordre des profils (en décalant le profil sélectionné vers le bas) - + Terminer l'édition - + Vue isométrique (Alt+Z) - + Vue isométrique (Alt+E) - + Vue isométrique (Alt+R) @@ -1834,37 +1834,37 @@ Seuls les 5 premiers seront édités. Network - + Add node Ajouter un nœud - + Delete the node Supprimer un nœud - + Disable the node Déactiver un nœud - + Delete the reach Supprimer un bief - + Disable the reach Déactiver un bief - + Enable the reach Activer un bief - + Reverse the reach orientation Inverser l'orientation du bief @@ -1872,162 +1872,162 @@ Seuls les 5 premiers seront édités. SolverParameters - + Name Nom - + Value Valeur - + Yes Oui - + No Non - + Y O - + N N - + Initial time (jj:hh:mm:ss) Temps initial (jj:hh:mm:ss) - + Final time (jj:hh:mm:ss) Temps final (jj:hh:mm:ss) - + Timestep (second) Pas de temps (en second) - + Minimum timestep (second) Pas de temps minimal (en second) - + Time step of writing on .TRA Pas de temps d'écriture dans le fichier .TRA - + Time step of writing on .BIN Pas de temps d'écriture dans le fichier .BIN - + Implicitation parameter - + Continuity discretization type (S/L) - + QSJ discretization (A/B) - + Stop criterion iterations (G/A/R) - + Iteration type - + Smoothing coefficient - + Maximun accepted number of CFL - + Minimum water height (meter) - + Maximun number of iterations (< 100) - + Timestep reduction factor - + Reduction precision factor of Z - + Reduction precision factor of Q - + Reduction precision factor of residue - + Number of iteration at maximum precision - + Number of iteration before switch - + Maximum accepted Froude number - + Diffluence node height balance - + Compute reach volume balance (Y/N) - + Maximum reach volume balance - + Minimum reach volume to check @@ -2035,12 +2035,12 @@ Seuls les 5 premiers seront édités. Solvers - + Generic Générique - + Mage version 8 Mage en version 8 @@ -2048,42 +2048,42 @@ Seuls les 5 premiers seront édités. Toolbar - + Vue originale - + Panoramique des axes avec la souris gauche, zoom avec la droite - + Zoom - + Vue globale automatique (Shift+X) - + Enregistrer la figure - + Retour à la vue précédente - + Passer à la vue suivante - + Vue isométrique (Shift+W) From 4f0f2514de30142068069cd6493a2c1f949e245f Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 2 Aug 2023 11:01:50 +0200 Subject: [PATCH 26/64] Config: Add default mage solver for new configuration. --- src/config.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/config.py b/src/config.py index 5e98a7af..16ec6b12 100644 --- a/src/config.py +++ b/src/config.py @@ -250,6 +250,13 @@ class Config(SQL): # Solvers self._solvers = [] + posix = os.name == 'posix' + ctor = solver_type_list["mage8"] + new = ctor("default-mage") + new._description = "Default PAMHYR mage 8 version" + new._cmd_solver = f"""@install_dir/mage/mage{"" if posix else ".exe"} -fp=1 @input""" + self._solvers.append(new) + # Meshing tool self.meshing_tool = "" From 20329eba229f2d7536fd4b9671951ee569bfb694 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 2 Aug 2023 11:25:52 +0200 Subject: [PATCH 27/64] Packages: Add test case Saar to package. --- packages/linux.sh | 4 ++++ packages/windows.bat | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/packages/linux.sh b/packages/linux.sh index 023fa079..83f5c6fe 100755 --- a/packages/linux.sh +++ b/packages/linux.sh @@ -60,6 +60,10 @@ cp ../mage/mage dist/pamhyr/MAGE/ cp ../mage/mage_extraire dist/pamhyr/MAGE/ cp ../mage/mailleurPF dist/pamhyr/MAGE/ +mkdir -p dist/pamhyr/tests_cases/ +mkdir -p dist/pamhyr/tests_cases/Saar +cp ../tests_cases/Saar/Saar.pamhyr dist/pamhyr/tests_cases/Saar/ + echo " *** MAKE SRC PACKAGE" OLD_PWD=$PWD diff --git a/packages/windows.bat b/packages/windows.bat index 65ac8f61..d8f6e2a5 100644 --- a/packages/windows.bat +++ b/packages/windows.bat @@ -45,5 +45,11 @@ copy /y ..\mage\mage.exe dist\pamhyr\MAGE\ copy /y ..\mage\mage_extraire.exe dist\pamhyr\MAGE\ copy /y ..\mage\mailleurPF.exe dist\pamhyr\MAGE\ +rem Copy tests_cases +mkdir dist\pamhyr\tests_cases +mkdir dist\pamhyr\tests_cases\Saar +copy /y ..\tests_cases\Saar\Saar.pamhyr dist\pamhyr\tests_cases\Saar\ + + rem Make installer "C:\Program Files (x86)\NSIS\makensis.exe" pamhyr.nsi From ee22dab89c22f2d57b708f746e0d7039cc6b7451 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 2 Aug 2023 15:07:13 +0200 Subject: [PATCH 28/64] Packages: Fix mage repository name. --- packages/linux.sh | 8 ++++---- packages/windows.bat | 9 ++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/linux.sh b/packages/linux.sh index 83f5c6fe..44770b6e 100755 --- a/packages/linux.sh +++ b/packages/linux.sh @@ -55,10 +55,10 @@ cp ../VERSION dist/pamhyr/ cp ../AUTHORS dist/pamhyr/ cp ../LICENSE dist/pamhyr/ -mkdir -p dist/pamhyr/MAGE/ -cp ../mage/mage dist/pamhyr/MAGE/ -cp ../mage/mage_extraire dist/pamhyr/MAGE/ -cp ../mage/mailleurPF dist/pamhyr/MAGE/ +mkdir -p dist/pamhyr/mage/ +cp ../mage/mage dist/pamhyr/mage/ +cp ../mage/mage_extraire dist/pamhyr/mage/ +cp ../mage/mailleurPF dist/pamhyr/mage/ mkdir -p dist/pamhyr/tests_cases/ mkdir -p dist/pamhyr/tests_cases/Saar diff --git a/packages/windows.bat b/packages/windows.bat index d8f6e2a5..16aba85c 100644 --- a/packages/windows.bat +++ b/packages/windows.bat @@ -40,16 +40,15 @@ copy /y ..\AUTHORS dist\pamhyr\ copy /y ..\LICENSE dist\pamhyr\ rem MAGE -mkdir dist\pamhyr\MAGE -copy /y ..\mage\mage.exe dist\pamhyr\MAGE\ -copy /y ..\mage\mage_extraire.exe dist\pamhyr\MAGE\ -copy /y ..\mage\mailleurPF.exe dist\pamhyr\MAGE\ +mkdir dist\pamhyr\mage +copy /y ..\mage\mage.exe dist\pamhyr\mage\ +copy /y ..\mage\mage_extraire.exe dist\pamhyr\mage\ +copy /y ..\mage\mailleurPF.exe dist\pamhyr\mage\ rem Copy tests_cases mkdir dist\pamhyr\tests_cases mkdir dist\pamhyr\tests_cases\Saar copy /y ..\tests_cases\Saar\Saar.pamhyr dist\pamhyr\tests_cases\Saar\ - rem Make installer "C:\Program Files (x86)\NSIS\makensis.exe" pamhyr.nsi From 304f7f1495b4fbbe1a10671f369a5a1d205c4808 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 2 Aug 2023 15:12:13 +0200 Subject: [PATCH 29/64] Network, BC: Fix mouseReleaseEvent and contextMenuEvent Exception. --- src/View/Network/GraphWidget.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/View/Network/GraphWidget.py b/src/View/Network/GraphWidget.py index e715b388..870792b8 100644 --- a/src/View/Network/GraphWidget.py +++ b/src/View/Network/GraphWidget.py @@ -736,6 +736,9 @@ class GraphWidget(QGraphicsView): def mouseReleaseEvent(self, event): self.clicked = False + if self._only_display: + return + if self._state == "move": if self._current_moved_node is not None: pos = self.mapToScene(event.pos()) @@ -841,6 +844,9 @@ class GraphWidget(QGraphicsView): self.reverse_edge(items[0]) def contextMenuEvent(self, event): + if self._only_display: + return + pos = self.mapToScene(event.pos()) items = self.items(event.pos()) From e8ae1c06316fd10b8f03cc6f377712afb37dfb26 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 4 Aug 2023 09:49:34 +0200 Subject: [PATCH 30/64] Stricklers: Fix minor and medium bed coefficient type. --- src/Model/Stricklers/Stricklers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Model/Stricklers/Stricklers.py b/src/Model/Stricklers/Stricklers.py index 244df20b..baa484fa 100644 --- a/src/Model/Stricklers/Stricklers.py +++ b/src/Model/Stricklers/Stricklers.py @@ -140,7 +140,7 @@ class Stricklers(SQLSubModel): @minor.setter def minor(self, minor): - self._minor = int(minor) + self._minor = float(minor) @property def medium(self): @@ -148,4 +148,4 @@ class Stricklers(SQLSubModel): @medium.setter def medium(self, medium): - self._medium = int(medium) + self._medium = float(medium) From 464209b6e5b81bc57b6d1b5ed22f5668652a5e46 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 4 Aug 2023 10:40:32 +0200 Subject: [PATCH 31/64] pamhyr: Catch some table data type exception (crash Fix). --- src/View/BoundaryCondition/Edit/Table.py | 13 ++-- .../BoundaryCondition/Edit/UndoCommand.py | 3 +- src/View/BoundaryCondition/Table.py | 41 +++++++----- src/View/BoundaryCondition/UndoCommand.py | 2 +- src/View/Frictions/Table.py | 59 +++++++++-------- src/View/Frictions/UndoCommand.py | 6 +- src/View/Geometry/Profile/Table.py | 64 +++++++++++-------- src/View/Geometry/Profile/UndoCommand.py | 18 +++++- src/View/Geometry/Table.py | 33 ++++++---- src/View/Geometry/UndoCommand.py | 10 ++- src/View/InitialConditions/Table.py | 18 ++++-- src/View/InitialConditions/UndoCommand.py | 7 +- src/View/LateralContribution/Edit/Table.py | 13 ++-- .../LateralContribution/Edit/UndoCommand.py | 3 +- src/View/LateralContribution/Table.py | 61 ++++++++++-------- src/View/LateralContribution/UndoCommand.py | 6 +- src/View/Network/Table.py | 53 ++++++++------- src/View/SolverParameters/Table.py | 23 ++++--- src/View/SolverParameters/UndoCommand.py | 2 +- src/View/Stricklers/Table.py | 50 +++++++++------ src/View/Stricklers/UndoCommand.py | 8 +-- 21 files changed, 303 insertions(+), 190 deletions(-) diff --git a/src/View/BoundaryCondition/Edit/Table.py b/src/View/BoundaryCondition/Edit/Table.py index d479ea46..6536bd0d 100644 --- a/src/View/BoundaryCondition/Edit/Table.py +++ b/src/View/BoundaryCondition/Edit/Table.py @@ -17,6 +17,7 @@ # -*- coding: utf-8 -*- import logging +import traceback from datetime import date, time, datetime, timedelta @@ -212,11 +213,15 @@ class TableModel(QAbstractTableModel): row = index.row() column = index.column() - self._undo.push( - SetDataCommand( - self._data, row, column, value + try: + self._undo.push( + SetDataCommand( + self._data, row, column, value + ) ) - ) + except Exception as e: + logger.info(e) + logger.debug(traceback.format_exc()) self.dataChanged.emit(index, index) return True diff --git a/src/View/BoundaryCondition/Edit/UndoCommand.py b/src/View/BoundaryCondition/Edit/UndoCommand.py index d2b063c9..4bb2605f 100644 --- a/src/View/BoundaryCondition/Edit/UndoCommand.py +++ b/src/View/BoundaryCondition/Edit/UndoCommand.py @@ -33,7 +33,8 @@ class SetDataCommand(QUndoCommand): self._index = index self._column = column self._old = self._data.get_i(self._index)[self._column] - self._new = new_value + _type = self._data.get_type_column(self._column) + self._new = _type(new_value) def undo(self): self._data._set_i_c_v(self._index, self._column, self._old) diff --git a/src/View/BoundaryCondition/Table.py b/src/View/BoundaryCondition/Table.py index d1570c05..fd39a13a 100644 --- a/src/View/BoundaryCondition/Table.py +++ b/src/View/BoundaryCondition/Table.py @@ -16,6 +16,9 @@ # -*- coding: utf-8 -*- +import logging +import traceback + from tools import trace, timer from PyQt5.QtCore import ( @@ -43,6 +46,8 @@ from View.BoundaryCondition.UndoCommand import ( ) from View.BoundaryCondition.translate import * +logger = logging.getLogger() + _translate = QCoreApplication.translate class ComboBoxDelegate(QItemDelegate): @@ -153,25 +158,29 @@ class TableModel(QAbstractTableModel): row = index.row() column = index.column() - if self._headers[column] == "name": - self._undo.push( - SetNameCommand( - self._bcs, self._tab,row, value + try: + if self._headers[column] == "name": + self._undo.push( + SetNameCommand( + self._bcs, self._tab,row, value + ) ) - ) - elif self._headers[column] == "type": - key = next(k for k, v in long_types.items() if v == value) - self._undo.push( - SetTypeCommand( - self._bcs, self._tab,row, BC_types[key] + elif self._headers[column] == "type": + key = next(k for k, v in long_types.items() if v == value) + self._undo.push( + SetTypeCommand( + self._bcs, self._tab,row, BC_types[key] + ) ) - ) - elif self._headers[column] == "node": - self._undo.push( - SetNodeCommand( - self._bcs, self._tab,row, self._data.node(value) + elif self._headers[column] == "node": + self._undo.push( + SetNodeCommand( + self._bcs, self._tab,row, self._data.node(value) + ) ) - ) + except Exception as e: + logger.info(e) + logger.debug(traceback.format_exc()) self.dataChanged.emit(index, index) return True diff --git a/src/View/BoundaryCondition/UndoCommand.py b/src/View/BoundaryCondition/UndoCommand.py index 9f8600c4..bbf8cb2c 100644 --- a/src/View/BoundaryCondition/UndoCommand.py +++ b/src/View/BoundaryCondition/UndoCommand.py @@ -34,7 +34,7 @@ class SetNameCommand(QUndoCommand): self._tab = tab self._index = index self._old = self._bcs.get(self._tab, self._index).name - self._new = new_value + self._new = str(new_value) def undo(self): self._bcs.get(self._tab, self._index).name = self._old diff --git a/src/View/Frictions/Table.py b/src/View/Frictions/Table.py index 8a6171da..ef9dc32f 100644 --- a/src/View/Frictions/Table.py +++ b/src/View/Frictions/Table.py @@ -16,6 +16,9 @@ # -*- coding: utf-8 -*- +import logging +import traceback + from tools import trace, timer from PyQt5.QtCore import ( @@ -40,6 +43,8 @@ from View.Frictions.UndoCommand import ( from View.Frictions.translate import * +logger = logging.getLogger() + _translate = QCoreApplication.translate class ComboBoxDelegate(QItemDelegate): @@ -148,36 +153,40 @@ class TableModel(QAbstractTableModel): row = index.row() column = index.column() - if self._headers[column] == "name": - self._undo.push( - SetNameCommand( - self._frictions, row, value + try: + if self._headers[column] == "name": + self._undo.push( + SetNameCommand( + self._frictions, row, value + ) ) - ) - elif self._headers[column] == "begin_kp": - self._undo.push( - SetBeginCommand( - self._frictions, row, value + elif self._headers[column] == "begin_kp": + self._undo.push( + SetBeginCommand( + self._frictions, row, value + ) ) - ) - elif self._headers[column] == "end_kp": - self._undo.push( - SetEndCommand( - self._frictions, row, value + elif self._headers[column] == "end_kp": + self._undo.push( + SetEndCommand( + self._frictions, row, value + ) ) - ) - elif self._headers[column] == "begin_strickler": - self._undo.push( - SetBeginStricklerCommand( - self._frictions, row, self._study.river.strickler(value) + elif self._headers[column] == "begin_strickler": + self._undo.push( + SetBeginStricklerCommand( + self._frictions, row, self._study.river.strickler(value) + ) ) - ) - elif self._headers[column] == "end_strickler": - self._undo.push( - SetEndStricklerCommand( - self._frictions, row, self._study.river.strickler(value) + elif self._headers[column] == "end_strickler": + self._undo.push( + SetEndStricklerCommand( + self._frictions, row, self._study.river.strickler(value) + ) ) - ) + except Exception as e: + logger.info(e) + logger.debug(traceback.format_exc()) self.dataChanged.emit(index, index) return True diff --git a/src/View/Frictions/UndoCommand.py b/src/View/Frictions/UndoCommand.py index 911ded8a..ef902f07 100644 --- a/src/View/Frictions/UndoCommand.py +++ b/src/View/Frictions/UndoCommand.py @@ -33,7 +33,7 @@ class SetNameCommand(QUndoCommand): self._frictions = frictions self._index = index self._old = self._frictions.get(self._index).name - self._new = new_value + self._new = str(new_value) def undo(self): self._frictions.get(self._index).name = self._old @@ -48,7 +48,7 @@ class SetBeginCommand(QUndoCommand): self._frictions = frictions self._index = index self._old = self._frictions.get(self._index).begin_kp - self._new = new_value + self._new = float(new_value) def undo(self): self._frictions.get(self._index).begin_kp = float(self._old) @@ -63,7 +63,7 @@ class SetEndCommand(QUndoCommand): self._frictions = frictions self._index = index self._old = self._frictions.get(self._index).end_kp - self._new = new_value + self._new = float(new_value) def undo(self): self._frictions.get(self._index).end_kp = float(self._old) diff --git a/src/View/Geometry/Profile/Table.py b/src/View/Geometry/Profile/Table.py index 3d5f72df..2de665aa 100644 --- a/src/View/Geometry/Profile/Table.py +++ b/src/View/Geometry/Profile/Table.py @@ -17,6 +17,8 @@ # -*- coding: utf-8 -*- import numpy as np +import logging +import traceback from tools import timer, trace @@ -36,6 +38,8 @@ from Model.Geometry.ProfileXYZ import ProfileXYZ from View.Geometry.Profile.UndoCommand import * +logger = logging.getLogger() + _translate = QCoreApplication.translate @@ -148,38 +152,42 @@ class TableEditableModel(QAbstractTableModel): column = index.column() if role == Qt.EditRole: - if column == 0: - self._undo_stack.push( - SetXCommand( - self._profile, row, - self._profile.point(row).x, - value + try: + if column == 0: + self._undo_stack.push( + SetXCommand( + self._profile, row, + self._profile.point(row).x, + value + ) ) - ) - elif column == 1: - self._undo_stack.push( - SetYCommand( - self._profile, row, - self._profile.point(row).y, - value + elif column == 1: + self._undo_stack.push( + SetYCommand( + self._profile, row, + self._profile.point(row).y, + value + ) ) - ) - elif column == 2: - self._undo_stack.push( - SetZCommand( - self._profile, row, - self._profile.point(row).z, - value + elif column == 2: + self._undo_stack.push( + SetZCommand( + self._profile, row, + self._profile.point(row).z, + value + ) ) - ) - elif column == 3: - self._undo_stack.push( - SetNameCommand( - self._profile, row, - self._profile.point(row).name, - value + elif column == 3: + self._undo_stack.push( + SetNameCommand( + self._profile, row, + self._profile.point(row).name, + value + ) ) - ) + except Exception as e: + logger.info(e) + logger.debug(traceback.format_exc()) self.dataChanged.emit(index, index) return True diff --git a/src/View/Geometry/Profile/UndoCommand.py b/src/View/Geometry/Profile/UndoCommand.py index 166a004b..7f0cd138 100644 --- a/src/View/Geometry/Profile/UndoCommand.py +++ b/src/View/Geometry/Profile/UndoCommand.py @@ -32,9 +32,13 @@ class SetDataCommand(QUndoCommand): self._profile = profile self._index = index self._old = old_value - self._new = new_value + self._new = self.type(new_value) class SetXCommand(SetDataCommand): + def __init__(self, reach, index, old_value, new_value): + self.type = float + super(SetXCommand, self).__init__(reach, index, old_value, new_value) + def undo(self): self._profile.point(self._index).x = self._old @@ -42,6 +46,10 @@ class SetXCommand(SetDataCommand): self._profile.point(self._index).x = self._new class SetYCommand(SetDataCommand): + def __init__(self, reach, index, old_value, new_value): + self.type = float + super(SetYCommand, self).__init__(reach, index, old_value, new_value) + def undo(self): self._profile.point(self._index).y = self._old @@ -49,6 +57,10 @@ class SetYCommand(SetDataCommand): self._profile.point(self._index).y = self._new class SetZCommand(SetDataCommand): + def __init__(self, reach, index, old_value, new_value): + self.type = float + super(SetZCommand, self).__init__(reach, index, old_value, new_value) + def undo(self): self._profile.point(self._index).z = self._old @@ -56,6 +68,10 @@ class SetZCommand(SetDataCommand): self._profile.point(self._index).z = self._new class SetNameCommand(SetDataCommand): + def __init__(self, reach, index, old_value, new_value): + self.type = str + super(SetNameCommand, self).__init__(reach, index, old_value, new_value) + def undo(self): self._profile.point(self._index).name = self._old diff --git a/src/View/Geometry/Table.py b/src/View/Geometry/Table.py index 63ae8e45..1b055209 100644 --- a/src/View/Geometry/Table.py +++ b/src/View/Geometry/Table.py @@ -17,6 +17,8 @@ # -*- coding: utf-8 -*- import time +import logging +import traceback from tools import timer, trace @@ -37,6 +39,7 @@ from Model.Geometry import Reach from Model.Geometry.ProfileXYZ import ProfileXYZ from View.Geometry.UndoCommand import * +logger = logging.getLogger() _translate = QCoreApplication.translate @@ -114,23 +117,27 @@ class TableEditableModel(QAbstractTableModel): column = index.column() if role == Qt.EditRole and index.column() != 2: - if index.column() == 0: - self._undo_stack.push( - SetNameCommand( - self._reach, index.row(), - self._reach.profile(index.row()).name, - value + try: + if index.column() == 0: + self._undo_stack.push( + SetNameCommand( + self._reach, index.row(), + self._reach.profile(index.row()).name, + value + ) ) - ) - if index.column() == 1: - self._undo_stack.push( - SetKPCommand( - self._reach, index.row(), - self._reach.profile(index.row()).kp, + if index.column() == 1: + self._undo_stack.push( + SetKPCommand( + self._reach, index.row(), + self._reach.profile(index.row()).kp, value + ) ) - ) + except Exception as e: + logger.info(e) + logger.debug(traceback.format_exc()) self.dataChanged.emit(index, index) self.layoutChanged.emit() diff --git a/src/View/Geometry/UndoCommand.py b/src/View/Geometry/UndoCommand.py index 148f7db3..1df9c58c 100644 --- a/src/View/Geometry/UndoCommand.py +++ b/src/View/Geometry/UndoCommand.py @@ -33,9 +33,13 @@ class SetDataCommand(QUndoCommand): self._reach = reach self._index = index self._old = old_value - self._new = new_value + self._new = self.type(new_value) class SetNameCommand(SetDataCommand): + def __init__(self, reach, index, old_value, new_value): + self.type = str + super(SetNameCommand, self).__init__(reach, index, old_value, new_value) + def undo(self): self._reach.profile(self._index).name = self._old @@ -43,6 +47,10 @@ class SetNameCommand(SetDataCommand): self._reach.profile(self._index).name = self._new class SetKPCommand(SetDataCommand): + def __init__(self, reach, index, old_value, new_value): + self.type = float + super(SetKPCommand, self).__init__(reach, index, old_value, new_value) + def undo(self): self._reach.profile(self._index).kp = self._old diff --git a/src/View/InitialConditions/Table.py b/src/View/InitialConditions/Table.py index ebb9af85..5e704ba9 100644 --- a/src/View/InitialConditions/Table.py +++ b/src/View/InitialConditions/Table.py @@ -16,6 +16,8 @@ # -*- coding: utf-8 -*- +import logging +import traceback from tools import trace, timer from PyQt5.QtCore import ( @@ -39,6 +41,8 @@ from View.InitialConditions.UndoCommand import ( from View.InitialConditions.translate import * +logger = logging.getLogger() + _translate = QCoreApplication.translate class ComboBoxDelegate(QItemDelegate): @@ -135,12 +139,16 @@ class TableModel(QAbstractTableModel): row = index.row() column = index.column() - if self._headers[column] is not None: - self._undo.push( - SetCommand( - self._ics, row, self._headers[column], value + try: + if self._headers[column] is not None: + self._undo.push( + SetCommand( + self._ics, row, self._headers[column], value + ) ) - ) + except Exception as e: + logger.info(e) + logger.debug(traceback.format_exc()) self.dataChanged.emit(index, index) return True diff --git a/src/View/InitialConditions/UndoCommand.py b/src/View/InitialConditions/UndoCommand.py index 9d93f78b..c96f90fa 100644 --- a/src/View/InitialConditions/UndoCommand.py +++ b/src/View/InitialConditions/UndoCommand.py @@ -34,7 +34,12 @@ class SetCommand(QUndoCommand): self._row = row self._column = column self._old = self._ics.get(self._row)[column] - self._new = new_value + + _type = float + if column == "name" or column == "comment": + _type = str + + self._new = _type(new_value) def undo(self): self._ics.get(self._row)[self._column] = self._old diff --git a/src/View/LateralContribution/Edit/Table.py b/src/View/LateralContribution/Edit/Table.py index 0fabd5cb..e9e878fd 100644 --- a/src/View/LateralContribution/Edit/Table.py +++ b/src/View/LateralContribution/Edit/Table.py @@ -17,6 +17,7 @@ # -*- coding: utf-8 -*- import logging +import traceback from datetime import date, time, datetime, timedelta from tools import trace, timer @@ -210,11 +211,15 @@ class TableModel(QAbstractTableModel): row = index.row() column = index.column() - self._undo.push( - SetDataCommand( - self._data, row, column, value + try: + self._undo.push( + SetDataCommand( + self._data, row, column, value + ) ) - ) + except Exception as e: + logger.info(e) + logger.debug(traceback.format_exc()) self.dataChanged.emit(index, index) return True diff --git a/src/View/LateralContribution/Edit/UndoCommand.py b/src/View/LateralContribution/Edit/UndoCommand.py index a0a602bc..715683c9 100644 --- a/src/View/LateralContribution/Edit/UndoCommand.py +++ b/src/View/LateralContribution/Edit/UndoCommand.py @@ -33,7 +33,8 @@ class SetDataCommand(QUndoCommand): self._index = index self._column = column self._old = self._data.get_i(self._index)[self._column] - self._new = new_value + _type = self._data.get_type_column(self._column) + self._new = _type(new_value) def undo(self): self._data._set_i_c_v(self._index, self._column, self._old) diff --git a/src/View/LateralContribution/Table.py b/src/View/LateralContribution/Table.py index f5a8bdf1..682bf00d 100644 --- a/src/View/LateralContribution/Table.py +++ b/src/View/LateralContribution/Table.py @@ -16,6 +16,9 @@ # -*- coding: utf-8 -*- +import logging +import traceback + from tools import trace, timer from PyQt5.QtCore import ( @@ -43,6 +46,8 @@ from Model.LateralContribution.LateralContributionTypes import ( ) from View.LateralContribution.translate import * +logger = logging.getLogger() + _translate = QCoreApplication.translate class ComboBoxDelegate(QItemDelegate): @@ -156,37 +161,41 @@ class TableModel(QAbstractTableModel): row = index.row() column = index.column() - if self._headers[column] == "name": - self._undo.push( - SetNameCommand( - self._lcs, self._tab, row, value + try: + if self._headers[column] == "name": + self._undo.push( + SetNameCommand( + self._lcs, self._tab, row, value + ) ) - ) - elif self._headers[column] == "type": - key = next(k for k, v in long_types.items() if v == value) - self._undo.push( - SetTypeCommand( - self._lcs, self._tab, row, LC_types[key] + elif self._headers[column] == "type": + key = next(k for k, v in long_types.items() if v == value) + self._undo.push( + SetTypeCommand( + self._lcs, self._tab, row, LC_types[key] + ) ) - ) - elif self._headers[column] == "edge": - self._undo.push( - SetEdgeCommand( - self._lcs, self._tab, row, self._data.edge(value) + elif self._headers[column] == "edge": + self._undo.push( + SetEdgeCommand( + self._lcs, self._tab, row, self._data.edge(value) + ) ) - ) - elif self._headers[column] == "begin_kp": - self._undo.push( - SetBeginCommand( - self._lcs, self._tab, row, value + elif self._headers[column] == "begin_kp": + self._undo.push( + SetBeginCommand( + self._lcs, self._tab, row, value + ) ) - ) - elif self._headers[column] == "end_kp": - self._undo.push( - SetEndCommand( - self._lcs, self._tab, row, value + elif self._headers[column] == "end_kp": + self._undo.push( + SetEndCommand( + self._lcs, self._tab, row, value + ) ) - ) + except Exception as e: + logger.info(e) + logger.debug(traceback.format_exc()) self.dataChanged.emit(index, index) return True diff --git a/src/View/LateralContribution/UndoCommand.py b/src/View/LateralContribution/UndoCommand.py index 6b688394..3d858436 100644 --- a/src/View/LateralContribution/UndoCommand.py +++ b/src/View/LateralContribution/UndoCommand.py @@ -34,7 +34,7 @@ class SetNameCommand(QUndoCommand): self._tab = tab self._index = index self._old = self._lcs.get(self._tab, self._index).name - self._new = new_value + self._new = str(new_value) def undo(self): self._lcs.get(self._tab, self._index).name = self._old @@ -50,7 +50,7 @@ class SetBeginCommand(QUndoCommand): self._tab = tab self._index = index self._old = self._lcs.get(self._tab, self._index).begin_kp - self._new = new_value + self._new = float(new_value) def undo(self): self._lcs.get(self._tab, self._index).begin_kp = float(self._old) @@ -66,7 +66,7 @@ class SetEndCommand(QUndoCommand): self._tab = tab self._index = index self._old = self._lcs.get(self._tab, self._index).end_kp - self._new = new_value + self._new = float(new_value) def undo(self): self._lcs.get(self._tab, self._index).end_kp = float(self._old) diff --git a/src/View/Network/Table.py b/src/View/Network/Table.py index 1b771779..b24865e8 100644 --- a/src/View/Network/Table.py +++ b/src/View/Network/Table.py @@ -16,6 +16,9 @@ # -*- coding: utf-8 -*- +import logging +import traceback + from Model.Network.Node import Node from Model.Network.Edge import Edge from Model.Network.Graph import Graph @@ -153,31 +156,35 @@ class GraphTableModel(QAbstractTableModel): def setData(self, index, value, role=Qt.EditRole): if index.isValid(): if role == Qt.EditRole: - if (self.headers[index.column()] == "node1" or - self.headers[index.column()] == "node2"): - node = self.graph.node(value) - self._undo.push( - SetNodeCommand( - self.graph, - self.rows[index.row()], - self.headers[index.column()], - node + try: + if (self.headers[index.column()] == "node1" or + self.headers[index.column()] == "node2"): + node = self.graph.node(value) + self._undo.push( + SetNodeCommand( + self.graph, + self.rows[index.row()], + self.headers[index.column()], + node + ) ) - ) - # elif self.headers[index.column()] == "enable": - # self._undo.push( - # EnableEdgeCommand( - # self.rows[index.row()], value - # ) - # ) - else: - self._undo.push( - SetCommand( - self.rows[index.row()], - self.headers[index.column()], - value + # elif self.headers[index.column()] == "enable": + # self._undo.push( + # EnableEdgeCommand( + # self.rows[index.row()], value + # ) + # ) + else: + self._undo.push( + SetCommand( + self.rows[index.row()], + self.headers[index.column()], + value + ) ) - ) + except Exception as e: + logger.info(e) + logger.debug(traceback.format_exc()) self.dataChanged.emit(index, index, [Qt.DisplayRole]) self.layoutChanged.emit() diff --git a/src/View/SolverParameters/Table.py b/src/View/SolverParameters/Table.py index 9aa3b55b..5aa488ab 100644 --- a/src/View/SolverParameters/Table.py +++ b/src/View/SolverParameters/Table.py @@ -16,6 +16,9 @@ # -*- coding: utf-8 -*- +import logging +import traceback + from tools import trace, timer from PyQt5.QtCore import ( @@ -97,16 +100,20 @@ class TableModel(QAbstractTableModel): row = index.row() column = index.column() - if self._headers[column] == "value": - if value in tr.r_yes_no: - value = tr.r_yes_no[value].lower() + try: + if self._headers[column] == "value": + if value in tr.r_yes_no: + value = tr.r_yes_no[value].lower() - self._undo.push( - SetCommand( - self._params, row, - "value", value + self._undo.push( + SetCommand( + self._params, row, + "value", value + ) ) - ) + except Exception as e: + logger.info(e) + logger.debug(traceback.format_exc()) self.dataChanged.emit(index, index) return True diff --git a/src/View/SolverParameters/UndoCommand.py b/src/View/SolverParameters/UndoCommand.py index 3c917e4f..d3343d00 100644 --- a/src/View/SolverParameters/UndoCommand.py +++ b/src/View/SolverParameters/UndoCommand.py @@ -33,7 +33,7 @@ class SetCommand(QUndoCommand): self._index = index self._column = column self._old = self._data.get(self._index)[column] - self._new = new_value + self._new = str(new_value) def undo(self): self._data.get(self._index)[self._column] = self._old diff --git a/src/View/Stricklers/Table.py b/src/View/Stricklers/Table.py index 31dd4d9b..5d32cda5 100644 --- a/src/View/Stricklers/Table.py +++ b/src/View/Stricklers/Table.py @@ -16,6 +16,9 @@ # -*- coding: utf-8 -*- +import logging +import traceback + from tools import trace, timer from PyQt5.QtCore import ( @@ -39,8 +42,9 @@ from View.Stricklers.UndoCommand import ( from View.Stricklers.translate import * -_translate = QCoreApplication.translate +logger = logging.getLogger() +_translate = QCoreApplication.translate class TableModel(QAbstractTableModel): def __init__(self, data=None, undo=None, tab=""): @@ -92,30 +96,34 @@ class TableModel(QAbstractTableModel): row = index.row() column = index.column() - if self._headers[column] == "name": - self._undo.push( - SetNameCommand( - self._data, row, value + try: + if self._headers[column] == "name": + self._undo.push( + SetNameCommand( + self._data, row, value + ) ) - ) - elif self._headers[column] == "comment": - self._undo.push( - SetCommentCommand( - self._data, row, value + elif self._headers[column] == "comment": + self._undo.push( + SetCommentCommand( + self._data, row, value + ) ) - ) - elif self._headers[column] == "minor": - self._undo.push( - SetMinorCommand( - self._data, row, value + elif self._headers[column] == "minor": + self._undo.push( + SetMinorCommand( + self._data, row, value + ) ) - ) - elif self._headers[column] == "medium": - self._undo.push( - SetMediumCommand( - self._data, row, value + elif self._headers[column] == "medium": + self._undo.push( + SetMediumCommand( + self._data, row, value + ) ) - ) + except Exception as e: + logger.info(e) + logger.debug(traceback.format_exc()) self.dataChanged.emit(index, index) return True diff --git a/src/View/Stricklers/UndoCommand.py b/src/View/Stricklers/UndoCommand.py index e7dc733e..ee75cf99 100644 --- a/src/View/Stricklers/UndoCommand.py +++ b/src/View/Stricklers/UndoCommand.py @@ -33,7 +33,7 @@ class SetNameCommand(QUndoCommand): self._data = data self._index = index self._old = self._data.get(self._index).name - self._new = new_value + self._new = str(new_value) def undo(self): self._data.get(self._index).name = self._old @@ -48,7 +48,7 @@ class SetCommentCommand(QUndoCommand): self._data = data self._index = index self._old = self._data.get(self._index).comment - self._new = new_value + self._new = str(new_value) def undo(self): self._data.get(self._index).comment = self._old @@ -63,7 +63,7 @@ class SetMinorCommand(QUndoCommand): self._data = data self._index = index self._old = self._data.get(self._index).minor - self._new = new_value + self._new = float(new_value) def undo(self): self._data.get(self._index).minor = self._old @@ -78,7 +78,7 @@ class SetMediumCommand(QUndoCommand): self._data = data self._index = index self._old = self._data.get(self._index).medium - self._new = new_value + self._new = float(new_value) def undo(self): self._data.get(self._index).medium = self._old From 61f31403d415819071dae5a55159170f21078f13 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 4 Aug 2023 11:20:15 +0200 Subject: [PATCH 32/64] Solver: Add error message when command executable do not exists. --- src/Solver/ASolver.py | 23 +++++++++++++++++++++-- src/View/RunSolver/Window.py | 5 ++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/Solver/ASolver.py b/src/Solver/ASolver.py index bfb47aa7..b4285923 100644 --- a/src/Solver/ASolver.py +++ b/src/Solver/ASolver.py @@ -193,6 +193,11 @@ class AbstractSolver(object): exe = cmd[0] args = cmd[1:] + if not os.path.exists(exe): + error = f"[ERROR] Path {exe} do not exists" + logger.info(error) + return error + self._process.start( exe, args, ) @@ -216,6 +221,11 @@ class AbstractSolver(object): exe = cmd[0] args = cmd[1:] + if not os.path.exists(exe): + error = f"[ERROR] Path {exe} do not exists" + logger.info(error) + return error + self._process.start( exe, args, ) @@ -240,6 +250,11 @@ class AbstractSolver(object): exe = cmd[0] args = cmd[1:] + if not os.path.exists(exe): + error = f"[ERROR] Path {exe} do not exists" + logger.info(error) + return error + self._process.start( exe, args, ) @@ -255,7 +270,9 @@ class AbstractSolver(object): def _run_next(self): self._step += 1 if self._step < len(self._runs): - self._runs[self._step]() + res = self._runs[self._step]() + if res is not True: + self._output.put(res) else: self._status = STATUS.STOPED @@ -281,7 +298,9 @@ class AbstractSolver(object): ] self._step = 0 # Run first step - self._runs[0]() + res = self._runs[0]() + if res is not True: + self._output.put(res) def kill(self): if self._process is None: diff --git a/src/View/RunSolver/Window.py b/src/View/RunSolver/Window.py index dba5a16e..4f915950 100644 --- a/src/View/RunSolver/Window.py +++ b/src/View/RunSolver/Window.py @@ -198,7 +198,10 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): while self._output.qsize() != 0: s = self._output.get() - self._log(s) + if type(s) is str and "[ERROR]" in s: + self._log(s, color="red") + else: + self._log(s) def start(self): if self._solver.is_stoped(): From ec16586755ba2e74d3bd0857864e7ceacd2975a9 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 4 Aug 2023 15:00:23 +0200 Subject: [PATCH 33/64] Geometry, ListedSubWindow: Use ListedSubWindow in Geometry windows. --- src/View/ASubWindow.py | 10 ++++++---- src/View/Geometry/Profile/Window.py | 12 ++++++++---- src/View/Geometry/Window.py | 13 +++++++++---- src/View/ListedSubWindow.py | 25 ++++++++++++++++++++++++- 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/View/ASubWindow.py b/src/View/ASubWindow.py index c07465f1..d9e121f4 100644 --- a/src/View/ASubWindow.py +++ b/src/View/ASubWindow.py @@ -462,10 +462,12 @@ class ASubWindowFeatures(object): class ASubMainWindow(QMainWindow, ASubWindowFeatures, WindowToolKit): def __init__(self, name="", ui="dummy", parent=None): super(ASubMainWindow, self).__init__(parent=parent) - self.ui = loadUi( - os.path.join(os.path.dirname(__file__), "ui", f"{ui}.ui"), - self - ) + if ui is not None: + self.ui = loadUi( + os.path.join(os.path.dirname(__file__), "ui", f"{ui}.ui"), + self + ) + self.name = name self.parent = parent if self.parent is not None: diff --git a/src/View/Geometry/Profile/Window.py b/src/View/Geometry/Profile/Window.py index cfcf6925..9f7df090 100644 --- a/src/View/Geometry/Profile/Window.py +++ b/src/View/Geometry/Profile/Window.py @@ -37,7 +37,7 @@ from PyQt5.QtWidgets import ( from Model.Geometry.Reach import Reach from Model.Geometry.ProfileXYZ import ProfileXYZ -from View.ASubWindow import WindowToolKit +from View.ASubWindow import ASubMainWindow from View.Geometry.Profile.mainwindow_ui_profile import Ui_MainWindow from View.Geometry.Profile.Plot import Plot from View.Geometry.Profile.Table import * @@ -45,10 +45,14 @@ from View.Geometry.Profile.Table import * _translate = QCoreApplication.translate -class ProfileWindow(QMainWindow, WindowToolKit): - def __init__(self, profile=None, parent=None): +class ProfileWindow(ASubMainWindow): + def __init__(self, profile=None, title="Profile", parent=None): + self._title = title self.parent = parent - super(ProfileWindow, self).__init__(self.parent) + super(ProfileWindow, self).__init__( + name=self._title, + parent=self.parent + ) self.ui = Ui_MainWindow() self.ui.setupUi(self) diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index 9fd0f6f2..46e339f6 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -41,7 +41,8 @@ from View.Geometry.PlotXY import PlotXY from View.Geometry.PlotKPC import PlotKPC from View.Geometry.PlotAC import PlotAC -from View.ASubWindow import WindowToolKit +from View.ASubWindow import ASubMainWindow, WindowToolKit +from View.ListedSubWindow import ListedSubWindow from View.Geometry.mainwindow_ui_reach import Ui_MainWindow from View.Geometry.Table import * from View.Geometry.Profile.Window import ProfileWindow @@ -49,10 +50,14 @@ from View.Geometry.Profile.Window import ProfileWindow _translate = QCoreApplication.translate -class GeometryWindow(QMainWindow, WindowToolKit): - def __init__(self, model=None, parent=None): +class GeometryWindow(ASubMainWindow, ListedSubWindow): + def __init__(self, model=None, title="Geometry", parent=None): + self._title = title self.parent = parent - super(GeometryWindow, self).__init__(parent=parent) + super(GeometryWindow, self).__init__( + name=self._title, + parent=parent + ) self._model = model self._reach = model.river.current_reach().reach diff --git a/src/View/ListedSubWindow.py b/src/View/ListedSubWindow.py index 37d64234..eaef39ef 100644 --- a/src/View/ListedSubWindow.py +++ b/src/View/ListedSubWindow.py @@ -48,9 +48,32 @@ class ListedSubWindow(object): self.sub_win_cnt = len(self.sub_win_list) logger.info(f"Close window: {name} ({self.sub_win_cnt})") - def sub_win_exists(self, name): + def _sub_win_exists(self, name): return reduce( lambda acc, n: (acc or (n[0] == name)), self.sub_win_list, False ) + + def _sub_win_exists_with_contain(self, name, contain): + return reduce( + lambda acc, n: ( + acc or + ( + (n[0] == name) and + reduce( + lambda acc, a: acc and (a in n[1]._title), + contain, + True + ) + ) + ), + self.sub_win_list, + False + ) + + def sub_win_exists(self, name, contain = []): + if contain == []: + self._sub_win_exists(name) + else: + self._sub_win_exists_with_contain(name, contain) From ec9a061f9ad2502a5241eb1762709d0521cd4df6 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 4 Aug 2023 15:28:01 +0200 Subject: [PATCH 34/64] Geometry: Forbidden duplicate window. --- src/View/Geometry/Profile/Window.py | 4 +++- src/View/Geometry/Window.py | 3 ++- src/View/ListedSubWindow.py | 24 +++++++++++++++++++++--- src/View/MainWindow.py | 15 +++++++++++---- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/View/Geometry/Profile/Window.py b/src/View/Geometry/Profile/Window.py index 9f7df090..54d1e011 100644 --- a/src/View/Geometry/Profile/Window.py +++ b/src/View/Geometry/Profile/Window.py @@ -86,12 +86,14 @@ class ProfileWindow(ASubMainWindow): if (name is None) or (name == ""): name = _translate("MainWindowProfile", "(no name)") - self.setWindowTitle( + self._title = ( header + " - " + f"{self._profile.reach.name}" + " - " + f"{name} ({self._profile.kp})" ) + self.setWindowTitle(self._title) + def setup_sc(self): self._undo_stack = QUndoStack() diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index 46e339f6..851b73bb 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -80,7 +80,8 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow): self.changed_slider_value() def setup_window(self): - self.setWindowTitle(f"{self.ui.mainwindow_title} - {self._reach.name}") + self._title = f"{self.ui.mainwindow_title} - {self._reach.name}" + self.setWindowTitle(self._title) def setup_sc(self): self._undo_stack = QUndoStack() diff --git a/src/View/ListedSubWindow.py b/src/View/ListedSubWindow.py index eaef39ef..b44efd61 100644 --- a/src/View/ListedSubWindow.py +++ b/src/View/ListedSubWindow.py @@ -62,7 +62,7 @@ class ListedSubWindow(object): ( (n[0] == name) and reduce( - lambda acc, a: acc and (a in n[1]._title), + lambda acc, c: acc and (c in n[1]._title), contain, True ) @@ -74,6 +74,24 @@ class ListedSubWindow(object): def sub_win_exists(self, name, contain = []): if contain == []: - self._sub_win_exists(name) + return self._sub_win_exists(name) else: - self._sub_win_exists_with_contain(name, contain) + return self._sub_win_exists_with_contain(name, contain) + + def sub_win_filter_first(self, name, contain): + try: + return next( + filter( + lambda n: ( + (n[0] == name) and + reduce( + lambda acc, c: acc and (c in n[1]._title), + contain, + True + ) + ), + self.sub_win_list, + ) + )[1] + except: + return None diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index 8a94c469..7b03dfb7 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -455,10 +455,17 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): Returns: Nothing """ - if (self.model is not None and - self.model.river.has_current_reach()): - geometry = GeometryWindow(model=self.model, parent=self) - geometry.show() + if (self.model is not None and self.model.river.has_current_reach()): + geometry = self.sub_win_filter_first( + "Geometry", + contain = [self.model.river.current_reach().name] + ) + + if geometry == None: + geometry = GeometryWindow(model=self.model, parent=self) + geometry.show() + else: + geometry.activateWindow() else: self.msg_select_reach() From 289c8ed12923b4f3fd03d22a509d8c2e5c165623 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 4 Aug 2023 15:32:09 +0200 Subject: [PATCH 35/64] Geometry: Profile: Forbidden duplicate window for profile editing. --- src/View/Geometry/Window.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index 851b73bb..e33b6d54 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -184,13 +184,20 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow): for row in rows: profile = self._reach.profile(row) - win = ProfileWindow( - profile = profile, - parent = self, + win = self.sub_win_filter_first( + "Profile", + contain = [self._reach.name, str(profile.kp)] ) - self._profile_window.append(win) - win.show() + if win is None: + win = ProfileWindow( + profile = profile, + parent = self, + ) + self._profile_window.append(win) + win.show() + else: + win.activateWindow() self.tableView.model().blockSignals(False) From 94a0a9665936df6c56eb6bda9216943c8d524dbf Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 4 Aug 2023 15:55:25 +0200 Subject: [PATCH 36/64] BC, LC: Forbidden duplicate window. --- src/View/BoundaryCondition/Edit/Window.py | 2 +- src/View/BoundaryCondition/Window.py | 22 +++++++++++------ src/View/LateralContribution/Edit/Window.py | 8 +++---- src/View/LateralContribution/Window.py | 22 +++++++++++------ src/View/ListedSubWindow.py | 2 +- src/View/MainWindow.py | 26 +++++++++++++++++---- 6 files changed, 57 insertions(+), 25 deletions(-) diff --git a/src/View/BoundaryCondition/Edit/Window.py b/src/View/BoundaryCondition/Edit/Window.py index 9ecd240c..efcf0993 100644 --- a/src/View/BoundaryCondition/Edit/Window.py +++ b/src/View/BoundaryCondition/Edit/Window.py @@ -71,7 +71,7 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow): self._title = ( _translate("Edit boundary condition", self._title) + f" - {self._study.name} " + - f" - {self._data.name} " + + f" - {self._data.name} ({self._data.id}) " + f"({long_types[self._data.bctype]} - {node_name})" ) diff --git a/src/View/BoundaryCondition/Window.py b/src/View/BoundaryCondition/Window.py index af314574..a2853590 100644 --- a/src/View/BoundaryCondition/Window.py +++ b/src/View/BoundaryCondition/Window.py @@ -65,7 +65,7 @@ logger = logging.getLogger() class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow): def __init__(self, title="Boundary conditions", study=None, parent=None): - title = title + " - " + study.name + self._title = title + " - " + study.name super(BoundaryConditionWindow, self).__init__( name=title, ui="BoundaryConditions", parent=parent @@ -79,7 +79,7 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow): self.setup_graph() self.setup_connections() - self.ui.setWindowTitle(title) + self.ui.setWindowTitle(self._title) def setup_sc(self): self._undo_stack = QUndoStack() @@ -220,9 +220,17 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow): tab = self.current_tab() rows = self.index_selected_rows() for row in rows: - win = EditBoundaryConditionWindow( - data=self._bcs.get(tab, row), - study=self._study, - parent=self + win = self.sub_win_filter_first( + "Edit boundary condition", + contain = [f"({self._bcs.get(tab, row).id})"] ) - win.show() + + if win is None: + win = EditBoundaryConditionWindow( + data=self._bcs.get(tab, row), + study=self._study, + parent=self + ) + win.show() + else: + win.activateWindow() diff --git a/src/View/LateralContribution/Edit/Window.py b/src/View/LateralContribution/Edit/Window.py index c3459958..3a801591 100644 --- a/src/View/LateralContribution/Edit/Window.py +++ b/src/View/LateralContribution/Edit/Window.py @@ -45,7 +45,7 @@ from View.LateralContribution.Edit.Plot import Plot _translate = QCoreApplication.translate class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow): - def __init__(self, title="Edit lateral conditribution", + def __init__(self, title="Edit lateral contribution", data=None, study=None, parent=None): self._data = data self._study = study @@ -54,7 +54,7 @@ class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow): self.compute_title() super(EditLateralContributionWindow, self).__init__( - name=self._title, ui="EditLateralContribution", parent=parent + name=title, ui="EditLateralContribution", parent=parent ) self.ui.setWindowTitle(self._title) @@ -69,9 +69,9 @@ class EditLateralContributionWindow(ASubMainWindow, ListedSubWindow): edge_name = (self._data.edge.name if self._data.edge is not None else _translate("LateralContribution", "Not associate")) self._title = ( - _translate("Edit Lateral contribution", self._title) + + _translate("Edit lateral contribution", self._title) + f" - {self._study.name} " + - f" - {self._data.name} " + + f" - {self._data.name} ({self._data.id}) " + f"({long_types[self._data.lctype]} - {edge_name})" ) diff --git a/src/View/LateralContribution/Window.py b/src/View/LateralContribution/Window.py index 003ad48e..dc3dd94f 100644 --- a/src/View/LateralContribution/Window.py +++ b/src/View/LateralContribution/Window.py @@ -65,7 +65,7 @@ logger = logging.getLogger() class LateralContributionWindow(ASubMainWindow, ListedSubWindow): def __init__(self, title="Lateral contribution", study=None, parent=None): - title = title + " - " + study.name + self._title = title + " - " + study.name super(LateralContributionWindow, self).__init__( name=title, ui="LateralContributions", parent=parent @@ -79,7 +79,7 @@ class LateralContributionWindow(ASubMainWindow, ListedSubWindow): self.setup_graph() self.setup_connections() - self.ui.setWindowTitle(title) + self.ui.setWindowTitle(self._title) def setup_sc(self): self._undo_stack = QUndoStack() @@ -266,9 +266,17 @@ class LateralContributionWindow(ASubMainWindow, ListedSubWindow): tab = self.current_tab() rows = self.index_selected_rows() for row in rows: - win = EditLateralContributionWindow( - data=self._lcs.get(tab, row), - study=self._study, - parent=self + win = self.sub_win_filter_first( + "Edit lateral contribution", + contain = [f"({self._lcs.get(tab, row).id})"] ) - win.show() + + if win is None: + win = EditLateralContributionWindow( + data=self._lcs.get(tab, row), + study=self._study, + parent=self + ) + win.show() + else: + win.activateWindow() diff --git a/src/View/ListedSubWindow.py b/src/View/ListedSubWindow.py index b44efd61..b4dfe416 100644 --- a/src/View/ListedSubWindow.py +++ b/src/View/ListedSubWindow.py @@ -83,7 +83,7 @@ class ListedSubWindow(object): return next( filter( lambda n: ( - (n[0] == name) and + (name in n[0]) and reduce( lambda acc, c: acc and (c in n[1]._title), contain, diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index 7b03dfb7..8b028d1b 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -461,7 +461,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): contain = [self.model.river.current_reach().name] ) - if geometry == None: + if geometry is None: geometry = GeometryWindow(model=self.model, parent=self) geometry.show() else: @@ -470,12 +470,28 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): self.msg_select_reach() def open_boundary_cond(self): - bound = BoundaryConditionWindow(study = self.model, parent = self) - bound.show() + bound = self.sub_win_filter_first( + "Boundary conditions", + contain = [] + ) + + if bound is None: + bound = BoundaryConditionWindow(study = self.model, parent = self) + bound.show() + else: + bound.activateWindow() def open_lateral_contrib(self): - lateral = LateralContributionWindow(study = self.model, parent = self) - lateral.show() + lateral = self.sub_win_filter_first( + "Lateral contribution", + contain = [] + ) + + if lateral is None: + lateral = LateralContributionWindow(study = self.model, parent = self) + lateral.show() + else: + lateral.activateWindow() def open_stricklers(self): strick = StricklersWindow( From 254f0d0e8e78b928a68f03a76277ccc6822ffd3f Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 4 Aug 2023 16:17:18 +0200 Subject: [PATCH 37/64] Friction: Forbidden duplicate window. --- src/View/Frictions/Window.py | 20 ++++++++++++++------ src/View/MainWindow.py | 35 ++++++++++++++++++++++++++--------- src/View/Stricklers/Window.py | 4 ++-- 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/View/Frictions/Window.py b/src/View/Frictions/Window.py index d5761485..81049593 100644 --- a/src/View/Frictions/Window.py +++ b/src/View/Frictions/Window.py @@ -68,7 +68,7 @@ class FrictionsWindow(ASubMainWindow, ListedSubWindow): self.setup_title(title) super(FrictionsWindow, self).__init__( - name=self._title, ui="Frictions", parent=parent + name=title, ui="Frictions", parent=parent ) self.setup_sc() @@ -246,9 +246,17 @@ class FrictionsWindow(ASubMainWindow, ListedSubWindow): self._table.redo() def edit_stricklers(self): - self.strick = StricklersWindow( - study = self._study, - config = self.parent.conf, - parent = self + strick = self.sub_win_filter_first( + "Stricklers", + contain = [] ) - self.strick.show() + + if strick is None: + strick = StricklersWindow( + study = self._study, + config = self.parent.conf, + parent = self + ) + strick.show() + else: + strick.activateWindow() diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index 8b028d1b..08c86628 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -494,21 +494,38 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): lateral.activateWindow() def open_stricklers(self): - strick = StricklersWindow( - study = self.model, - config = self.conf, - parent = self + strick = self.sub_win_filter_first( + "Stricklers", + contain = [] ) - strick.show() + + if strick is None: + strick = StricklersWindow( + study = self.model, + config = self.conf, + parent = self + ) + strick.show() + else: + strick.activateWindow() def open_frictions(self): if (self.model is not None and self.model.river.has_current_reach()): - frictions = FrictionsWindow( - study = self.model, - parent = self + + frictions = self.sub_win_filter_first( + "Frictions", + contain = [self.model.river.current_reach().name] ) - frictions.show() + + if frictions is None: + frictions = FrictionsWindow( + study = self.model, + parent = self + ) + frictions.show() + else: + frictions.activateWindow() else: self.msg_select_reach() diff --git a/src/View/Stricklers/Window.py b/src/View/Stricklers/Window.py index 29f886cb..8726f971 100644 --- a/src/View/Stricklers/Window.py +++ b/src/View/Stricklers/Window.py @@ -51,7 +51,7 @@ logger = logging.getLogger() class StricklersWindow(ASubMainWindow, ListedSubWindow): def __init__(self, title="Stricklers", study=None, config=None, parent=None): - title = title + " - " + study.name + self._title = title + " - " + study.name super(StricklersWindow, self).__init__( name=title, ui="Stricklers", parent=parent @@ -64,7 +64,7 @@ class StricklersWindow(ASubMainWindow, ListedSubWindow): self.setup_table() self.setup_connections() - self.ui.setWindowTitle(title) + self.ui.setWindowTitle(self._title) def setup_sc(self): self._undo_stack = QUndoStack() From f4a852f8f3d33e2953461da21c60f4f2e69a8185 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 4 Aug 2023 16:37:14 +0200 Subject: [PATCH 38/64] SolverParameters: Forbidden duplicate window. --- src/View/MainWindow.py | 16 ++++++++++++---- src/View/SolverParameters/Window.py | 4 ++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index 08c86628..ad2e1c3c 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -540,11 +540,19 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): self.msg_select_reach() def open_solver_parameters(self): - params = SolverParametersWindow( - study = self.model, - parent = self + params = self.sub_win_filter_first( + "Solver parameters", + contain = [] ) - params.show() + + if params is None: + params = SolverParametersWindow( + study = self.model, + parent = self + ) + params.show() + else: + params.activateWindow() def run_solver(self): if self.model is None: diff --git a/src/View/SolverParameters/Window.py b/src/View/SolverParameters/Window.py index 9560251d..c04eebc7 100644 --- a/src/View/SolverParameters/Window.py +++ b/src/View/SolverParameters/Window.py @@ -56,7 +56,7 @@ class SolverParametersWindow(ASubMainWindow, ListedSubWindow): # Init tanslate dictionary tr.init() - title = title + " - " + study.name + self._title = title + " - " + study.name super(SolverParametersWindow, self).__init__( name=title, ui="SolverParameters", parent=parent @@ -69,7 +69,7 @@ class SolverParametersWindow(ASubMainWindow, ListedSubWindow): self.setup_table() self.setup_connections() - self.ui.setWindowTitle(title) + self.ui.setWindowTitle(self._title) def setup_sc(self): self._undo_stack = {} From 06b6d59494e4e0bfbd48a76c13135f5731ed31c8 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 4 Aug 2023 16:40:37 +0200 Subject: [PATCH 39/64] InitialConditions: Forbidden duplicate window. --- src/View/MainWindow.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index ad2e1c3c..0808ba8f 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -531,11 +531,19 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): def open_initial_conditions(self): if self.model.river.has_current_reach(): - initial = InitialConditionsWindow( - study = self.model, - parent = self + initial = self.sub_win_filter_first( + "Initial condition", + contain = [self.model.river.current_reach().name] ) - initial.show() + + if initial is None: + initial = InitialConditionsWindow( + study = self.model, + parent = self + ) + initial.show() + else: + initial.activateWindow() else: self.msg_select_reach() From 02dafd469462f574f8325b392f74a10e0a4b7dd1 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 4 Aug 2023 17:17:42 +0200 Subject: [PATCH 40/64] Solver: Fix case of space into solver path. --- src/Solver/ASolver.py | 45 +++++++++++++++++++++++++++++++++---------- src/config.py | 2 +- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/Solver/ASolver.py b/src/Solver/ASolver.py index b4285923..ca6e6f4f 100644 --- a/src/Solver/ASolver.py +++ b/src/Solver/ASolver.py @@ -189,9 +189,18 @@ class AbstractSolver(object): logger.debug(f"! {cmd}") - cmd = cmd.split() - exe = cmd[0] - args = cmd[1:] + if cmd[0] == "\"": + # Command line executable path is between " char + cmd = cmd.split("\"") + exe = cmd[1] + args = "\"".join(cmd[3:]).split(" ") + else: + # We suppose the command line executable path as no space char + cmd = cmd.replace("\ ", "&_&").split(" ") + exe = cmd[0].replace("&_&", "\ ") + args = cmd[1:] + + logger.info(f"! {exe} {args}") if not os.path.exists(exe): error = f"[ERROR] Path {exe} do not exists" @@ -215,11 +224,20 @@ class AbstractSolver(object): cmd = cmd.replace("@input", self.input_param()) cmd = cmd.replace("@dir", self._process.workingDirectory()) - logger.debug(f"! {cmd}") + logger.info(f"! {cmd}") - cmd = cmd.split() - exe = cmd[0] - args = cmd[1:] + if cmd[0] == "\"": + # Command line executable path is between " char + cmd = cmd.split("\"") + exe = cmd[1] + args = "\"".join(cmd[3:]).split(" ") + else: + # We suppose the command line executable path as no space char + cmd = cmd.replace("\ ", "&_&").split(" ") + exe = cmd[0].replace("&_&", "\ ") + args = cmd[1:] + + logger.info(f"! {exe} {args}") if not os.path.exists(exe): error = f"[ERROR] Path {exe} do not exists" @@ -246,9 +264,16 @@ class AbstractSolver(object): logger.debug(f"! {cmd}") - cmd = cmd.split() - exe = cmd[0] - args = cmd[1:] + if cmd[0] == "\"": + # Command line executable path is between " char + cmd = cmd.split("\"") + exe = cmd[1] + args = "\"".join(cmd[3:]).split(" ") + else: + # We suppose the command line executable path as no space char + cmd = cmd.replace("\ ", "&_&").split(" ") + exe = cmd[0].replace("&_&", "\ ") + args = cmd[1:] if not os.path.exists(exe): error = f"[ERROR] Path {exe} do not exists" diff --git a/src/config.py b/src/config.py index 16ec6b12..89563ecb 100644 --- a/src/config.py +++ b/src/config.py @@ -254,7 +254,7 @@ class Config(SQL): ctor = solver_type_list["mage8"] new = ctor("default-mage") new._description = "Default PAMHYR mage 8 version" - new._cmd_solver = f"""@install_dir/mage/mage{"" if posix else ".exe"} -fp=1 @input""" + new._cmd_solver = f""""@install_dir/mage/mage{"" if posix else ".exe"}" -fp=1 @input""" self._solvers.append(new) # Meshing tool From 9ecd9a8f2a138becf2e7ae9144716cfe285b2839 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 7 Aug 2023 11:20:22 +0200 Subject: [PATCH 41/64] Config: Save the last study open and keep close status. --- src/View/ASubWindow.py | 5 +++- src/View/MainWindow.py | 52 +++++++++++++++++++++++++++++++++++++++--- src/config.py | 30 +++++++++++++++++++++++- 3 files changed, 82 insertions(+), 5 deletions(-) diff --git a/src/View/ASubWindow.py b/src/View/ASubWindow.py index d9e121f4..4e1c1327 100644 --- a/src/View/ASubWindow.py +++ b/src/View/ASubWindow.py @@ -78,13 +78,14 @@ class WindowToolKit(object): return header, values - def file_dialog(self, select_file=True, callback=lambda x: None): + def file_dialog(self, select_file=True, callback=lambda x: None, directory=None): """Open a new file dialog and send result to callback function Args: select_file: Select a file if True, else select a dir callback: The callback function with one arguments, files selection list + directory: Defaut directory Returns: The returns of callback @@ -97,6 +98,8 @@ class WindowToolKit(object): mode = QFileDialog.FileMode.Directory dialog.setFileMode(mode) + if directory is not None: + dialog.setDirectory(directory) if dialog.exec_(): file_names = dialog.selectedFiles() diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index 0808ba8f..afb2de1e 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -119,6 +119,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): self.trans = QTranslator(self) #self.ui.retranslateUi() + if self.conf.last_study != "" and not self.conf.close_correctly: + self.dialog_reopen_study() + def set_title(self): if self.model is not None: self.setWindowTitle(f"PAMHYR - {self.model.name}") @@ -202,16 +205,24 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): if self.model is not None and not self.model.is_saved: self._close_question = True if self.dialog_close(): + # PAMHYR is close correctly (no crash) + self.conf.set_close_correctly() + super(ApplicationWindow, self).close() else: self._close_question = False else: + # PAMHYR is close correctly (no crash) + self.conf.set_close_correctly() + super(ApplicationWindow, self).close() def closeEvent(self, event): if not self._close_question: if self.model is not None and not self.model.is_saved: if self.dialog_close(cancel = False): + # PAMHYR is close correctly (no crash) + self.conf.set_close_correctly() super(ApplicationWindow, self).closeEvent(event) else: super(ApplicationWindow, self).closeEvent(event) @@ -264,11 +275,13 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): def set_model(self, model): self.model = model self.update_enable_action() + self.conf.set_last_study(self.model.filename) self.set_title() def close_model(self): self.model = None self.update_enable_action() + self.conf.set_close_correctly() self.set_title() def update_enable_action(self): @@ -295,6 +308,19 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): # FEATURES # ############ + def open_study(self, filename): + """Open a study + + Args: + filename: The study path + + Returns: + Nothing + """ + self.set_model(Study.open(filename)) + logger.info(f"Open Study - {self.model.name}") + self.set_title() + def save_study(self): """Save current study @@ -351,6 +377,27 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): "Geometry edition need a reach selected " "into river network window to work on it") + def dialog_reopen_study(self): + dlg = QMessageBox(self) + + dlg.setWindowTitle("Last open study") + dlg.setText("Do you want to open again the last open study?") + opt = QMessageBox.Cancel | QMessageBox.Ok #| QMessageBox.Open + + dlg.setStandardButtons(opt) + dlg.setIcon(QMessageBox.Question) + + res = dlg.exec() + + if res == QMessageBox.Ok: + self.open_study(self.conf.last_study) + return True + elif res == QMessageBox.Open: + self.open_model() + return True + elif res == QMessageBox.Cancel: + return False + def dialog_close(self, cancel = True): dlg = QMessageBox(self) @@ -411,12 +458,11 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): dialog.setDefaultSuffix(".pamhyr") #dialog.setFilter(dialog.filter() | QtCore.QDir.Hidden) dialog.setNameFilters(['PamHyr (*.pamhyr)']) + dialog.setDirectory(os.path.dirname(self.conf.last_study)) if dialog.exec_(): file_name = dialog.selectedFiles() - self.set_model(Study.open(file_name[0])) - logger.info(f"Open Study - {self.model.name}") - self.set_title() + self.open_study(file_name[0]) def open_new_study(self): """Open dialog to set new study diff --git a/src/config.py b/src/config.py index 89563ecb..d1ebb71e 100644 --- a/src/config.py +++ b/src/config.py @@ -34,7 +34,7 @@ logger = logging.getLogger() class Config(SQL): def __init__(self): - self._version = '0.0.2' + self._version = '0.0.3' self.filename = Config.filename() self.set_default_value() @@ -105,6 +105,10 @@ class Config(SQL): '' ) """) + if int(release) < 3: + self.execute(f"INSERT INTO data VALUES ('last_study', '')") + self.execute(f"INSERT INTO data VALUES ('close_correctly', 'True')") + self.commit() def _load_solver(self): @@ -176,6 +180,12 @@ class Config(SQL): v = self.execute("SELECT value FROM data WHERE key='lang'") self.lang = v[0] + # Last study + v = self.execute("SELECT value FROM data WHERE key='last_study'") + self.last_study = v[0] + v = self.execute("SELECT value FROM data WHERE key='close_correctly'") + self.close_correctly = v[0] == "True" + # Debug v = self.execute("SELECT value FROM data WHERE key='debug'") self.debug = v[0] == "True" @@ -228,6 +238,8 @@ class Config(SQL): "backup_max": self.backup_max, "editor": self.editor, "lang": self.lang, + "last_study": self.last_study, + "close_correctly": self.close_correctly, "debug": self.debug, } @@ -279,9 +291,25 @@ class Config(SQL): # Stricklers self.stricklers = StricklersList() + # Last study + self.last_study = "" + self.close_correctly = False + # Debug self.debug = False + def set_close_correctly(self): + self.close_correctly = True + self.execute(f"UPDATE data SET value='True' WHERE key='close_correctly'") + self.commit() + + def set_last_study(self, filename): + self.last_study = filename + self.close_correctly = False + self.execute(f"UPDATE data SET value='{self._sql_format(self.last_study)}' WHERE key='last_study'") + self.execute(f"UPDATE data SET value='{self.close_correctly}' WHERE key='close_correctly'") + self.commit() + @classmethod def filename(cls): file = "" From 0835900aad02a864b846d0f8180f28822b323c82 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 7 Aug 2023 12:04:18 +0200 Subject: [PATCH 42/64] BC, LC: Fix convert exceptions. --- src/Model/BoundaryCondition/BoundaryCondition.py | 11 +++++++++-- src/Model/LateralContribution/LateralContribution.py | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Model/BoundaryCondition/BoundaryCondition.py b/src/Model/BoundaryCondition/BoundaryCondition.py index 7df962d2..86e0f1d2 100644 --- a/src/Model/BoundaryCondition/BoundaryCondition.py +++ b/src/Model/BoundaryCondition/BoundaryCondition.py @@ -16,11 +16,15 @@ # -*- coding: utf-8 -*- +import logging + from tools import trace, timer, old_pamhyr_date_to_timestamp from Model.DB import SQLSubModel from Model.Except import NotImplementedMethodeError +logger = logging.getLogger() + class BoundaryCondition(SQLSubModel): _sub_classes = [] _id_cnt = 0 @@ -317,14 +321,17 @@ class BoundaryCondition(SQLSubModel): new = cls(name = self.name, status = self._status) new.node = self.node - for i, _ in self.data: + for i, _ in enumerate(self.data): new.add(i) for i in [0,1]: for j in [0,1]: if self._header[i] == new.header[j]: for ind, v in self.data: - new._set_i_c_v(ind, j, v[i]) + try: + new._set_i_c_v(ind, j, v[i]) + except Exception as e: + logger.info(e) return new diff --git a/src/Model/LateralContribution/LateralContribution.py b/src/Model/LateralContribution/LateralContribution.py index e95733bf..38cbada4 100644 --- a/src/Model/LateralContribution/LateralContribution.py +++ b/src/Model/LateralContribution/LateralContribution.py @@ -16,11 +16,15 @@ # -*- coding: utf-8 -*- +import logging + from tools import trace, timer, old_pamhyr_date_to_timestamp from Model.DB import SQLSubModel from Model.Except import NotImplementedMethodeError +logger = logging.getLogger() + class LateralContribution(SQLSubModel): _sub_classes = [] _id_cnt = 0 @@ -358,14 +362,17 @@ class LateralContribution(SQLSubModel): new.begin_kp = self.begin_kp new.end_kp = self.end_kp - for i, _ in self.data: + for i, _ in enumerate(self.data): new.add(i) for i in [0,1]: for j in [0,1]: if self._header[i] == new.header[j]: for ind, v in self.data: - new._set_i_c_v(ind, j, v[i]) + try: + new._set_i_c_v(ind, j, v[i]) + except Exception as e: + logger.info(e) self._status.modified() return new From ac12275d81630839a1712e6f84b808f0461a809f Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 7 Aug 2023 13:39:33 +0200 Subject: [PATCH 43/64] git: Remove submodule mage. --- .gitmodules | 3 --- mage | 1 - 2 files changed, 4 deletions(-) delete mode 160000 mage diff --git a/.gitmodules b/.gitmodules index 0aad7c1d..e69de29b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "mage"] - path = mage - url = https://gitlab.irstea.fr/jean-baptiste.faure/mage.git diff --git a/mage b/mage deleted file mode 160000 index 18aa9a7e..00000000 --- a/mage +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 18aa9a7e0f8415a94a40fe647d329268c6932663 From 475c9fb23c0b2062dd80fdef8c659b51a6ae210c Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 7 Aug 2023 14:26:33 +0200 Subject: [PATCH 44/64] Pamhyr: Add log file and some log display. --- src/pamhyr.py | 38 ++++++++++++++++++++++++++++++++++++-- src/tools.py | 24 ++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/pamhyr.py b/src/pamhyr.py index 0f957d70..1c7ec5ca 100755 --- a/src/pamhyr.py +++ b/src/pamhyr.py @@ -27,7 +27,8 @@ from PyQt5.QtWidgets import QApplication from config import Config from tools import ( - reset_timers, display_timers, timer + reset_timers, display_timers, timer, + logger_color_blue, logger_color_red, logger_color_green, logger_color_reset ) from View.MainWindow import ApplicationWindow @@ -35,12 +36,45 @@ from Model.Study import Study logging.basicConfig( level=logging.DEBUG, - format='[PAMHYR][%(levelname)s] %(message)s' + format=(f'[{logger_color_blue()}PAMHYR{logger_color_reset()}]' + + f'[{logger_color_green()}%(levelname)s{logger_color_reset()}]' + + ' %(message)s') ) logger = logging.getLogger() logger.setLevel(logging.INFO) +try: + log = os.path.join( + os.path.dirname(Config.filename()), "log.txt" + ) + logfile = open(log, "w+") + handler = logging.StreamHandler(logfile) + formatter = logging.Formatter('[%(asctime)s][%(levelname)s] %(message)s') + handler.setFormatter(formatter) + handler.setLevel(logging.DEBUG) + logger.addHandler(handler) +except: + logger.error("Failed to create logfile...") + def license(): + blue = lambda s: logger.info(f"{logger_color_blue()}{s}{logger_color_reset()}") + + blue("""`7MM\"""Mq. db `7MMM. ,MMF'`7MMF' `7MMF'`YMM' `MM'`7MM\"""Mq.""") + blue(""" MM `MM. ;MM: MMMb dPMM MM MM VMA ,V MM `MM.""") + blue(""" MM ,M9 ,V^MM. M YM ,M MM MM MM VMA ,V MM ,M9""") + blue(""" MMmmdM9 ,M `MM M Mb M' MM MMmmmmmmMM VMMP MMmmdM9""") + blue(""" MM AbmmmqMA M YM.P' MM MM MM MM MM YM.""") + blue(""" MM A' VML M `YM' MM MM MM MM MM `Mb.""") + blue(""".JMML. .AMA. .AMMA..JML. `' .JMML..JMML. .JMML. .JMML. .JMML. .JMM.""") + with open(os.path.abspath( + os.path.join( + os.path.dirname(__file__), + "VERSION" + ) + ), "r") as f: + version = f.readline().strip() + logger.info(f"version: {logger_color_green()}{version}{logger_color_reset()}") + logger.info("license: pamhyr Copyright (C) 2023 INRAE") logger.info("license: This program comes with ABSOLUTELY NO WARRANTY.") logger.info("license: This is free software, and you are welcome to redistribute it") diff --git a/src/tools.py b/src/tools.py index d5707c56..c345fb7f 100644 --- a/src/tools.py +++ b/src/tools.py @@ -39,6 +39,30 @@ from functools import ( logger = logging.getLogger() +def logger_color_blue(): + posix = os.name == "posix" + if posix: + return f"{Style.BRIGHT}{Fore.BLUE}" + return "" + +def logger_color_red(): + posix = os.name == "posix" + if posix: + return f"{Style.BRIGHT}{Fore.RED}" + return "" + +def logger_color_green(): + posix = os.name == "posix" + if posix: + return f"{Style.BRIGHT}{Fore.GREEN}" + return "" + +def logger_color_reset(): + posix = os.name == "posix" + if posix: + return f"{Style.RESET_ALL}" + return "" + ########## # TIMERS # ########## From cecbb6817726cb25fcceae6940eec57c8e68bd40 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 7 Aug 2023 16:03:04 +0200 Subject: [PATCH 45/64] Solver: Fix command line parsing. --- src/Solver/ASolver.py | 62 ++++++++++++++----------------------------- 1 file changed, 20 insertions(+), 42 deletions(-) diff --git a/src/Solver/ASolver.py b/src/Solver/ASolver.py index ca6e6f4f..d438af05 100644 --- a/src/Solver/ASolver.py +++ b/src/Solver/ASolver.py @@ -176,12 +176,15 @@ class AbstractSolver(object): ) ) - def run_input_data_fomater(self): - if self._cmd_input == "": - self._run_next() - return True + def _format_command(self, cmd): + """Format command line - cmd = self._cmd_input + Args: + cmd: The command line + + Returns: + The executable and list of arguments + """ cmd = cmd.replace("@install_dir", self._install_dir()) cmd = cmd.replace("@path", self._path_input) cmd = cmd.replace("@input", self.input_param()) @@ -193,7 +196,7 @@ class AbstractSolver(object): # Command line executable path is between " char cmd = cmd.split("\"") exe = cmd[1] - args = "\"".join(cmd[3:]).split(" ") + args = "\"".join(cmd[2:]).split(" ")[1:] else: # We suppose the command line executable path as no space char cmd = cmd.replace("\ ", "&_&").split(" ") @@ -201,6 +204,15 @@ class AbstractSolver(object): args = cmd[1:] logger.info(f"! {exe} {args}") + return exe, args + + def run_input_data_fomater(self): + if self._cmd_input == "": + self._run_next() + return True + + cmd = self._cmd_input + exe, args = self._format_command(cmd) if not os.path.exists(exe): error = f"[ERROR] Path {exe} do not exists" @@ -219,25 +231,7 @@ class AbstractSolver(object): return True cmd = self._cmd_solver - cmd = cmd.replace("@install_dir", self._install_dir()) - cmd = cmd.replace("@path", self._path_solver) - cmd = cmd.replace("@input", self.input_param()) - cmd = cmd.replace("@dir", self._process.workingDirectory()) - - logger.info(f"! {cmd}") - - if cmd[0] == "\"": - # Command line executable path is between " char - cmd = cmd.split("\"") - exe = cmd[1] - args = "\"".join(cmd[3:]).split(" ") - else: - # We suppose the command line executable path as no space char - cmd = cmd.replace("\ ", "&_&").split(" ") - exe = cmd[0].replace("&_&", "\ ") - args = cmd[1:] - - logger.info(f"! {exe} {args}") + exe, args = self._format_command(cmd) if not os.path.exists(exe): error = f"[ERROR] Path {exe} do not exists" @@ -257,23 +251,7 @@ class AbstractSolver(object): return True cmd = self._cmd_output - cmd = cmd.replace("@install_dir", self._install_dir()) - cmd = cmd.replace("@path", self._path_output) - cmd = cmd.replace("@input", self.input_param()) - cmd = cmd.replace("@dir", self._process.workingDirectory()) - - logger.debug(f"! {cmd}") - - if cmd[0] == "\"": - # Command line executable path is between " char - cmd = cmd.split("\"") - exe = cmd[1] - args = "\"".join(cmd[3:]).split(" ") - else: - # We suppose the command line executable path as no space char - cmd = cmd.replace("\ ", "&_&").split(" ") - exe = cmd[0].replace("&_&", "\ ") - args = cmd[1:] + exe, args = self._format_command(cmd) if not os.path.exists(exe): error = f"[ERROR] Path {exe} do not exists" From dcc6e2df2d3ba1864a60151f50b8336f839e82c6 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 7 Aug 2023 16:03:32 +0200 Subject: [PATCH 46/64] Network: Fix window duplication prohibition mechanism. --- src/View/MainWindow.py | 10 ++++++---- src/View/Network/Window.py | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index afb2de1e..d5508a10 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -490,10 +490,12 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): Returns: Nothing """ - if (self.model is not None and - not self.sub_win_exists("River network")): - self.network = NetworkWindow(model=self.model, parent=self) - self.network.show() + if self.model is not None: + if not self.sub_win_exists("River network"): + self.network = NetworkWindow(model=self.model, parent=self) + self.network.show() + else: + self.network.activateWindow() def open_geometry(self): """Open geometry window diff --git a/src/View/Network/Window.py b/src/View/Network/Window.py index 7099cea5..05051862 100644 --- a/src/View/Network/Window.py +++ b/src/View/Network/Window.py @@ -50,7 +50,7 @@ class NetworkWindow(ASubMainWindow): self.setup_title() super(NetworkWindow, self).__init__( - name=self._title, ui="Network", parent=parent + name=title, ui="Network", parent=parent ) self.ui.setWindowTitle(self._title) From 798d9198d6fca5014a9b58d89fa5a4de1923c011 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Mon, 7 Aug 2023 16:20:38 +0200 Subject: [PATCH 47/64] Solver: Fix command line parsing (again). --- src/Solver/ASolver.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Solver/ASolver.py b/src/Solver/ASolver.py index d438af05..300bb36c 100644 --- a/src/Solver/ASolver.py +++ b/src/Solver/ASolver.py @@ -176,17 +176,20 @@ class AbstractSolver(object): ) ) - def _format_command(self, cmd): + def _format_command(self, cmd, path = ""): """Format command line Args: cmd: The command line + path: Optional path string (replace @path in cmd) Returns: The executable and list of arguments """ + # HACK: Works in most case... Trust me i'm an engineer + cmd = cmd.replace("@install_dir", self._install_dir()) - cmd = cmd.replace("@path", self._path_input) + cmd = cmd.replace("@path", path.replace(" ", "\ ")) cmd = cmd.replace("@input", self.input_param()) cmd = cmd.replace("@dir", self._process.workingDirectory()) @@ -195,13 +198,13 @@ class AbstractSolver(object): if cmd[0] == "\"": # Command line executable path is between " char cmd = cmd.split("\"") - exe = cmd[1] + exe = cmd[1].replace("\ ", " ") args = "\"".join(cmd[2:]).split(" ")[1:] else: # We suppose the command line executable path as no space char cmd = cmd.replace("\ ", "&_&").split(" ") - exe = cmd[0].replace("&_&", "\ ") - args = cmd[1:] + exe = cmd[0].replace("&_&", " ") + args = list(map(lambda s: s.replace("&_&", "\ "), cmd[1:])) logger.info(f"! {exe} {args}") return exe, args @@ -212,7 +215,7 @@ class AbstractSolver(object): return True cmd = self._cmd_input - exe, args = self._format_command(cmd) + exe, args = self._format_command(cmd, self._path_input) if not os.path.exists(exe): error = f"[ERROR] Path {exe} do not exists" @@ -231,7 +234,7 @@ class AbstractSolver(object): return True cmd = self._cmd_solver - exe, args = self._format_command(cmd) + exe, args = self._format_command(cmd, self._path_solver) if not os.path.exists(exe): error = f"[ERROR] Path {exe} do not exists" @@ -251,7 +254,7 @@ class AbstractSolver(object): return True cmd = self._cmd_output - exe, args = self._format_command(cmd) + exe, args = self._format_command(cmd, self._path_output) if not os.path.exists(exe): error = f"[ERROR] Path {exe} do not exists" From d78310476ec44d52b252008208772c4899102b3d Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 8 Aug 2023 13:48:01 +0200 Subject: [PATCH 48/64] Results: Add results model, view scheme and mage results reading. --- src/Model/Saved.py | 2 +- src/Solver/ASolver.py | 14 ++++ src/Solver/Mage.py | 139 +++++++++++++++++++++++++++++++++++ src/View/RunSolver/Window.py | 15 +++- src/View/ui/SolverLog.ui | 6 ++ 5 files changed, 174 insertions(+), 2 deletions(-) diff --git a/src/Model/Saved.py b/src/Model/Saved.py index a1b91fd5..60013cde 100644 --- a/src/Model/Saved.py +++ b/src/Model/Saved.py @@ -33,5 +33,5 @@ class SavedStatus(object): self._saved = True def modified(self): - logger.debug("model status set as modified") + # logger.debug("model status set as modified") self._saved = False diff --git a/src/Solver/ASolver.py b/src/Solver/ASolver.py index 300bb36c..64cc01cb 100644 --- a/src/Solver/ASolver.py +++ b/src/Solver/ASolver.py @@ -19,6 +19,8 @@ import os import logging +from tools import timer + try: from signal import SIGTERM, SIGSTOP, SIGCONT _signal = True @@ -29,6 +31,9 @@ from enum import Enum from Model.Except import NotImplementedMethodeError +from Model.Results.Results import Results +from Model.Results.River.River import River, Reach, Profile + logger = logging.getLogger() class STATUS(Enum): @@ -164,6 +169,15 @@ class AbstractSolver(object): """ raise NotImplementedMethodeError(self, self.log_file) + ########### + # RESULTS # + ########### + + @timer + def results(self, study, repertory, qlog = None): + results = Results(study = study) + return results + ####### # Run # ####### diff --git a/src/Solver/Mage.py b/src/Solver/Mage.py index 0d43d2ef..907f5ff3 100644 --- a/src/Solver/Mage.py +++ b/src/Solver/Mage.py @@ -17,12 +17,19 @@ # -*- coding: utf-8 -*- import os +import logging +import numpy as np from tools import timer from Solver.ASolver import AbstractSolver from Checker.Mage import MageNetworkGraphChecker +from Model.Results.Results import Results +from Model.Results.River.River import River, Reach, Profile + +logger = logging.getLogger() + def mage_file_open(filepath, mode): f = open(filepath, mode) @@ -337,6 +344,21 @@ class Mage(AbstractSolver): return True + ########### + # RESULTS # + ########### + + def read_bin(self, study, repertory, results, qlog = None): + return + + @timer + def results(self, study, repertory, qlog = None): + results = Results(study = study) + + self.read_bin(study, repertory, results, qlog) + + return results + ########## # MAGE 7 # ########## @@ -450,3 +472,120 @@ class Mage8(Mage): self._export_REP(study, repertory, files, qlog) return True + + ########### + # RESULTS # + ########### + + def read_bin(self, study, repertory, results, qlog = None): + with mage_file_open(os.path.join(repertory, f"0.BIN"), "r") as f: + newline = lambda: np.fromfile(f, dtype=np.int32, count=1) + endline = lambda: np.fromfile(f, dtype=np.int32, count=1) + + read_int = lambda size: np.fromfile(f, dtype=np.int32, count=size) + read_float = lambda size: np.fromfile(f, dtype=np.float32, count=size) + read_float64 = lambda size: np.fromfile(f, dtype=np.float64, count=size) + + # Meta data (1st line) + newline() + + data = read_int(3) + + nb_reach = data[0] + nb_profile = data[1] + mage_version = data[2] + + logger.debug(f"read_bin: nb_reach = {nb_reach}") + logger.debug(f"read_bin: nb_profile = {nb_profile}") + logger.debug(f"read_bin: mage_version = {mage_version}") + + if mage_version <= 80: + msg = ( + "Read BIN files: " + + f"Possible incompatible mage version '{mage_version}', " + + "please check your solver configuration..." + ) + logger.warning(msg) + + if qlog is not None: + qlog.put("[WARNING] " + msg) + + results.set("solver_version", f"Mage8 ({mage_version})") + results.set("nb_reach", f"{nb_reach}") + results.set("nb_profile", f"{nb_profile}") + + endline() + + # Reach information (2nd line) + newline() + + reachs = [] + iprofiles = {} + reach_offset = {} + + ip_to_r = lambda i: iprofiles[ + next( + filter( + lambda k: k[0] <= i <= k[1], + iprofiles + ) + ) + ] + ip_to_ri = lambda r, i: i - reach_offset[r] + + data = read_int(2*nb_reach) + + for i in range(nb_reach): + # Add results reach to reach list + r = results.river.add(i) + reachs.append(r) + + # ID of first and last reach profiles + i1 = data[2*i] - 1 + i2 = data[2*i+1] - 1 + + # Add profile id correspondance to reach + key = (i1, i2) + iprofiles[key] = r + + # Profile ID offset + reach_offset[r] = i1 + + logger.debug(f"read_bin: iprofiles = {iprofiles}") + + endline() + + # X (3rd line) + newline() + _ = read_float(nb_profile) + endline() + + # Z and Y (4th line) + newline() + _ = read_float(3*nb_profile) + endline() + + # Data + newline() + + end = False + while not end: + n = read_int(1)[0] + timestamp = read_float64(1)[0] + key = bytearray(np.fromfile(f, dtype=np.byte, count=1)).decode() + data = read_float(n) + + logger.debug(f"read_bin: timestamp = {timestamp} sec") + for i, d in enumerate(data): + # Get reach corresponding to profile ID + reach = ip_to_r(i) + # Get profile id in reach + ri = ip_to_ri(reach, i) + + # Set data for profile RI + reach.set(ri, timestamp, key, d) + + endline() + end = newline().size <= 0 + + logger.info(reachs[0].profiles[0]._data) diff --git a/src/View/RunSolver/Window.py b/src/View/RunSolver/Window.py index 4f915950..b03a4603 100644 --- a/src/View/RunSolver/Window.py +++ b/src/View/RunSolver/Window.py @@ -16,8 +16,9 @@ # -*- coding: utf-8 -*- -import tempfile import os +import logging +import tempfile from queue import Queue from tools import trace, timer @@ -53,6 +54,8 @@ except: _translate = QCoreApplication.translate +logger = logging.getLogger() + class SelectSolverWindow(ASubWindow, ListedSubWindow): def __init__(self, title="Select solver", study=None, config=None, @@ -110,6 +113,8 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): self._config = config self._solver = solver + self._results = None + super(SolverLogWindow, self).__init__( name=self._title, ui="SolverLog", parent=parent ) @@ -169,6 +174,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): self.find(QAction, "action_pause").triggered.connect(self.pause) self.find(QAction, "action_stop").triggered.connect(self.stop) self.find(QAction, "action_log_file").triggered.connect(self.log_file) + self.find(QAction, "action_results").triggered.connect(self.results) self._alarm.timeout.connect(self.update) @@ -193,6 +199,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): self.find(QAction, "action_start").setEnabled(True) self.find(QAction, "action_pause").setEnabled(False) self.find(QAction, "action_stop").setEnabled(False) + self.find(QAction, "action_results").setEnabled(True) if self._solver.log_file() != "": self.find(QAction, "action_log_file").setEnabled(True) @@ -221,6 +228,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): self.find(QAction, "action_pause").setEnabled(False) self.find(QAction, "action_stop").setEnabled(True) self.find(QAction, "action_log_file").setEnabled(False) + self.find(QAction, "action_results").setEnabled(False) def pause(self): self._log(" *** Pause", color="blue") @@ -229,6 +237,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): self.find(QAction, "action_start").setEnabled(True) self.find(QAction, "action_pause").setEnabled(False) self.find(QAction, "action_stop").setEnabled(True) + self.find(QAction, "action_results").setEnabled(False) def stop(self): self._log(" *** Stop", color="blue") @@ -237,9 +246,13 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): self.find(QAction, "action_start").setEnabled(True) self.find(QAction, "action_pause").setEnabled(False) self.find(QAction, "action_stop").setEnabled(False) + self.find(QAction, "action_results").setEnabled(True) if self._solver.log_file() != "": self.find(QAction, "action_log_file").setEnabled(True) + def results(self): + self._results = self._solver.results(self._study, self._workdir, qlog = self._output) + def log_file(self): file_name = os.path.join(self._workdir, self._solver.log_file()) log = SolverLogFileWindow( diff --git a/src/View/ui/SolverLog.ui b/src/View/ui/SolverLog.ui index bbbc3edb..c94c57db 100644 --- a/src/View/ui/SolverLog.ui +++ b/src/View/ui/SolverLog.ui @@ -63,6 +63,7 @@ + @@ -100,6 +101,11 @@ LogFile + + + results + + From 0c750ec2447d5965aaa2ee4388b6f0b7c00ca620 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 8 Aug 2023 16:17:15 +0200 Subject: [PATCH 49/64] Results: Minor change. --- src/Solver/Mage.py | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/src/Solver/Mage.py b/src/Solver/Mage.py index 907f5ff3..cc695556 100644 --- a/src/Solver/Mage.py +++ b/src/Solver/Mage.py @@ -478,6 +478,8 @@ class Mage8(Mage): ########### def read_bin(self, study, repertory, results, qlog = None): + logger.info(f"read_bin: Start ...") + with mage_file_open(os.path.join(repertory, f"0.BIN"), "r") as f: newline = lambda: np.fromfile(f, dtype=np.int32, count=1) endline = lambda: np.fromfile(f, dtype=np.int32, count=1) @@ -523,16 +525,6 @@ class Mage8(Mage): iprofiles = {} reach_offset = {} - ip_to_r = lambda i: iprofiles[ - next( - filter( - lambda k: k[0] <= i <= k[1], - iprofiles - ) - ) - ] - ip_to_ri = lambda r, i: i - reach_offset[r] - data = read_int(2*nb_reach) for i in range(nb_reach): @@ -568,6 +560,17 @@ class Mage8(Mage): # Data newline() + ip_to_r = lambda i: iprofiles[ + next( + filter( + lambda k: k[0] <= i <= k[1], + iprofiles + ) + ) + ] + ip_to_ri = lambda r, i: i - reach_offset[r] + + ts = set() end = False while not end: n = read_int(1)[0] @@ -576,16 +579,20 @@ class Mage8(Mage): data = read_float(n) logger.debug(f"read_bin: timestamp = {timestamp} sec") - for i, d in enumerate(data): - # Get reach corresponding to profile ID - reach = ip_to_r(i) - # Get profile id in reach - ri = ip_to_ri(reach, i) + ts.add(timestamp) - # Set data for profile RI - reach.set(ri, timestamp, key, d) + if key in ["Z", "Q"]: + for i, d in enumerate(data): + # Get reach corresponding to profile ID + reach = ip_to_r(i) + # Get profile id in reach + ri = ip_to_ri(reach, i) + + # Set data for profile RI + reach.set(ri, timestamp, key, d) endline() end = newline().size <= 0 - logger.info(reachs[0].profiles[0]._data) + logger.debug(reachs[0].profiles[0]._data) + logger.info(f"read_bin: ... end with {len(ts)} timestamp read") From 1f0d49bd4def2ea9cc512898377255a0fd15c388 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 8 Aug 2023 16:36:28 +0200 Subject: [PATCH 50/64] Results: Add results model. --- src/Model/Results/Results.py | 45 ++++++++++++++++++ src/Model/Results/River/River.py | 81 ++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 src/Model/Results/Results.py create mode 100644 src/Model/Results/River/River.py diff --git a/src/Model/Results/Results.py b/src/Model/Results/Results.py new file mode 100644 index 00000000..b3a83e43 --- /dev/null +++ b/src/Model/Results/Results.py @@ -0,0 +1,45 @@ +# Results.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 . + +import logging +import numpy as np + +from copy import deepcopy +from datetime import datetime + +from Model.Results.River.River import River + +logger = logging.getLogger() + +class Results(object): + def __init__(self, study = None): + self._study = study + self._river = River(self._study) + + self._meta_data = { + # Keep results creation date + "creation_date": datetime.now(), + } + + @property + def river(self): + return self._river + + def set(self, key, value): + self._meta_data[key] = value + + def get(self, key): + return self._meta_data[key] diff --git a/src/Model/Results/River/River.py b/src/Model/Results/River/River.py new file mode 100644 index 00000000..7425f532 --- /dev/null +++ b/src/Model/Results/River/River.py @@ -0,0 +1,81 @@ +# River.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 . + +import logging + +from datetime import datetime + +logger = logging.getLogger() + +class Profile(object): + def __init__(self, profile, study): + self._study = study + self._profile = profile # Source profile in the study + self._data = {} # Dict of dict {: {: , ...}, ...} + + def set(self, timestamp, key, data): + if timestamp not in self._data: + self._data[timestamp] = {} + + self._data[timestamp][key] = data + + def get_ts(self, timestamp): + return self._data[timestamp] + + def get_key(self, timestamp): + return list( + map(lambda ts: self._data[ts][key], self._data) + ) + + def get_ts_key(self, timestamp, key): + return self._data[timestamp][key] + +class Reach(object): + def __init__(self, reach, study): + self._study = study + self._reach = reach # Source reach in the study + self._profiles = list( + map( + lambda p: Profile(p, self._study), + reach.profiles + ) + ) + + @property + def profiles(self): + return self._profiles.copy() + + def set(self, profile_id, timestamp, key, data): + self._profiles[profile_id].set(timestamp, key, data) + +class River(object): + def __init__(self, study): + self._study = study + + # Dict with timestamps as key + self._reachs = [] + + @property + def reachs(self): + return self.reachs.copy() + + def add(self, reach_id): + reachs = self._study.river.enable_edges() + + new = Reach(reachs[reach_id].reach, self._study) + + self._reachs.append(new) + return new From 6f95e514b93f39f0ba880150f406d82cc54309b5 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 8 Aug 2023 16:36:59 +0200 Subject: [PATCH 51/64] Results: Add results view file scheme and ui. --- src/View/Results/PlotAC.py | 17 ++++ src/View/Results/PlotKPC.py | 17 ++++ src/View/Results/PlotXY.py | 17 ++++ src/View/Results/Table.py | 17 ++++ src/View/Results/UndoCommand.py | 17 ++++ src/View/Results/Window.py | 174 ++++++++++++++++++++++++++++++++ src/View/Results/translate.py | 17 ++++ src/View/ui/Results.ui | 96 ++++++++++++++++++ 8 files changed, 372 insertions(+) create mode 100644 src/View/Results/PlotAC.py create mode 100644 src/View/Results/PlotKPC.py create mode 100644 src/View/Results/PlotXY.py create mode 100644 src/View/Results/Table.py create mode 100644 src/View/Results/UndoCommand.py create mode 100644 src/View/Results/Window.py create mode 100644 src/View/Results/translate.py create mode 100644 src/View/ui/Results.ui diff --git a/src/View/Results/PlotAC.py b/src/View/Results/PlotAC.py new file mode 100644 index 00000000..7c882e6e --- /dev/null +++ b/src/View/Results/PlotAC.py @@ -0,0 +1,17 @@ +# PlotAC.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# -*- coding: utf-8 -*- diff --git a/src/View/Results/PlotKPC.py b/src/View/Results/PlotKPC.py new file mode 100644 index 00000000..c044d35e --- /dev/null +++ b/src/View/Results/PlotKPC.py @@ -0,0 +1,17 @@ +# PlotKPC.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# -*- coding: utf-8 -*- diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py new file mode 100644 index 00000000..a8c4b206 --- /dev/null +++ b/src/View/Results/PlotXY.py @@ -0,0 +1,17 @@ +# PlotXY.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# -*- coding: utf-8 -*- diff --git a/src/View/Results/Table.py b/src/View/Results/Table.py new file mode 100644 index 00000000..bfe2dbaa --- /dev/null +++ b/src/View/Results/Table.py @@ -0,0 +1,17 @@ +# Table.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# -*- coding: utf-8 -*- diff --git a/src/View/Results/UndoCommand.py b/src/View/Results/UndoCommand.py new file mode 100644 index 00000000..ca18efaa --- /dev/null +++ b/src/View/Results/UndoCommand.py @@ -0,0 +1,17 @@ +# UndoCommand.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# -*- coding: utf-8 -*- diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py new file mode 100644 index 00000000..90955df5 --- /dev/null +++ b/src/View/Results/Window.py @@ -0,0 +1,174 @@ +# 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 . + +# -*- coding: utf-8 -*- + +import logging + +from tools import trace, timer + +from View.ASubWindow import ASubMainWindow +from View.ListedSubWindow import ListedSubWindow + +from PyQt5.QtGui import ( + QKeySequence, +) + +from PyQt5.QtCore import ( + Qt, QVariant, QAbstractTableModel, + QCoreApplication, QModelIndex, pyqtSlot, +) + +from PyQt5.QtWidgets import ( + QDialogButtonBox, QPushButton, QLineEdit, + QFileDialog, QTableView, QAbstractItemView, + QUndoStack, QShortcut, QAction, QItemDelegate, + QComboBox, QVBoxLayout, QHeaderView, QTabWidget, +) + +from View.Plot.MplCanvas import MplCanvas +from View.Geometry.PlotKPC import PlotKPC + +from View.Results.Table import TableModel +from View.Results.translate import * +from View.Stricklers.Window import StricklersWindow + +_translate = QCoreApplication.translate + +logger = logging.getLogger() + +class ResultsWindow(ASubMainWindow, ListedSubWindow): + def __init__(self, title="Results", + study=None, solver=None, results=None, + parent=None): + self._study = study + self._solver = solver + self._results = results + + self.setup_title(title) + + super(ResultsWindow, self).__init__( + name=title, ui="Results", parent=parent + ) + + self.setup_sc() + self.setup_table() + self.setup_graph() + self.setup_connections() + + self.ui.setWindowTitle(self._title) + + def setup_title(self, title): + self._title = ( + title + " - " + + self._study.name + " - " + + self._solver.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): + self._table = {} + + for t in ["reach", "profile"]: + table = self.find(QTableView, f"tableView_{t}") + self._table[t] = TableModel( + results = self._results, + study = self._study, + mode = t, + undo = self._undo_stack, + ) + table.setModel(self._table[t]) + + table.setSelectionBehavior(QAbstractItemView.SelectRows) + table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) + table.setAlternatingRowColors(True) + + def setup_graph(self): + self.canvas = MplCanvas(width=5, height=4, dpi=100) + self.canvas.setObjectName("canvas") + self.plot_layout = self.find(QVBoxLayout, "verticalLayout") + self.plot_layout.addWidget(self.canvas) + + # self.plot = PlotKPC( + # canvas = self.canvas, + # data = self._reach.reach, + # toolbar = None, + # display_current = False + # ) + # self.plot.draw() + + self.canvas_2 = MplCanvas(width=5, height=4, dpi=100) + self.canvas_2.setObjectName("canvas_2") + self.plot_layout_2 = self.find(QVBoxLayout, "verticalLayout_2") + self.plot_layout_2.addWidget(self.canvas_2) + + # self.plot_2 = PlotStricklers( + # canvas = self.canvas_2, + # data = self._reach, + # toolbar = None + # ) + # self.plot_2.draw() + + self.canvas_3 = MplCanvas(width=5, height=4, dpi=100) + self.canvas_3.setObjectName("canvas_3") + self.plot_layout_3 = self.find(QVBoxLayout, "verticalLayout_3") + self.plot_layout_3.addWidget(self.canvas_3) + + + def setup_connections(self): + self.undo_sc.activated.connect(self.undo) + self.redo_sc.activated.connect(self.redo) + self.copy_sc.activated.connect(self.copy) + self.paste_sc.activated.connect(self.paste) + + fun = { + "reach": self._set_current_reach, + "profile": self._set_current_profile, + } + + for t in ["reach", "profile"]: + table = self.find(QTableView, f"tableView_{t}") + + table.selectionModel()\ + .selectionChanged\ + .connect(fun[t]) + + self._table.dataChanged.connect(fun[t]) + + def _set_current_reach(self): + return + + def _set_current_profile(self): + return + + def copy(self): + logger.info("TODO: copy") + + def paste(self): + logger.info("TODO: paste") + + def undo(self): + self._table.undo() + + def redo(self): + self._table.redo() diff --git a/src/View/Results/translate.py b/src/View/Results/translate.py new file mode 100644 index 00000000..dad67d85 --- /dev/null +++ b/src/View/Results/translate.py @@ -0,0 +1,17 @@ +# 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 . + +# -*- coding: utf-8 -*- diff --git a/src/View/ui/Results.ui b/src/View/ui/Results.ui new file mode 100644 index 00000000..2f886339 --- /dev/null +++ b/src/View/ui/Results.ui @@ -0,0 +1,96 @@ + + + MainWindow + + + + 0 + 0 + 942 + 655 + + + + MainWindow + + + + + + + + + + Qt::Horizontal + + + + Qt::Vertical + + + + + + + + + + Qt::Horizontal + + + + + + + Qt::Vertical + + + true + + + true + + + + + + + Qt::Vertical + + + + Qt::Horizontal + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 942 + 22 + + + + + + + + From b31be5ac36b673d49eec2cf7cc57cea4698ebac5 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 9 Aug 2023 08:05:39 +0200 Subject: [PATCH 52/64] pamhyr: Change PAMHYR ascii art to PAMHYR2. --- src/pamhyr.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/pamhyr.py b/src/pamhyr.py index 1c7ec5ca..e67d4e82 100755 --- a/src/pamhyr.py +++ b/src/pamhyr.py @@ -61,11 +61,12 @@ def license(): blue("""`7MM\"""Mq. db `7MMM. ,MMF'`7MMF' `7MMF'`YMM' `MM'`7MM\"""Mq.""") blue(""" MM `MM. ;MM: MMMb dPMM MM MM VMA ,V MM `MM.""") - blue(""" MM ,M9 ,V^MM. M YM ,M MM MM MM VMA ,V MM ,M9""") - blue(""" MMmmdM9 ,M `MM M Mb M' MM MMmmmmmmMM VMMP MMmmdM9""") - blue(""" MM AbmmmqMA M YM.P' MM MM MM MM MM YM.""") - blue(""" MM A' VML M `YM' MM MM MM MM MM `Mb.""") - blue(""".JMML. .AMA. .AMMA..JML. `' .JMML..JMML. .JMML. .JMML. .JMML. .JMM.""") + blue(""" MM ,M9 ,V^MM. M YM ,M MM MM MM VMA ,V MM ,M9 pd*"*b.""") + blue(""" MMmmdM9 ,M `MM M Mb M' MM MMmmmmmmMM VMMP MMmmdM9 (O) j8""") + blue(""" MM AbmmmqMA M YM.P' MM MM MM MM MM YM. ,;j9""") + blue(""" MM A' VML M `YM' MM MM MM MM MM `Mb. ,-='""") + blue(""".JMML. .AMA. .AMMA..JML. `' .JMML..JMML. .JMML. .JMML. .JMML. .JMM.Ammmmmmm""") + with open(os.path.abspath( os.path.join( os.path.dirname(__file__), From d499636cb674602fb4c0964ef2bf8c3a2ca09333 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 9 Aug 2023 08:45:44 +0200 Subject: [PATCH 53/64] Results: Add tables and open window. --- src/Model/Results/Results.py | 5 ++ src/Model/Results/River/River.py | 20 ++++++- src/View/MainWindow.py | 33 ++++++++++++ src/View/Results/Table.py | 90 ++++++++++++++++++++++++++++++++ src/View/Results/Window.py | 5 +- src/View/Results/translate.py | 13 +++++ src/View/RunSolver/Window.py | 5 +- 7 files changed, 167 insertions(+), 4 deletions(-) diff --git a/src/Model/Results/Results.py b/src/Model/Results/Results.py index b3a83e43..67698f4e 100644 --- a/src/Model/Results/Results.py +++ b/src/Model/Results/Results.py @@ -34,6 +34,11 @@ class Results(object): "creation_date": datetime.now(), } + @property + def date(self): + date = self._meta_data["creation_date"] + return f"{date.isoformat(sep=' ')}" + @property def river(self): return self._river diff --git a/src/Model/Results/River/River.py b/src/Model/Results/River/River.py index 7425f532..22312a9a 100644 --- a/src/Model/Results/River/River.py +++ b/src/Model/Results/River/River.py @@ -26,6 +26,14 @@ class Profile(object): self._profile = profile # Source profile in the study self._data = {} # Dict of dict {: {: , ...}, ...} + @property + def name(self): + return self._profile.name + + @property + def kp(self): + return self._profile.kp + def set(self, timestamp, key, data): if timestamp not in self._data: self._data[timestamp] = {} @@ -54,10 +62,17 @@ class Reach(object): ) ) + @property + def name(self): + return self._reach.name + @property def profiles(self): return self._profiles.copy() + def profile(self, id): + return self._profiles[id] + def set(self, profile_id, timestamp, key, data): self._profiles[profile_id].set(timestamp, key, data) @@ -70,7 +85,10 @@ class River(object): @property def reachs(self): - return self.reachs.copy() + return self._reachs.copy() + + def reach(self, id): + return self._reachs[id] def add(self, reach_id): reachs = self._study.river.enable_edges() diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index d5508a10..559601c2 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -52,6 +52,7 @@ from View.Frictions.Window import FrictionsWindow from View.SolverParameters.Window import SolverParametersWindow from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow from View.CheckList.Window import CheckListWindow +from View.Results.Window import ResultsWindow from View.Debug.Window import ReplWindow from Model.Study import Study @@ -105,6 +106,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): # Model self.model = None + # Results + self._last_results = None + # UI self.ui = loadUi( os.path.join(os.path.dirname(__file__), "ui", "MainWindow.ui"), @@ -304,6 +308,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): for action in model_action: self.enable_actions(action, not no_model) + def set_results(self, results): + self._last_results = results + ############ # FEATURES # ############ @@ -638,6 +645,32 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): ) sol.show() + def open_solver_results(self, solver, results = None): + # If no specific results, get last results + if results is None: + results = self._last_results + + # No results available + if results is None: + return + + # Windows already opened + res = self.sub_win_filter_first( + "Results", + contain = [solver.name, results.date] + ) + + if res is None: + res = ResultsWindow( + study = self.model, + solver = solver, + results = results, + parent = self + ) + res.show() + else: + res.activateWindow() + ######### # DEBUG # ######### diff --git a/src/View/Results/Table.py b/src/View/Results/Table.py index bfe2dbaa..8e167459 100644 --- a/src/View/Results/Table.py +++ b/src/View/Results/Table.py @@ -15,3 +15,93 @@ # along with this program. If not, see . # -*- coding: utf-8 -*- + +import logging +import traceback + +from tools import timer, trace + +from PyQt5.QtGui import ( + QKeySequence, QColor +) +from PyQt5.QtCore import ( + Qt, QAbstractTableModel, QModelIndex, + QVariant, pyqtSlot, QCoreApplication, +) +from PyQt5.QtWidgets import ( + QMessageBox, QUndoCommand, QUndoStack, + QStyledItemDelegate, QLineEdit, QAbstractItemView, + QComboBox, +) + +from View.Results.translate import * + +logger = logging.getLogger() + +_translate = QCoreApplication.translate + + +class TableModel(QAbstractTableModel): + def __init__(self, results = None, study = None, mode = None, undo=None): + super(QAbstractTableModel, self).__init__() + + self._results = results + self._study = study + self._mode = mode + self._undo_stack = undo + + self._table_headers = table_headers_reach + if mode != "reach": + self._table_headers = table_headers_profile + + self._headers = list(self._table_headers.keys()) + + self._selected = 0 + self._timestamp = 0 + + def rowCount(self, parent=QModelIndex()): + if self._mode == "reach": + return len(self._results.river.reachs) + + current_reach = self._results.river.reach(self._selected) + return len(current_reach.profiles) + + def columnCount(self, parent=QModelIndex()): + return len(self._headers) + + def data(self, index, role=Qt.DisplayRole): + if role != Qt.ItemDataRole.DisplayRole: + return QVariant() + + row = index.row() + column = index.column() + + if self._mode == "reach": + if self._headers[column] == "name": + v = self._results.river.reach(row).name + return str(v) + else: + current_reach = self._results.river.reach(self._selected) + if self._headers[column] == "name": + v = current_reach.profile(row).name + return str(v) + elif self._headers[column] == "kp": + v = current_reach.profile(row).kp + return f"{v:.4f}" + + return QVariant() + + def headerData(self, section, orientation, role=Qt.DisplayRole): + if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal: + return self._table_headers[self._headers[section]] + + return QVariant() + + def index(self, row, column, parent=QModelIndex()): + if not self.hasIndex(row, column, parent): + return QModelIndex() + + return self.createIndex(row, column, QModelIndex()) + + def flags(self, index): + return Qt.ItemIsEnabled | Qt.ItemIsSelectable diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py index 90955df5..e4c1b65c 100644 --- a/src/View/Results/Window.py +++ b/src/View/Results/Window.py @@ -75,7 +75,8 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): self._title = ( title + " - " + self._study.name + " - " - + self._solver.name + + self._solver.name + " - " + + self._results.date ) def setup_sc(self): @@ -153,7 +154,7 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): .selectionChanged\ .connect(fun[t]) - self._table.dataChanged.connect(fun[t]) + self._table[t].dataChanged.connect(fun[t]) def _set_current_reach(self): return diff --git a/src/View/Results/translate.py b/src/View/Results/translate.py index dad67d85..4b5ab3c5 100644 --- a/src/View/Results/translate.py +++ b/src/View/Results/translate.py @@ -15,3 +15,16 @@ # along with this program. If not, see . # -*- coding: utf-8 -*- + +from PyQt5.QtCore import QCoreApplication + +_translate = QCoreApplication.translate + +table_headers_reach = { + "name": _translate("Results", "Reach name"), +} + +table_headers_profile = { + "name": _translate("Results", "Name"), + "kp": _translate("Results", "KP (m)"), +} diff --git a/src/View/RunSolver/Window.py b/src/View/RunSolver/Window.py index b03a4603..872d72ef 100644 --- a/src/View/RunSolver/Window.py +++ b/src/View/RunSolver/Window.py @@ -219,6 +219,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): self._process = self.new_process(self._parent) self._log(" *** Start", color="blue") + self._results = None self._solver.start(self._process) self.find(QAction, "action_start").setEnabled(False) @@ -251,7 +252,9 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow): self.find(QAction, "action_log_file").setEnabled(True) def results(self): - self._results = self._solver.results(self._study, self._workdir, qlog = self._output) + if self._results is None: + self._results = self._solver.results(self._study, self._workdir, qlog = self._output) + self._parent.open_solver_results(self._solver, self._results) def log_file(self): file_name = os.path.join(self._workdir, self._solver.log_file()) From 2faab43aed65332040ab53666bac0c5c47f95c65 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 9 Aug 2023 10:36:57 +0200 Subject: [PATCH 54/64] Results: Add XY plot (without water zone) --- src/Model/Results/River/River.py | 8 ++ src/View/Results/PlotXY.py | 121 +++++++++++++++++++++++++++++++ src/View/Results/Window.py | 18 +++-- 3 files changed, 139 insertions(+), 8 deletions(-) diff --git a/src/Model/Results/River/River.py b/src/Model/Results/River/River.py index 22312a9a..ae8b33c0 100644 --- a/src/Model/Results/River/River.py +++ b/src/Model/Results/River/River.py @@ -34,6 +34,10 @@ class Profile(object): def kp(self): return self._profile.kp + @property + def geometry(self): + return self._profile + def set(self, timestamp, key, data): if timestamp not in self._data: self._data[timestamp] = {} @@ -66,6 +70,10 @@ class Reach(object): def name(self): return self._reach.name + @property + def geometry(self): + return self._reach + @property def profiles(self): return self._profiles.copy() diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py index a8c4b206..43934073 100644 --- a/src/View/Results/PlotXY.py +++ b/src/View/Results/PlotXY.py @@ -15,3 +15,124 @@ # along with this program. If not, see . # -*- coding: utf-8 -*- + +from tools import timer, trace +from View.Plot.APlot import APlot + +from PyQt5.QtCore import ( + QCoreApplication +) + +_translate = QCoreApplication.translate + +class PlotXY(APlot): + def __init__(self, canvas=None, results=None, + reach_id=0, profile_id=0, + toolbar=None, display_current=True): + super(PlotXY, self).__init__( + canvas=canvas, + data=results, + toolbar=toolbar + ) + + self.display_current = display_current + + self.line_xy = [] + self.line_gl = [] + + self._current_reach_id = reach_id + self._current_profile_id = profile_id + + @property + def results(self): + return self.data + + @timer + def draw(self, highlight=None): + self.canvas.axes.cla() + self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5) + + if self.results is None: + return + + reach = self.results.river.reach(self._current_reach_id) + + if reach.geometry.number_profiles == 0: + self._init = False + return + + kp_min, kp_max = (-1, -1) + if highlight is not None: + kp_min, kp_max = highlight + + # Axes + self.canvas.axes.set_xlabel( + _translate("Results", "X (m)"), + color='green', fontsize=12 + ) + self.canvas.axes.set_ylabel( + _translate("Results", "Y (m)"), + color='green', fontsize=12 + ) + self.canvas.axes.axis("equal") + + kp = reach.geometry.get_kp() + self.canvas.axes.set_xlim( + left = min(kp), right = max(kp) + ) + + # Draw line for each profile + self.line_xy = [ + self.canvas.axes.plot( + x, y, lw=1., + color='b' if kp_min <= kp <= kp_max else 'r', + markersize=3, marker='+' + ) + for x, y, kp in zip( + reach.geometry.get_x(), + reach.geometry.get_y(), + kp + ) + ] + + # Guide lines + x_complete = reach.geometry.get_guidelines_x() + y_complete = reach.geometry.get_guidelines_y() + + self.line_gl = [ + self.canvas.axes.plot( + x, y, + ) + for x, y in zip(x_complete, y_complete) + ] + + if self.display_current: + # Current profile + profile = reach.geometry.profile(self._current_profile_id) + + self.plot_selected, = self.canvas.axes.plot( + profile.x(), + profile.y(), + lw=1., markersize=3, + marker='+', color="b" + ) + self.plot_selected.set_visible(False) + + self.canvas.axes.autoscale_view(True, True, True) + self.canvas.axes.autoscale() + self.canvas.figure.tight_layout() + self.canvas.figure.canvas.draw_idle() + if self.toolbar is not None: + self.toolbar.update() + + def set_reach(self, reach_id): + self._current_reach_id = reach_id + self._current_profile_id = 0 + self.draw() + + def set_profile(self, profile_id): + self._current_profile_id = profile_id + self.draw() + + def update(self): + self.draw() diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py index e4c1b65c..e2d3f8b3 100644 --- a/src/View/Results/Window.py +++ b/src/View/Results/Window.py @@ -40,8 +40,8 @@ from PyQt5.QtWidgets import ( ) from View.Plot.MplCanvas import MplCanvas -from View.Geometry.PlotKPC import PlotKPC +from View.Results.PlotXY import PlotXY from View.Results.Table import TableModel from View.Results.translate import * from View.Stricklers.Window import StricklersWindow @@ -110,13 +110,15 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): self.plot_layout = self.find(QVBoxLayout, "verticalLayout") self.plot_layout.addWidget(self.canvas) - # self.plot = PlotKPC( - # canvas = self.canvas, - # data = self._reach.reach, - # toolbar = None, - # display_current = False - # ) - # self.plot.draw() + self.plot_xy = PlotXY( + canvas = self.canvas, + results = self._results, + reach_id = 0, + profile_id = 0, + toolbar = None, + display_current = False + ) + self.plot_xy.draw() self.canvas_2 = MplCanvas(width=5, height=4, dpi=100) self.canvas_2.setObjectName("canvas_2") From b04e325ab5d2a4fb4394fb1c55445e8e53dd16f8 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 9 Aug 2023 11:00:07 +0200 Subject: [PATCH 55/64] Results: PlotXY: Add water level. --- src/Model/Results/River/River.py | 2 +- src/Solver/Mage.py | 1 + src/View/Results/PlotXY.py | 32 +++++++++++++++++++++++++++++++- src/View/Results/Window.py | 11 +++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/Model/Results/River/River.py b/src/Model/Results/River/River.py index ae8b33c0..5ae1e90f 100644 --- a/src/Model/Results/River/River.py +++ b/src/Model/Results/River/River.py @@ -47,7 +47,7 @@ class Profile(object): def get_ts(self, timestamp): return self._data[timestamp] - def get_key(self, timestamp): + def get_key(self, key): return list( map(lambda ts: self._data[ts][key], self._data) ) diff --git a/src/Solver/Mage.py b/src/Solver/Mage.py index cc695556..6c129f88 100644 --- a/src/Solver/Mage.py +++ b/src/Solver/Mage.py @@ -595,4 +595,5 @@ class Mage8(Mage): end = newline().size <= 0 logger.debug(reachs[0].profiles[0]._data) + results.set("timestamps", ts) logger.info(f"read_bin: ... end with {len(ts)} timestamp read") diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py index 43934073..a0af6a2d 100644 --- a/src/View/Results/PlotXY.py +++ b/src/View/Results/PlotXY.py @@ -16,6 +16,8 @@ # -*- coding: utf-8 -*- +from functools import reduce + from tools import timer, trace from View.Plot.APlot import APlot @@ -40,6 +42,7 @@ class PlotXY(APlot): self.line_xy = [] self.line_gl = [] + self._current_timestamp = max(results.get("timestamps")) self._current_reach_id = reach_id self._current_profile_id = profile_id @@ -106,9 +109,32 @@ class PlotXY(APlot): for x, y in zip(x_complete, y_complete) ] + # Display point under water + for profile in reach.profiles: + water_z = profile.get_ts_key( + self._current_timestamp, "Z" + ) + pgeo = profile.geometry + + x, y = reduce( + lambda acc, pts: (acc[0] + [pts.x], acc[1] + [pts.y]), + filter( + lambda pts: pts.z < water_z, + pgeo.points + ), + ([], []) + ) + + self.canvas.axes.plot( + x, y, lw=1., + color='b', + markersize=4, + marker='o' + ) + if self.display_current: # Current profile - profile = reach.geometry.profile(self._current_profile_id) + profile = reach.profile(self._current_profile_id).geometry self.plot_selected, = self.canvas.axes.plot( profile.x(), @@ -134,5 +160,9 @@ class PlotXY(APlot): self._current_profile_id = profile_id self.draw() + def set_timestamp(self, timestamp): + self._current_timestamp = timestamp + self.draw() + def update(self): self.draw() diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py index e2d3f8b3..66845431 100644 --- a/src/View/Results/Window.py +++ b/src/View/Results/Window.py @@ -158,6 +158,17 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): self._table[t].dataChanged.connect(fun[t]) + def plotXY(self, reach_id = None, profile_id = None, timestamp = None): + if reach_id is not None: + self.plot_xy.set_reach(reach_id) + if profile_id is not None: + self.plot_xy.set_profile(profile_id) + if timestamp is not None: + self.plot_xy.set_timestamp(timestamp) + + self.plot_xy.draw() + + def _set_current_reach(self): return From 05411c468daba087ef29fa09e2ef702332bb9c71 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 9 Aug 2023 11:54:52 +0200 Subject: [PATCH 56/64] Results: Connect sliders. --- src/View/Results/Window.py | 36 ++++++++++++++++++++++++++++++++++-- src/View/ui/Results.ui | 6 +++--- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py index 66845431..dbf335f0 100644 --- a/src/View/Results/Window.py +++ b/src/View/Results/Window.py @@ -37,6 +37,7 @@ from PyQt5.QtWidgets import ( QFileDialog, QTableView, QAbstractItemView, QUndoStack, QShortcut, QAction, QItemDelegate, QComboBox, QVBoxLayout, QHeaderView, QTabWidget, + QSlider, ) from View.Plot.MplCanvas import MplCanvas @@ -58,6 +59,8 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): self._solver = solver self._results = results + self._timestamps = sorted(list(self._results.get("timestamps"))) + self.setup_title(title) super(ResultsWindow, self).__init__( @@ -67,6 +70,7 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): self.setup_sc() self.setup_table() self.setup_graph() + self.setup_slider() self.setup_connections() self.ui.setWindowTitle(self._title) @@ -104,6 +108,14 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.setAlternatingRowColors(True) + def setup_slider(self): + self._slider_profile = self.find(QSlider, f"verticalSlider_profile") + default_reach = self._results.river.reach(0) + self._slider_profile.setMaximum(len(default_reach.profiles) - 1) + + self._slider_time = self.find(QSlider, f"horizontalSlider_time") + self._slider_time.setMaximum(len(self._timestamps) - 1) + def setup_graph(self): self.canvas = MplCanvas(width=5, height=4, dpi=100) self.canvas.setObjectName("canvas") @@ -158,7 +170,11 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): self._table[t].dataChanged.connect(fun[t]) - def plotXY(self, reach_id = None, profile_id = None, timestamp = None): + self._slider_profile.valueChanged.connect(self._set_current_profile_slider) + self._slider_time.valueChanged.connect(self._set_current_timestamp) + + + def update(self, reach_id = None, profile_id = None, timestamp = None): if reach_id is not None: self.plot_xy.set_reach(reach_id) if profile_id is not None: @@ -170,11 +186,27 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): def _set_current_reach(self): - return + table = self.find(QTableView, f"tableView_reach") + indexes = table.selectedIndexes() + + self.update(reach_id = indexes[0]) def _set_current_profile(self): + table = self.find(QTableView, f"tableView_profile") + indexes = table.selectedIndexes() + + self.update(profile_id = indexes[0]) + + def _set_current_profile_slider(self): + pid = self._slider_profile.value() + self.update(profile_id = pid) + return + def _set_current_timestamp(self): + timestamp = self._timestamps[self._slider_time.value()] + self.update(timestamp = timestamp) + def copy(self): logger.info("TODO: copy") diff --git a/src/View/ui/Results.ui b/src/View/ui/Results.ui index 2f886339..64cde207 100644 --- a/src/View/ui/Results.ui +++ b/src/View/ui/Results.ui @@ -30,17 +30,17 @@ - + - + Qt::Horizontal - + Qt::Vertical From 2ba3c16a9876fb510e1b3ef35ce7f3d768177c71 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 9 Aug 2023 15:40:20 +0200 Subject: [PATCH 57/64] Results: Add the 2 last plot into results view. --- src/View/InitialConditions/PlotDKP.py | 2 +- src/View/Results/PlotAC.py | 98 +++++++++++++++++++++++++++ src/View/Results/PlotKPC.py | 95 ++++++++++++++++++++++++++ src/View/Results/PlotXY.py | 2 +- src/View/Results/Window.py | 41 ++++++++--- 5 files changed, 228 insertions(+), 10 deletions(-) diff --git a/src/View/InitialConditions/PlotDKP.py b/src/View/InitialConditions/PlotDKP.py index 23752aef..58a83219 100644 --- a/src/View/InitialConditions/PlotDKP.py +++ b/src/View/InitialConditions/PlotDKP.py @@ -42,7 +42,7 @@ class PlotDKP(APlot): return self.canvas.axes.set_ylabel( - _translate("MainWindow_reach", "Draft (m)"), + _translate("MainWindow_reach", "Elevation (m)"), color='green', fontsize=11 ) self.canvas.axes.set_xlabel( diff --git a/src/View/Results/PlotAC.py b/src/View/Results/PlotAC.py index 7c882e6e..f0e4b0e2 100644 --- a/src/View/Results/PlotAC.py +++ b/src/View/Results/PlotAC.py @@ -15,3 +15,101 @@ # along with this program. If not, see . # -*- coding: utf-8 -*- + +from tools import timer +from View.Plot.APlot import APlot + +from PyQt5.QtCore import ( + QCoreApplication +) + +_translate = QCoreApplication.translate + +class PlotAC(APlot): + def __init__(self, canvas=None, results=None, + reach_id=0, profile_id=0, + toolbar=None): + super(PlotAC, self).__init__( + canvas=canvas, + data=results, + toolbar=toolbar + ) + + self._current_timestamp = max(results.get("timestamps")) + self._current_reach_id = reach_id + self._current_profile_id = profile_id + + @property + def results(self): + return self.data + + @timer + def draw(self, highlight=None): + self.canvas.axes.cla() + self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5) + + if self.results is None: + return + + self.canvas.axes.set_xlabel( + _translate("MainWindow_reach", "X (m)"), + color='green', fontsize=11 + ) + self.canvas.axes.set_ylabel( + _translate("MainWindow_reach", "Elevation (m)"), + color='green', fontsize=11 + ) + + reach = self.results.river.reach(self._current_reach_id) + profile = reach.profile(self._current_profile_id) + x = profile.geometry.get_station() + z = profile.geometry.z() + + self.canvas.axes.set_xlim( + left = min(x), right = max(x) + ) + + self.line_kp, = self.canvas.axes.plot( + x, z, + linestyle="solid", + lw=1.8, + color='grey', + ) + + kp = reach.geometry.get_kp() + + # Water elevation + water_z = profile.get_ts_key(self._current_timestamp, "Z") + + self.canvas.axes.plot( + [min(x), max(x)], [water_z, water_z], + lw=1., color='b', + ) + + x_z = list(map(lambda _: water_z, x)) + self.canvas.axes.fill_between( + x, z, water_z, + where=z <= water_z, + color='blue', alpha=0.5, interpolate=True + ) + + self.canvas.figure.tight_layout() + self.canvas.figure.canvas.draw_idle() + if self.toolbar is not None: + self.toolbar.update() + + def set_reach(self, reach_id): + self._current_reach_id = reach_id + self._current_profile_id = 0 + self.draw() + + def set_profile(self, profile_id): + self._current_profile_id = profile_id + self.draw() + + def set_timestamp(self, timestamp): + self._current_timestamp = timestamp + self.draw() + + def update(self): + self.draw() diff --git a/src/View/Results/PlotKPC.py b/src/View/Results/PlotKPC.py index c044d35e..4d7f69a6 100644 --- a/src/View/Results/PlotKPC.py +++ b/src/View/Results/PlotKPC.py @@ -15,3 +15,98 @@ # along with this program. If not, see . # -*- coding: utf-8 -*- + +from tools import timer +from View.Plot.APlot import APlot + +from PyQt5.QtCore import ( + QCoreApplication +) + +_translate = QCoreApplication.translate + +class PlotKPC(APlot): + def __init__(self, canvas=None, results=None, + reach_id=0, profile_id=0, + toolbar=None): + super(PlotKPC, self).__init__( + canvas=canvas, + data=results, + toolbar=toolbar + ) + + self._current_timestamp = max(results.get("timestamps")) + self._current_reach_id = reach_id + self._current_profile_id = profile_id + + @property + def results(self): + return self.data + + @timer + def draw(self, highlight=None): + self.canvas.axes.cla() + self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5) + + if self.results is None: + return + + reach = self.results.river.reach(self._current_reach_id) + + self.canvas.axes.set_ylabel( + _translate("MainWindow_reach", "Elevation (m)"), + color='green', fontsize=11 + ) + self.canvas.axes.set_xlabel( + _translate("MainWindow_reach", "KP (m)"), + color='green', fontsize=11 + ) + + kp = reach.geometry.get_kp() + z_min = reach.geometry.get_z_min() + + self.canvas.axes.set_xlim( + left = min(kp), right = max(kp) + ) + + self.line_kp_zmin = self.canvas.axes.plot( + kp, z_min, + color='grey', lw=1. + ) + + if len(reach.geometry.profiles) != 0: + kp = reach.geometry.get_kp() + + # Water elevation + water_z = list( + map( + lambda p: p.get_ts_key(self._current_timestamp, "Z"), + reach.profiles + ) + ) + + self.canvas.axes.plot( + kp, water_z, lw=1., + color='b', + ) + + self.canvas.figure.tight_layout() + self.canvas.figure.canvas.draw_idle() + if self.toolbar is not None: + self.toolbar.update() + + def set_reach(self, reach_id): + self._current_reach_id = reach_id + self._current_profile_id = 0 + self.draw() + + def set_profile(self, profile_id): + self._current_profile_id = profile_id + self.draw() + + def set_timestamp(self, timestamp): + self._current_timestamp = timestamp + self.draw() + + def update(self): + self.draw() diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py index a0af6a2d..905692a3 100644 --- a/src/View/Results/PlotXY.py +++ b/src/View/Results/PlotXY.py @@ -88,7 +88,7 @@ class PlotXY(APlot): self.line_xy = [ self.canvas.axes.plot( x, y, lw=1., - color='b' if kp_min <= kp <= kp_max else 'r', + color='b' if kp_min <= kp <= kp_max else 'grey', markersize=3, marker='+' ) for x, y, kp in zip( diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py index dbf335f0..4ae5293e 100644 --- a/src/View/Results/Window.py +++ b/src/View/Results/Window.py @@ -43,6 +43,9 @@ from PyQt5.QtWidgets import ( from View.Plot.MplCanvas import MplCanvas from View.Results.PlotXY import PlotXY +from View.Results.PlotAC import PlotAC +from View.Results.PlotKPC import PlotKPC + from View.Results.Table import TableModel from View.Results.translate import * from View.Stricklers.Window import StricklersWindow @@ -112,9 +115,11 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): self._slider_profile = self.find(QSlider, f"verticalSlider_profile") default_reach = self._results.river.reach(0) self._slider_profile.setMaximum(len(default_reach.profiles) - 1) + self._slider_profile.setValue(0) self._slider_time = self.find(QSlider, f"horizontalSlider_time") self._slider_time.setMaximum(len(self._timestamps) - 1) + self._slider_time.setValue(len(self._timestamps) - 1) def setup_graph(self): self.canvas = MplCanvas(width=5, height=4, dpi=100) @@ -137,18 +142,28 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): self.plot_layout_2 = self.find(QVBoxLayout, "verticalLayout_2") self.plot_layout_2.addWidget(self.canvas_2) - # self.plot_2 = PlotStricklers( - # canvas = self.canvas_2, - # data = self._reach, - # toolbar = None - # ) - # self.plot_2.draw() + self.plot_kpc = PlotKPC( + canvas = self.canvas_2, + results = self._results, + reach_id = 0, + profile_id = 0, + toolbar = None + ) + self.plot_kpc.draw() self.canvas_3 = MplCanvas(width=5, height=4, dpi=100) self.canvas_3.setObjectName("canvas_3") self.plot_layout_3 = self.find(QVBoxLayout, "verticalLayout_3") self.plot_layout_3.addWidget(self.canvas_3) + self.plot_ac = PlotAC( + canvas = self.canvas_3, + results = self._results, + reach_id = 0, + profile_id = 0, + toolbar = None + ) + self.plot_ac.draw() def setup_connections(self): self.undo_sc.activated.connect(self.undo) @@ -177,25 +192,35 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): def update(self, reach_id = None, profile_id = None, timestamp = None): if reach_id is not None: self.plot_xy.set_reach(reach_id) + self.plot_ac.set_reach(reach_id) + self.plot_kpc.set_reach(reach_id) if profile_id is not None: self.plot_xy.set_profile(profile_id) + self.plot_ac.set_profile(profile_id) + self.plot_kpc.set_profile(profile_id) if timestamp is not None: self.plot_xy.set_timestamp(timestamp) + self.plot_ac.set_timestamp(timestamp) + self.plot_kpc.set_timestamp(timestamp) self.plot_xy.draw() + self.plot_ac.draw() + self.plot_kpc.draw() def _set_current_reach(self): table = self.find(QTableView, f"tableView_reach") indexes = table.selectedIndexes() - self.update(reach_id = indexes[0]) + self.update(reach_id = indexes[0].row()) def _set_current_profile(self): table = self.find(QTableView, f"tableView_profile") indexes = table.selectedIndexes() - self.update(profile_id = indexes[0]) + ind = indexes[0].row() + self.update(profile_id = ind) + self._slider_profile.setValue(ind) def _set_current_profile_slider(self): pid = self._slider_profile.value() From bf80d870d397d9c52b5ffe5a414a2e150565cece Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 9 Aug 2023 15:40:57 +0200 Subject: [PATCH 58/64] pamhyr: Minor change. --- src/pamhyr.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pamhyr.py b/src/pamhyr.py index e67d4e82..55172c78 100755 --- a/src/pamhyr.py +++ b/src/pamhyr.py @@ -61,11 +61,11 @@ def license(): blue("""`7MM\"""Mq. db `7MMM. ,MMF'`7MMF' `7MMF'`YMM' `MM'`7MM\"""Mq.""") blue(""" MM `MM. ;MM: MMMb dPMM MM MM VMA ,V MM `MM.""") - blue(""" MM ,M9 ,V^MM. M YM ,M MM MM MM VMA ,V MM ,M9 pd*"*b.""") - blue(""" MMmmdM9 ,M `MM M Mb M' MM MMmmmmmmMM VMMP MMmmdM9 (O) j8""") - blue(""" MM AbmmmqMA M YM.P' MM MM MM MM MM YM. ,;j9""") - blue(""" MM A' VML M `YM' MM MM MM MM MM `Mb. ,-='""") - blue(""".JMML. .AMA. .AMMA..JML. `' .JMML..JMML. .JMML. .JMML. .JMML. .JMM.Ammmmmmm""") + blue(""" MM ,M9 ,V^MM. M YM ,M MM MM MM VMA ,V MM ,M9 pd*"*b.""") + blue(""" MMmmdM9 ,M `MM M Mb M' MM MMmmmmmmMM VMMP MMmmdM9 (O) j8""") + blue(""" MM AbmmmqMA M YM.P' MM MM MM MM MM YM. ,;j9""") + blue(""" MM A' VML M `YM' MM MM MM MM MM `Mb. ,-='""") + blue(""".JMML. .AMA. .AMMA..JML. `' .JMML..JMML. .JMML. .JMML. .JMML. .JMM. Ammmmmmm""") with open(os.path.abspath( os.path.join( From 24bc3738277a7c69a9de1cbd280927a4c0d88bea Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 9 Aug 2023 15:41:48 +0200 Subject: [PATCH 59/64] trans: Update (incomplete). --- src/lang/fr.ts | 246 +++++++++++++++++++++++++++++-------------------- 1 file changed, 144 insertions(+), 102 deletions(-) diff --git a/src/lang/fr.ts b/src/lang/fr.ts index e3581eb9..9bc3f345 100644 --- a/src/lang/fr.ts +++ b/src/lang/fr.ts @@ -1,6 +1,5 @@ - - + About @@ -12,7 +11,7 @@ BoundaryCondition - + Not associate Non associer @@ -93,9 +92,14 @@ - Discharge (m³/s) + Discharge (m³/s) Débit (m³/s) + + + Discharge (m³/s) + + Checker @@ -502,7 +506,7 @@ Frictions - + Not defined Non définie @@ -535,27 +539,27 @@ Geometry - + Name Nom - + Kp (m) Pk (m) - + Type Type - + upstream amont - + downstream aval @@ -583,7 +587,7 @@ Commentaire - + Not associate Non associer @@ -679,9 +683,14 @@ - Discharge (m³/s) + Discharge (m³/s) Débit (m³/s) + + + Discharge (m³/s) + + MainWindow @@ -1301,22 +1310,22 @@ Ressayer la vérification - + Stop Stopper - + Start Commencer - + Pause Pause - + LogFile Fichier de log @@ -1385,41 +1394,46 @@ Define initial conditions Définire les conditions initiales - + Édition des Tronçons - + Ouvrir une étude - + Enrégistrer étude en cours (Ctrl+S) - + Fermer étude en cours (Ctrl+F) + + + results + + - + MainWindowProfile - + Profile - + (no name) - + Quittez ? @@ -1439,34 +1453,34 @@ - + Nom - + Abs en travers (m) - + La cote du fond Z minimale - + La cote maximale Z maximale - + Rive gauche - + Rive droite @@ -1480,102 +1494,102 @@ Cote (m) - - + + Suppression les lignes incomplètes - - + + Supprimer les lignes des cellules non renseignées ? - - + + Suppression des noms répétés - - + + Etes-vous sûr de vouloir quitter ? - + Insérer un point - + Supprimer le/les point(s) sélectionnés - + Trier les points par ordre décroissant de X - + Trier les points par ordre décroissant de Y - + Décaler le point sélectionné vers le haut - + Décaler le point sélectionné vers le bas - + Exporter (dans un fichier) les points du profil au format tabulé - + Copier la sélection au format tabulé - + Coller la sélection depuis le presse-papier au format tabulé - + Vérifier la validité de la saisie et garder ou pas les modifications apportées - + Annuler toutes les modifications depuis la dernière validation - + Annuler toutes les modifications et revenir à l'état initial - + Ligne d'eau : - Z : Cote (m) - A : Aire mouillée (mu00B2) - p : Périmètre mouillé (m) - L : Largeur au miroir (m) + Z : Cote (m) + A : Aire mouillée (mu00B2) + p : Périmètre mouillé (m) + L : Largeur au miroir (m) - + 'Maj + Clic' : Ligne d'eau & 'Ctrl + Clic' : Sélectionner des points - - + + Abscisse en travers calculée en projétant les points sur le plan défini par les deux points nommés extrêmes @@ -1594,37 +1608,37 @@ sur le plan défini par les deux points nommés extrêmes Pk (m) - + Ouvrir un fichier - + Fichiers .ST (*.ST) - + Fichiers .M (*.M) - + Tous les fichiers (*) - + Kp : - + Files .ST(*.ST or *.st) - + All files (*) @@ -1719,11 +1733,6 @@ Ordre des sections : Amont --> Aval Y (m) - - - Draft (m) - - KP (m) @@ -1734,141 +1743,174 @@ Ordre des sections : Amont --> Aval Discharge (m^3/s) Débit (m³/s) - + Choisissez un nom de fichier à sauvegarder - - + + Édition des profils sélectionnés - - + + Vous avez sélectionné plus de 5 profils. Seuls les 5 premiers seront édités. - - + + Profil N° : - + Profil précédent - + Profil sélectionné - + Importer une géométrie - + Supprimer le profil sélectionné - + Éditer le profil sélectionné - + Copier le profil sélectionné - + Coller le profil en fin de liste (penser à modifier le Pk avant de trier) - + Dupliquer la section sélectionnée - + Trier les profils par ordre décroissant des Pk - + Changer l'ordre des profils (en décalant le profil sélectionné vers le haut) - + Changer l'ordre des profils (en décalant le profil sélectionné vers le bas) - + Terminer l'édition - + Vue isométrique (Alt+Z) - + Vue isométrique (Alt+E) - + Vue isométrique (Alt+R) + + + Elevation (m) + Altitude (m) + Network - + Add node Ajouter un nœud - + Delete the node Supprimer un nœud - + Disable the node Déactiver un nœud - + Delete the reach Supprimer un bief - + Disable the reach Déactiver un bief - + Enable the reach Activer un bief - + Reverse the reach orientation Inverser l'orientation du bief + + Results + + + X (m) + + + + + Y (m) + + + + + Reach name + + + + + Name + Nom + + + + KP (m) + + + SolverParameters @@ -2072,17 +2114,17 @@ Seuls les 5 premiers seront édités. Enregistrer la figure - + Retour à la vue précédente - + Passer à la vue suivante - + Vue isométrique (Shift+W) From 6356bab3207fb60bad517eeff17f0bf3051becaa Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 9 Aug 2023 17:21:59 +0200 Subject: [PATCH 60/64] Results: Plot: Fill between in KPC and fill water zone in XY. --- src/View/Results/PlotKPC.py | 5 +++++ src/View/Results/PlotXY.py | 43 ++++++++++++++++++++++++++----------- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/View/Results/PlotKPC.py b/src/View/Results/PlotKPC.py index 4d7f69a6..68f6fb4e 100644 --- a/src/View/Results/PlotKPC.py +++ b/src/View/Results/PlotKPC.py @@ -90,6 +90,11 @@ class PlotKPC(APlot): color='b', ) + self.canvas.axes.fill_between( + kp, z_min, water_z, + color='blue', alpha=0.5, interpolate=True + ) + self.canvas.figure.tight_layout() self.canvas.figure.canvas.draw_idle() if self.toolbar is not None: diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py index 905692a3..a88071f8 100644 --- a/src/View/Results/PlotXY.py +++ b/src/View/Results/PlotXY.py @@ -16,6 +16,8 @@ # -*- coding: utf-8 -*- +import logging + from functools import reduce from tools import timer, trace @@ -27,6 +29,8 @@ from PyQt5.QtCore import ( _translate = QCoreApplication.translate +logger = logging.getLogger() + class PlotXY(APlot): def __init__(self, canvas=None, results=None, reach_id=0, profile_id=0, @@ -109,7 +113,23 @@ class PlotXY(APlot): for x, y in zip(x_complete, y_complete) ] + if self.display_current: + # Current profile + profile = reach.profile(self._current_profile_id).geometry + + self.plot_selected, = self.canvas.axes.plot( + profile.x(), + profile.y(), + lw=1., markersize=3, + marker='+', color="b" + ) + self.plot_selected.set_visible(False) + # Display point under water + poly_l_x = [] + poly_l_y = [] + poly_r_x = [] + poly_r_y = [] for profile in reach.profiles: water_z = profile.get_ts_key( self._current_timestamp, "Z" @@ -125,24 +145,23 @@ class PlotXY(APlot): ([], []) ) + poly_l_x.append(x[0]) + poly_l_y.append(y[0]) + poly_r_x.append(x[-1]) + poly_r_y.append(y[-1]) + self.canvas.axes.plot( x, y, lw=1., color='b', - markersize=4, + markersize=1, marker='o' ) - if self.display_current: - # Current profile - profile = reach.profile(self._current_profile_id).geometry - - self.plot_selected, = self.canvas.axes.plot( - profile.x(), - profile.y(), - lw=1., markersize=3, - marker='+', color="b" - ) - self.plot_selected.set_visible(False) + poly_x = poly_l_x + list(reversed(poly_r_x)) + [poly_l_x[0]] + poly_y = poly_l_y + list(reversed(poly_r_y)) + [poly_l_y[0]] + # FIXME: Fill do not works ? (tmp fix: use plot) + self.canvas.axes.fill(poly_x, poly_y, color='blue', alpha=0.5) + self.canvas.axes.plot(poly_x, poly_y, color='blue', alpha=0.5) self.canvas.axes.autoscale_view(True, True, True) self.canvas.axes.autoscale() From 32fb90521fbada3d37764264b6b9a4d89a482da0 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 9 Aug 2023 17:32:19 +0200 Subject: [PATCH 61/64] Results: Plot: XY: Fix fill. --- src/View/Results/PlotXY.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py index a88071f8..3e7a88f3 100644 --- a/src/View/Results/PlotXY.py +++ b/src/View/Results/PlotXY.py @@ -159,9 +159,8 @@ class PlotXY(APlot): poly_x = poly_l_x + list(reversed(poly_r_x)) + [poly_l_x[0]] poly_y = poly_l_y + list(reversed(poly_r_y)) + [poly_l_y[0]] - # FIXME: Fill do not works ? (tmp fix: use plot) - self.canvas.axes.fill(poly_x, poly_y, color='blue', alpha=0.5) - self.canvas.axes.plot(poly_x, poly_y, color='blue', alpha=0.5) + + self.canvas.axes.fill(poly_x, poly_y, color='blue', alpha=1) self.canvas.axes.autoscale_view(True, True, True) self.canvas.axes.autoscale() From add8261cebd63dcd13baa691dd0981c184fc8dc7 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Wed, 9 Aug 2023 17:47:20 +0200 Subject: [PATCH 62/64] Results: Fix minor bug and add tab widget to result window. --- src/View/Results/Window.py | 4 +++ src/View/ui/Results.ui | 72 +++++++++++++++++++++++++------------- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py index 4ae5293e..99022b2f 100644 --- a/src/View/Results/Window.py +++ b/src/View/Results/Window.py @@ -211,12 +211,16 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): def _set_current_reach(self): table = self.find(QTableView, f"tableView_reach") indexes = table.selectedIndexes() + if len(indexes) == 0: + return self.update(reach_id = indexes[0].row()) def _set_current_profile(self): table = self.find(QTableView, f"tableView_profile") indexes = table.selectedIndexes() + if len(indexes) == 0: + return ind = indexes[0].row() self.update(profile_id = ind) diff --git a/src/View/ui/Results.ui b/src/View/ui/Results.ui index 64cde207..d975641b 100644 --- a/src/View/ui/Results.ui +++ b/src/View/ui/Results.ui @@ -17,7 +17,7 @@ - + @@ -30,13 +30,51 @@ - - - - - - Qt::Horizontal + + + + + + 0 + + + Geometry + + + + + + Qt::Vertical + + + + Qt::Horizontal + + + + + + + + + + + + + + + + + + Hydrograph + + + + + + + @@ -52,25 +90,11 @@ - - + + - Qt::Vertical + Qt::Horizontal - - - Qt::Horizontal - - - - - - - - - - - From 35ee6617ac6aaa41764530aa09229a966ccc4cef Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 11 Aug 2023 09:28:15 +0200 Subject: [PATCH 63/64] Results: Add hydrograph. --- src/View/Results/PlotH.py | 131 +++++++++++++++++++++++++++++++++++++ src/View/Results/Window.py | 19 ++++++ 2 files changed, 150 insertions(+) create mode 100644 src/View/Results/PlotH.py diff --git a/src/View/Results/PlotH.py b/src/View/Results/PlotH.py new file mode 100644 index 00000000..dcc9f7f6 --- /dev/null +++ b/src/View/Results/PlotH.py @@ -0,0 +1,131 @@ +# PlotH.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# -*- coding: utf-8 -*- + +import logging + +from functools import reduce + +from tools import timer, trace +from View.Plot.APlot import APlot + +from PyQt5.QtCore import ( + QCoreApplication +) + +_translate = QCoreApplication.translate + +logger = logging.getLogger() + +class PlotH(APlot): + def __init__(self, canvas=None, results=None, + reach_id=0, profile_id=0, + toolbar=None, display_current=True): + super(PlotH, self).__init__( + canvas=canvas, + data=results, + toolbar=toolbar + ) + + self.display_current = display_current + + self._current_timestamp = max(results.get("timestamps")) + self._current_reach_id = reach_id + self._current_profile_id = profile_id + + @property + def results(self): + return self.data + + @timer + def draw(self, highlight=None): + self.canvas.axes.cla() + self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5) + + if self.results is None: + return + + reach = self.results.river.reach(self._current_reach_id) + profile = reach.profile(self._current_profile_id) + + if reach.geometry.number_profiles == 0: + self._init = False + return + + kp_min, kp_max = (-1, -1) + if highlight is not None: + kp_min, kp_max = highlight + + # Axes + self.canvas.axes.set_xlabel( + _translate("Results", "Time (s)"), + color='green', fontsize=12 + ) + self.canvas.axes.set_ylabel( + _translate("Results", "Discharge (m³/s)"), + color='green', fontsize=12 + ) + + ts = list(self.results.get("timestamps")) + ts.sort() + + self.canvas.axes.set_xlim( + left = min(ts), right = max(ts) + ) + + # Draw discharge for each timestamp + x = ts + y = profile.get_key("Q") + + if len(ts) != len(x): + logger.warning( + "Results as less Q data ({len(x)}) " + + "than timestamps ({len(ts)}) " + + "for profile {self._current_profile_id}" + ) + return + + self._line = [ + self.canvas.axes.plot( + x, y, lw=1., + color='r', + markersize=3, marker='+' + ) + ] + + self.canvas.axes.autoscale_view(True, True, True) + self.canvas.axes.autoscale() + self.canvas.figure.tight_layout() + self.canvas.figure.canvas.draw_idle() + if self.toolbar is not None: + self.toolbar.update() + + def set_reach(self, reach_id): + self._current_reach_id = reach_id + self._current_profile_id = 0 + self.draw() + + def set_profile(self, profile_id): + self._current_profile_id = profile_id + self.draw() + + def set_timestamp(self, timestamp): + self._current_timestamp = timestamp + self.draw() + + def update(self): + self.draw() diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py index 99022b2f..22d0a2c4 100644 --- a/src/View/Results/Window.py +++ b/src/View/Results/Window.py @@ -45,6 +45,7 @@ from View.Plot.MplCanvas import MplCanvas from View.Results.PlotXY import PlotXY from View.Results.PlotAC import PlotAC from View.Results.PlotKPC import PlotKPC +from View.Results.PlotH import PlotH from View.Results.Table import TableModel from View.Results.translate import * @@ -165,6 +166,20 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): ) self.plot_ac.draw() + self.canvas_4 = MplCanvas(width=5, height=4, dpi=100) + self.canvas_4.setObjectName("canvas_4") + self.plot_layout_4 = self.find(QVBoxLayout, "verticalLayout_hydrograph") + self.plot_layout_4.addWidget(self.canvas_4) + + self.plot_h = PlotH( + canvas = self.canvas_4, + results = self._results, + reach_id = 0, + profile_id = 0, + toolbar = None + ) + self.plot_h.draw() + def setup_connections(self): self.undo_sc.activated.connect(self.undo) self.redo_sc.activated.connect(self.redo) @@ -194,18 +209,22 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow): self.plot_xy.set_reach(reach_id) self.plot_ac.set_reach(reach_id) self.plot_kpc.set_reach(reach_id) + self.plot_h.set_reach(reach_id) if profile_id is not None: self.plot_xy.set_profile(profile_id) self.plot_ac.set_profile(profile_id) self.plot_kpc.set_profile(profile_id) + self.plot_h.set_profile(profile_id) if timestamp is not None: self.plot_xy.set_timestamp(timestamp) self.plot_ac.set_timestamp(timestamp) self.plot_kpc.set_timestamp(timestamp) + self.plot_h.set_timestamp(timestamp) self.plot_xy.draw() self.plot_ac.draw() self.plot_kpc.draw() + self.plot_h.draw() def _set_current_reach(self): From bb56c9293823fa335cab70fd4683070c575fd436 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Fri, 11 Aug 2023 09:57:08 +0200 Subject: [PATCH 64/64] BC, LC: Fix axes scale for none time data. --- src/View/BoundaryCondition/Edit/Plot.py | 7 +++++++ src/View/LateralContribution/Edit/Plot.py | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/View/BoundaryCondition/Edit/Plot.py b/src/View/BoundaryCondition/Edit/Plot.py index c9e36413..b27380a5 100644 --- a/src/View/BoundaryCondition/Edit/Plot.py +++ b/src/View/BoundaryCondition/Edit/Plot.py @@ -16,6 +16,8 @@ # -*- coding: utf-8 -*- +import logging + from datetime import datetime from tools import timer, trace @@ -29,6 +31,8 @@ from View.BoundaryCondition.Edit.translate import * _translate = QCoreApplication.translate +logger = logging.getLogger() + class Plot(APlot): def __init__(self, canvas=None, data=None, mode = "time", toolbar=None): @@ -41,6 +45,9 @@ class Plot(APlot): self._mode = mode def custom_ticks(self): + if self.data.header[0] != "time": + return + t0 = datetime.fromtimestamp(0) nb = len(self.data.data) mod = int(nb / 5) diff --git a/src/View/LateralContribution/Edit/Plot.py b/src/View/LateralContribution/Edit/Plot.py index df088405..5843ee56 100644 --- a/src/View/LateralContribution/Edit/Plot.py +++ b/src/View/LateralContribution/Edit/Plot.py @@ -41,6 +41,9 @@ class Plot(APlot): self._mode = mode def custom_ticks(self): + if self.data.header[0] != "time": + return + t0 = datetime.fromtimestamp(0) nb = len(self.data.data) mod = int(nb / 5)