From cb5ee1b9bbe131e997b0299534139bb9ef69cdec Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 14 Mar 2023 10:11:00 +0100 Subject: [PATCH] Add configuration window and many minor change. * src/config.py: Application config class. * src/pamhyr.py: Add app config. * src/view/ASubWindow.py: Add some methods. * src/view/ConfigureWindow.py: New app sub window. * src/view/MainWindow.py: Minor change. * src/view/ui/ConfigureDialog.ui: New ui. * src/view/ui/MainWindow.ui: Start rename some component. * src/view/ui/MainWindow_old.ui: Old version of main UI. --- src/config.py | 51 ++ src/model/AModelComponent.py | 10 + src/pamhyr.py | 6 +- src/view/ASubWindow.py | 114 ++++- src/view/ConfigureWindow.py | 95 ++++ src/view/MainWindow.py | 65 ++- src/view/ui/ConfigureDialog.ui | 369 ++++++++++++++ src/view/ui/MainWindow.ui | 116 +++-- src/view/ui/MainWindow_old.ui | 908 +++++++++++++++++++++++++++++++++ 9 files changed, 1672 insertions(+), 62 deletions(-) create mode 100644 src/config.py create mode 100644 src/model/AModelComponent.py create mode 100644 src/view/ConfigureWindow.py create mode 100644 src/view/ui/ConfigureDialog.ui create mode 100644 src/view/ui/MainWindow_old.ui diff --git a/src/config.py b/src/config.py new file mode 100644 index 00000000..26416b78 --- /dev/null +++ b/src/config.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- + +import os +import pickle + +config_dir = "/.cache/pamhyr/" +config_file = "config.pkl" + +class Config(object): + def __init__(self): + super(Config, self).__init__() + + self.filename = Config.filename() + self.set_default_value() + + def set_default_value(self): + # Mage + self.mage_path = "" + self.mage_extract_path = "" + self.mailleur_path = "" + + # Const + self.manning = False + self.segment = 1000 + self.max_listing = 500000 + + # Backup + self.backup_enable = True + self.backup_path = "" + self.backup_frequence = "00:05:00" + self.backup_max = 10 + + @classmethod + def filename(cls): + return os.environ["HOME"] + config_dir + config_file + + def save(self): + os.makedirs(os.path.dirname(self.filename), exist_ok=True) + with open(self.filename, 'wb') as out_file: + pickle.dump(self, out_file) + + @classmethod + def load(cls): + filename = cls.filename() + if os.path.isfile(filename): + with open(filename, 'rb') as in_file: + me = pickle.load(in_file) + return me + else: + print("config: New config") + return cls() diff --git a/src/model/AModelComponent.py b/src/model/AModelComponent.py new file mode 100644 index 00000000..3da2aa6c --- /dev/null +++ b/src/model/AModelComponent.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- + +class AbstractModelComponent(object): + def __init__(self): + super(AbstractModelComponent, self).__init__() + + def new(self, filename): + + + def export(self, filename): diff --git a/src/pamhyr.py b/src/pamhyr.py index 1d7cf0e5..ec9f74f0 100755 --- a/src/pamhyr.py +++ b/src/pamhyr.py @@ -4,12 +4,16 @@ import sys from PyQt5.QtWidgets import QApplication + +from config import Config from view.MainWindow import ApplicationWindow from model.Study import Study def main(): + conf = Config.load() + app = QApplication(sys.argv) - application = ApplicationWindow() + application = ApplicationWindow(conf=conf) application.show() sys.exit(app.exec_()) diff --git a/src/view/ASubWindow.py b/src/view/ASubWindow.py index 2739a6a2..3f01e02c 100644 --- a/src/view/ASubWindow.py +++ b/src/view/ASubWindow.py @@ -5,7 +5,11 @@ import os from PyQt5.QtWidgets import ( QMainWindow, QApplication, QDesktopWidget, QMdiArea, QMdiSubWindow, QDialog, - QPushButton + QPushButton, QLineEdit, QCheckBox, + QTimeEdit, QSpinBox +) +from PyQt5.QtCore import ( + QTime, ) from PyQt5.uic import loadUi @@ -23,3 +27,111 @@ class ASubWindow(QDialog): def closeEvent(self, event): if not self.parent is None: self.parent.sub_win_del(self.name) + + # Commun use features + + def find(self, qtype, name): + """Find an ui component + + Args: + qtype: Type of QT component + name: Name for component + + Returns: + return the component + """ + return self.ui.findChild(qtype, name) + + def set_line_edit_text(self, name:str, text:str): + """Set text of line edit component + + Args: + line_edit: The line edit component name + text: The text + + Returns: + Nothing + """ + self.find(QLineEdit, name).setText(text) + + def get_line_edit_text(self, name:str): + """Get text of line edit component + + Args: + line_edit: The line edit component name + + Returns: + Text + """ + return self.find(QLineEdit, name).text() + + def set_check_box(self, name:str, checked:bool): + """Set status of checkbox component + + Args: + name: The check box component name + checked: Bool + + Returns: + Nothing + """ + self.find(QCheckBox, name).setChecked(checked) + + def get_check_box(self, name:str): + """Get status of checkbox component + + Args: + name: The check box component name + + Returns: + Status of checkbox (bool) + """ + return self.find(QCheckBox, name).isChecked() + + + def set_time_edit(self, name:str, time:str): + """Set time of timeedit component + + Args: + name: The timeedit component name + time: The new time in format "HH:mm:ss" + + Returns: + Nothing + """ + qtime = QTime.fromString(time) + self.find(QTimeEdit, name).setTime(qtime) + + def get_time_edit(self, name:str): + """Get time of timeedit component + + Args: + name: The timeedit component name + + Returns: + The time of timeedit in format "HH:mm:ss" + """ + return self.find(QTimeEdit, name).time().toString() + + def set_spin_box(self, name:str, value:int): + """Set value of spinbox component + + Args: + name: The spinbox component name + value: The new value + + Returns: + Nothing + """ + self.find(QSpinBox, name).setValue(value) + + def get_spin_box(self, name:str): + """Get time of spin box component + + Args: + name: The spin box component + + Returns: + The value of spin box + """ + return self.find(QSpinBox, name).value() diff --git a/src/view/ConfigureWindow.py b/src/view/ConfigureWindow.py new file mode 100644 index 00000000..c633c2ce --- /dev/null +++ b/src/view/ConfigureWindow.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- + +from config import Config +from view.ASubWindow import ASubWindow +from PyQt5.QtWidgets import ( + QDialogButtonBox, QPushButton, QLineEdit, + QFileDialog, +) + +class ConfigureWindow(ASubWindow): + def __init__(self, conf=None, title="Configure", parent=None): + super(ConfigureWindow, self).__init__(name=title, ui="ConfigureDialog", parent=parent) + self.ui.setWindowTitle(title) + + if conf is None: + self.conf = Config() + else: + self.conf = conf + + # MAGE + self.set_line_edit_text("lineEdit_exec_mage", self.conf.mage_path) + self.set_line_edit_text("lineEdit_exec_mage_extract", self.conf.mage_extract_path) + self.set_line_edit_text("lineEdit_exec_mailleur", self.conf.mailleur_path) + + # Const + self.set_check_box("checkBox_manning", self.conf.manning) + self.set_line_edit_text("lineEdit_segment", str(self.conf.segment)) + self.set_line_edit_text("lineEdit_max_listing", str(self.conf.max_listing)) + + # Backup + self.set_check_box("checkBox_backup", self.conf.backup_enable) + self.set_line_edit_text("lineEdit_backup_path", self.conf.backup_path) + self.set_time_edit("timeEdit_backup_frequence", self.conf.backup_frequence) + self.set_spin_box("spinBox_backup_max", self.conf.backup_max) + + self.connect() + + def connect(self): + # File button + buttons = { + "pushButton_exec_mage": lambda: self.file_dialog("exec_mage", True), + "pushButton_exec_mage_extract": lambda: self.file_dialog("exec_mage_extract", True), + "pushButton_exec_mailleur": lambda: self.file_dialog("exec_mailleur", True), + "pushButton_backup_path": lambda: self.file_dialog("backup_path", False), + } + + for button in buttons: + self.find(QPushButton, button).clicked.connect(buttons[button]) + + def accept(self): + # MAGE + self.conf.mage_path = self.get_line_edit_text("lineEdit_exec_mage") + self.conf.mage_extract_path = self.get_line_edit_text("lineEdit_exec_mage_extract") + self.conf.mailleur_path = self.get_line_edit_text("lineEdit_exec_mailleur") + + # Const + self.conf.manning = self.get_check_box("checkBox_manning") + self.conf.segment = self.get_line_edit_text("lineEdit_segment") + self.conf.max_listing = self.get_line_edit_text("lineEdit_max_listing") + + # Backup + self.conf.backup_enable = self.get_check_box("checkBox_backup") + self.conf.backup_path = self.get_line_edit_text("lineEdit_backup_path") + self.conf.backup_frequence = self.get_time_edit("timeEdit_backup_frequence") + self.conf.backup_max = self.get_spin_box("spinBox_backup_max") + + self.end() + + def reject(self): + # Nothing todo + self.end() + + def end(self): + self.conf.save() + self.close() + + def file_dialog(self, line_edit, select_file): + dialog = QFileDialog(self) + if select_file: + mode = QFileDialog.FileMode.ExistingFile + else: + mode = QFileDialog.FileMode.Directory + + dialog.setFileMode(mode) + + if dialog.exec_(): + file_names = dialog.selectedFiles() + if len(file_names) != 1: + print("pas bien") + else: + if line_edit != "": + self.set_line_edit_text( + f"lineEdit_{line_edit}", + file_names[0] + ) diff --git a/src/view/MainWindow.py b/src/view/MainWindow.py index 66fbbac0..b13bebf0 100644 --- a/src/view/MainWindow.py +++ b/src/view/MainWindow.py @@ -10,6 +10,7 @@ from PyQt5.uic import loadUi from view.ListedSubWindow import ListedSubWindow from view.DummyWindow import DummyWindow +from view.ConfigureWindow import ConfigureWindow from view.AboutWindow import AboutWindow from model.Study import Study @@ -43,14 +44,17 @@ action = ( ) class ApplicationWindow(QMainWindow, ListedSubWindow): - def __init__(self): + def __init__(self, conf=None): super(ApplicationWindow, self).__init__() + # App Configuration + self.conf = conf + # Model self.model = None # UI self.ui = loadUi( - os.path.join(os.path.dirname(__file__), "ui", "MainWindow.ui"), + os.path.join(os.path.dirname(__file__), "ui", "MainWindow_old.ui"), self ) @@ -58,15 +62,27 @@ class ApplicationWindow(QMainWindow, ListedSubWindow): self.default_style() def enable_actions(self, action:str, enable:bool): + """Enable of disable an action componant + + Args: + action: Action to enable/disable + enable: True to Enable, or False to disable + + Returns: + Nothing + """ self.ui.findChild(QAction, action).setEnabled(enable) def init_callback(self): - """ - Connect action to callback function. + """Connect action to callback function + + Returns: + Nothing """ actions = { # Menu action "actionA_propos": self.open_about, + "actionConfiguration_de_Pamhyr": self.open_configure, # ToolBar action "actionquitter_application": self.close, "actionOuvrir_une_tude": self.dummy_model, @@ -93,6 +109,11 @@ class ApplicationWindow(QMainWindow, ListedSubWindow): .triggered.connect(actions[action]) def default_style(self): + """Set default window style + + Returns: + Nothing + """ self.update_enable_action() # Maximise window self.showMaximized() @@ -113,15 +134,22 @@ class ApplicationWindow(QMainWindow, ListedSubWindow): self.update_enable_action() def update_enable_action(self): - no_model = self.model is None + """Update status of action componante - if no_model: - for action in define_model_action + other_model_action: - self.enable_actions(action, False) + Update status of action componant, enable or disable in + function of model state + + Returns: + Nothing + """ + no_model = self.model is None for action in no_model_action: self.enable_actions(action, no_model) + for action in define_model_action + other_model_action: + self.enable_actions(action, not no_model) + for action in model_action: self.enable_actions(action, not no_model) @@ -129,7 +157,25 @@ class ApplicationWindow(QMainWindow, ListedSubWindow): # SUBWINDOW # ############# + def open_configure(self): + """Open configure window + + Open PamHyr configure window + + Returns: + Nothing + """ + self.config = ConfigureWindow(conf=self.conf, parent=self) + self.config.show() + def open_about(self): + """Open about window + + Open a new window with information about PamHyr + + Returns: + Nothing + """ self.about = AboutWindow(parent=self) self.about.show() @@ -139,9 +185,6 @@ class ApplicationWindow(QMainWindow, ListedSubWindow): ############### def open_dummy(self, title="Dummy"): - """ - Open a dummy dialog window. - """ self.dummy = DummyWindow( title=title if type(title) is str else "Dummy", parent=self diff --git a/src/view/ui/ConfigureDialog.ui b/src/view/ui/ConfigureDialog.ui new file mode 100644 index 00000000..b8316907 --- /dev/null +++ b/src/view/ui/ConfigureDialog.ui @@ -0,0 +1,369 @@ + + + Dialog + + + + 0 + 0 + 770 + 351 + + + + Dialog + + + + + 10 + 20 + 751 + 321 + + + + + + + + + true + + + Executable + + + + + 10 + 20 + 351 + 111 + + + + + + + + + MAGE + + + + + + + MAGE_Extraire + + + + + + + Mailleur + + + + + + + + + + + + + + + + + + + + ressources/open.pngressources/open.png + + + + + + + + + + + + + + + + + + ressources/open.pngressources/open.png + + + + + + + + + + + + + + + + + + ressources/open.pngressources/open.png + + + + + + + + + + + + + + + BackUp + + + + + 10 + 20 + 343 + 125 + + + + + + + + + Sauvegarde automatique + + + + + + + Chemin + + + + + + + Frequence + + + + + + + Max. archives + + + + + + + + + + + Activé + + + false + + + + + + + + + + + + + + + + ressources/open.pngressources/open.png + + + + + + + + + + + + HH:mm:ss + + + Qt::LocalTime + + + + + + + + + + 1 + + + 10 + + + + + + + + + + + + + Constante numérique + + + + + 10 + 30 + 268 + 93 + + + + + + + + + Frottement + + + + + + + Nombre de segment + + + + + + + Taille max. du listing + + + + + + + + + + + Manning + + + + + + + 1000 + + + + + + + 500000 + + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + buttonBox + accepted() + Dialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Dialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/view/ui/MainWindow.ui b/src/view/ui/MainWindow.ui index 1a014058..d9c42155 100644 --- a/src/view/ui/MainWindow.ui +++ b/src/view/ui/MainWindow.ui @@ -75,33 +75,33 @@ &Fichier - - + + - + - - + + - + - - - - + + + + - + - + &Réseau - + @@ -115,22 +115,22 @@ Profil en travers - - + + - + - - + + - - - - - - + + + + + + @@ -302,7 +302,7 @@ - + false @@ -332,7 +332,7 @@ Ouvrir une étude - + Nouvelle étude RubarBE @@ -340,7 +340,7 @@ Ctrl+R - + ressources/open.png @@ -353,7 +353,7 @@ Ctrl+O - + Importer un jeu de données MAGE @@ -361,12 +361,12 @@ - + Importer un jeu de données RubarBE - + ../ressources/menu/gtk-close.png../ressources/menu/gtk-close.png @@ -375,7 +375,7 @@ Fermer - + true @@ -386,7 +386,7 @@ Enregistrer le maillage - + ressources/gtk-save.pngressources/gtk-save.png @@ -398,7 +398,7 @@ Ctrl+S - + ressources/gtk-save-as.pngressources/gtk-save-as.png @@ -410,17 +410,17 @@ Ctrl+Shift+S - + Archiver - + Configuration de Pamhyr - + ../ressources/menu/gtk-quit.png../ressources/menu/gtk-quit.png @@ -432,62 +432,74 @@ Ctrl+F4 - + Éditer le réseau - + Éditer la géométrie - + Importer une géométrie - + Exporter la géométrie - + Lancer le mailleur externe - + Choix du mailleur par bief - + + + false + Visualiser la géométrie maillée - + + + false + Exporter le maillage - + + + false + Supprimer le maillage du bief courant - + + + false + Supprimer l'ensemble des maillages - + Abscisse - Cote - + XYZ @@ -705,7 +717,7 @@ Enrégistrer étude en cours (Ctrl+S) - Ctrl+S + @@ -754,6 +766,9 @@ + + false + ressources/gtk-stop.pngressources/gtk-stop.png @@ -781,6 +796,9 @@ + + false + ressources/gnome-stock-edit.pngressources/gnome-stock-edit.png diff --git a/src/view/ui/MainWindow_old.ui b/src/view/ui/MainWindow_old.ui new file mode 100644 index 00000000..3824a981 --- /dev/null +++ b/src/view/ui/MainWindow_old.ui @@ -0,0 +1,908 @@ + + + MainWindow + + + Qt::ApplicationModal + + + true + + + + 0 + 0 + 850 + 646 + + + + + Serif + 75 + true + false + + + + true + + + Qt::NoContextMenu + + + true + + + PAMHYR + + + + ressources/M_icon.pngressources/M_icon.png + + + Qt::LeftToRight + + + false + + + + + + false + + + + Qt::NoContextMenu + + + + + + 0 + 0 + 850 + 23 + + + + + Sans Serif + + + + + &Fichier + + + + + + + + + + + + + + + + + + + + + + + + + + &Réseau + + + + + + &Géométrie + + + + Comparer + + + + Profil en travers + + + + + + + + + + + + + + + + + + + + + + + + &Exécuter + + + + Sous-étude Rubar3 + + + + + + + + + + + + + + + &Hydraulique + + + + + + + + + + + + + + + + &Graphiques + + + + + + + + + + + + + + + + &Cartographie + + + + + + &Aide + + + + + + + + + + + + + + + + + + true + + + + 0 + 0 + + + + + 50 + false + true + + + + true + + + Qt::ClickFocus + + + Qt::NoContextMenu + + + toolBar + + + + + + true + + + true + + + false + + + TopToolBarArea + + + false + + + + + + + + + + + + + + + + + + Sans Serif + 9 + 50 + false + false + + + + toolBar_2 + + + TopToolBarArea + + + true + + + + + + + + + + + + + + + + + false + + + + ressources/edit.pngressources/edit.png + + + Nouvelle étude MAGE + + + + 75 + true + + + + Ctrl+N + + + + + + ressources/open.pngressources/open.png + + + Ouvrir une étude + + + + + Nouvelle étude RubarBE + + + Ctrl+R + + + + + + ressources/open.png + + + + Ouvrir une étude + + + Ctrl+O + + + + + Importer un jeu de données MAGE + + + + + + + + Importer un jeu de données RubarBE + + + + + + ../ressources/menu/gtk-close.png../ressources/menu/gtk-close.png + + + Fermer + + + + + true + + + true + + + Enregistrer le maillage + + + + + + ressources/gtk-save.pngressources/gtk-save.png + + + Enregistrer + + + Ctrl+S + + + + + + ressources/gtk-save-as.pngressources/gtk-save-as.png + + + Enregistrer sous ... + + + Ctrl+Shift+S + + + + + Archiver + + + + + Configuration de Pamhyr + + + + + + ../ressources/menu/gtk-quit.png../ressources/menu/gtk-quit.png + + + Quitter + + + Ctrl+F4 + + + + + Éditer le réseau + + + + + Éditer la géométrie + + + + + Importer une géométrie + + + + + Exporter la géométrie + + + + + Lancer le mailleur externe + + + + + Choix du mailleur par bief + + + + + Visualiser la géométrie maillée + + + + + Exporter le maillage + + + + + Supprimer le maillage du bief courant + + + + + Supprimer l'ensemble des maillages + + + + + Abscisse - Cote + + + + + XYZ + + + + + Paramètres numériques du solveur MAGE + + + + + Conditions aux Limites & Apports Ponctuels + + + + 75 + true + + + + + + Conditions initiales + + + + + true + + + Activer/Désactiver l'export des conditions initiales + + + + + Importer l'état final comme état initial + + + + + Édition des Frottements + + + + + Édition des Apports Latéraux + + + + + Édition des déversements + + + + + Édition des Tronçons + + + + + Édition des ouvrages en travers + + + + + Solveur MAGE + + + + + Stop Solveur + + + + + Afficher les listings + + + + + Gestion des répertoires de simulation + + + + + Ouvrir + + + + + Fermer + + + + + Hydrogramme + + + + Ubuntu + 75 + true + + + + + + Limnigramme + + + + 75 + true + + + + + + Ligne d'eau + + + + + Ligne d'eau finale + + + + + Ligne d'eau enveloppe + + + + + Vitesse(Pk) à t fixé + + + + + Vitesse(t) à Pk fixé + + + + + Charge hydraulique(Pk) à t fixé + + + + + Charge hydraulique(t) à Pk fixé + + + + 75 + true + + + + + + Voir l'animation (MAGE) + + + + + Autres résulats MAGE + + + + 75 + true + + + + + + Cartographier le bief courant + + + + + Aide de PAMHYR + + + + + Aide de MAGE + + + + + À propos + + + + + + ../ressources/menu/open.png../ressources/menu/open.png + + + ouvrir + + + Ouvrir une étude + + + + + + ressources/save.pngressources/save.png + + + enregistrer_etude_en_cours + + + Enrégistrer étude en cours (Ctrl+S) + + + + + + + + + ressources/gtk-close.pngressources/gtk-close.png + + + fermer_etude_en_cours + + + Fermer étude en cours (Ctrl+F) + + + Ctrl+F + + + + + + ressources/exit_bis.pngressources/exit_bis.png + + + quitter_application + + + Quitter l'application (Ctrl+Q) + + + Ctrl+Q + + + + + + ressources/gtk-execute.pngressources/gtk-execute.png + + + lancer_solveur + + + Lancer le solveur pour réaliser une simulation + + + Ctrl+X + + + + + false + + + + ressources/gtk-stop.pngressources/gtk-stop.png + + + interrompt_simulation_en_cours + + + Interrompt la simulation en cours + + + Ctrl+C + + + + + + ressources/gnome-stock-insert-table.pngressources/gnome-stock-insert-table.png + + + lancer_mailleur_externe + + + Lancer le mailleur externe sur la géométrie du bief courant + + + + + false + + + + ressources/gnome-stock-edit.pngressources/gnome-stock-edit.png + + + afficher_listings_simulation + + + Aficher les listings de la simulation courante + + + + + + ressources/reseau3_24.pngressources/reseau3_24.png + + + Réseau + + + Ouvrir l'éditeur de la topologie du réseau + + + + + + ressources/geometrie0.pngressources/geometrie0.png + + + Géométrie + + + Ouvrir l'éditeur de géométrie + + + + + + ressources/mailles-50.pngressources/mailles-50.png + + + Maillage + + + Afficher le maillage + + + + + Cond. Limites + + + Ouvir l'éditeur des Conditions aux Limites & Apports Ponctuels + + + + + + + + App. Latéraux + + + Ouvrir l'éditeur des Apports Latéraux Distribués + + + + + Déversements + + + Ouvrir l'éditeur des Déversements Latéraux + + + + + Tronçons + + + Ouvrir l'éditeur des tronçons pour les frottements et Apports Latéraux + + + + + Frottements + + + Ouvrir l'éditeur des frottements au fond + + + + + Ouvrages + + + Ouvrir l'éditeur des ouvrages (seuils, vannes, etc.), singularités et pompes + + + + + + + MainWindow + customContextMenuRequested(QPoint) + MainWindow + showMaximized() + + + 346 + 301 + + + 346 + 301 + + + + +