diff --git a/src/View/About/Window.py b/src/View/About/Window.py index 7c269aaf17155517136c4bf6f83a39c557b36301..218869b5fc7d87595dcadc8b018660f6edfcb8e3 100644 --- a/src/View/About/Window.py +++ b/src/View/About/Window.py @@ -19,14 +19,17 @@ import os import logging -from View.ASubWindow import ASubWindow +from View.Tools.PamhyrWindow import PamhyrDialog from PyQt5.QtCore import QCoreApplication _translate = QCoreApplication.translate logger = logging.getLogger() -class AboutWindow(ASubWindow): +class AboutWindow(PamhyrDialog): + _pamhyr_ui = "about" + _pamhyr_name = "About" + def _path_file(self, filename): return os.path.abspath( os.path.join( @@ -35,10 +38,14 @@ class AboutWindow(ASubWindow): ) ) - - def __init__(self, title="About", parent=None): - super(AboutWindow, self).__init__(name=title, ui="about", parent=parent) - self.ui.setWindowTitle(title) + def __init__(self, study = None, config = None, parent=None): + super(AboutWindow, self).__init__( + title = _translate("About", "About"), + study = study, + config = config, + options = [], + parent = parent + ) # Version with open(self._path_file("VERSION"), "r") as f: diff --git a/src/View/Configure/Solver/Window.py b/src/View/Configure/Solver/Window.py index c295481f1e46ecd870137db6c3d8a29a4466d38c..369ff40ad28272803d4f280344a951ff47990b2c 100644 --- a/src/View/Configure/Solver/Window.py +++ b/src/View/Configure/Solver/Window.py @@ -16,7 +16,7 @@ # -*- coding: utf-8 -*- -from View.ASubWindow import ASubWindow +from View.Tools.PamhyrWindow import PamhyrDialog from Solver.Solvers import solver_type_list from Solver.GenericSolver import GenericSolver @@ -24,12 +24,22 @@ from PyQt5.QtWidgets import ( QPushButton, ) -class ConfigureSolverWindow(ASubWindow): - def __init__(self, data=None, title="Configuration : Add Solver", parent=None): +class ConfigureSolverWindow(PamhyrDialog): + _pamhyr_ui = "ConfigureAddSolverDialog" + _pamhyr_name = "Add/Edit Solver" + + def __init__(self, data=None, config=None, parent=None): + if data is not None: + name = f"Edit Solver - {data.name}" + else: + name = "Add a new Solver" + super(ConfigureSolverWindow, self).__init__( - name=title, ui="ConfigureAddSolverDialog", parent=parent + title = name, + config = config, + options = [], + parent=parent ) - self.ui.setWindowTitle(title) # Combo box item for solver in solver_type_list: @@ -37,10 +47,10 @@ class ConfigureSolverWindow(ASubWindow): # Data to return self.data = data - if not self.data is None: + if self.data is not None: self.copy_data() - self.connect() + self.setup_connection() def copy_data(self): self.set_combobox_text("comboBox_solver", self.data.type) @@ -53,7 +63,7 @@ class ConfigureSolverWindow(ASubWindow): self.set_line_edit_text("lineEdit_output", self.data._path_output) self.set_line_edit_text("lineEdit_output_cmd", self.data._cmd_output) - def connect(self): + def setup_connection(self): # File button buttons = { "pushButton_input": (lambda: self.file_dialog( diff --git a/src/View/Configure/Window.py b/src/View/Configure/Window.py index 23a371ac98d702e1a435098b47e05a6d046bcf8a..83db81f6bfe0cad93deca88ff2698b9a7a1516db 100644 --- a/src/View/Configure/Window.py +++ b/src/View/Configure/Window.py @@ -21,8 +21,7 @@ import logging from copy import deepcopy from config import Config -from View.ASubWindow import ASubWindow -from View.ListedSubWindow import ListedSubWindow +from View.Tools.PamhyrWindow import PamhyrDialog from View.Stricklers.Table import TableModel from View.Stricklers.translate import * @@ -95,50 +94,42 @@ class SolverTableModel(QAbstractTableModel): self.layoutChanged.emit() -class ConfigureWindow(ASubWindow, ListedSubWindow): - def __init__(self, conf=None, title="Configure", parent=None): +class ConfigureWindow(PamhyrDialog): + _pamhyr_ui = "ConfigureDialog" + _pamhyr_name = "Configure" + + def __init__(self, config=None, parent=None): + if config is None: + config = Config() + super(ConfigureWindow, self).__init__( - name=title, ui="ConfigureDialog", parent=parent + title = self._pamhyr_name, + config = config, + options = [], + parent=parent ) - self.ui.setWindowTitle(title) - if conf is None: - self.conf = Config() - else: - self.conf = conf + self.setup_custom_sc() + self.setup_solver() + self.setup_stricklers() + self.setup_data() + self.setup_connection() - self.setup_sc() - - # Solver + def setup_solver(self): table = self.find(QTableView, "tableView_solver") self.solver_table_model = SolverTableModel( headers = ["name", "type", "description"], - rows = conf.solvers + rows = self._config.solvers ) table.setModel(self.solver_table_model) table.setSelectionBehavior(QAbstractItemView.SelectRows) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.setAlternatingRowColors(True) + table.resizeColumnsToContents() - # Meshing_Tool - self.set_line_edit_text("lineEdit_meshing_tool", self.conf.meshing_tool) - - # Const - self.set_line_edit_text("lineEdit_segment", str(self.conf.segment)) - self.set_line_edit_text("lineEdit_max_listing", str(self.conf.max_listing)) - - # Backup - self.set_check_box("checkBox_backup", self.conf.backup_enable) - self.set_line_edit_text("lineEdit_backup_path", self.conf.backup_path) - self.set_time_edit("timeEdit_backup_frequence", self.conf.backup_frequence) - self.set_spin_box("spinBox_backup_max", self.conf.backup_max) - - self.find(QTableView, "tableView_solver").resizeColumnsToContents() - self.connect() - - # Stricklers + def setup_stricklers(self): table = self.find(QTableView, f"tableView_stricklers") - self._stricklers = deepcopy(self.conf.stricklers) + self._stricklers = deepcopy(self._config.stricklers) self._stricklers_table = TableModel( data = self._stricklers, undo = self._undo_stack, @@ -148,26 +139,35 @@ class ConfigureWindow(ASubWindow, ListedSubWindow): table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.setAlternatingRowColors(True) + def setup_data(self): + # Meshing_Tool + self.set_line_edit_text("lineEdit_meshing_tool", self._config.meshing_tool) + + # Const + self.set_line_edit_text("lineEdit_segment", str(self._config.segment)) + self.set_line_edit_text("lineEdit_max_listing", str(self._config.max_listing)) + + # Backup + self.set_check_box("checkBox_backup", self._config.backup_enable) + self.set_line_edit_text("lineEdit_backup_path", self._config.backup_path) + self.set_time_edit("timeEdit_backup_frequence", self._config.backup_frequence) + self.set_spin_box("spinBox_backup_max", self._config.backup_max) + # Editor - self.set_line_edit_text("lineEdit_editor_cmd", str(self.conf.editor)) + self.set_line_edit_text("lineEdit_editor_cmd", str(self._config.editor)) # Language languages = Config.languages() for lang in languages: self.combobox_add_item("comboBox_language", lang) - if self.conf.lang == languages[lang]: + if self._config.lang == languages[lang]: self.set_combobox_text("comboBox_language", lang) - def setup_sc(self): - self._undo_stack = QUndoStack() + def setup_custom_sc(self): + self._debug_sc = QShortcut(QKeySequence("Ctrl+G"), self) + self._debug_sc.activated.connect(self.set_debug) - self.debug_sc = QShortcut(QKeySequence("Ctrl+G"), self) - self.undo_sc = QShortcut(QKeySequence.Undo, self) - self.redo_sc = QShortcut(QKeySequence.Redo, self) - self.copy_sc = QShortcut(QKeySequence.Copy, self) - self.paste_sc = QShortcut(QKeySequence.Paste, self) - - def connect(self): + def setup_connection(self): buttons = { # Solvers "pushButton_solver_add": self.add_solver, @@ -195,33 +195,31 @@ class ConfigureWindow(ASubWindow, ListedSubWindow): for button in buttons: self.find(QPushButton, button).clicked.connect(buttons[button]) - self.debug_sc.activated.connect(self.set_debug) - def accept(self): # Solvers - self.conf.solvers = self.solver_table_model.rows.copy() + self._config.solvers = self.solver_table_model.rows.copy() # Meshing_Tool - self.conf.meshing_tool = self.get_line_edit_text("lineEdit_meshing_tool") + self._config.meshing_tool = self.get_line_edit_text("lineEdit_meshing_tool") # Const - self.conf.segment = self.get_line_edit_text("lineEdit_segment") - self.conf.max_listing = self.get_line_edit_text("lineEdit_max_listing") + self._config.segment = self.get_line_edit_text("lineEdit_segment") + self._config.max_listing = self.get_line_edit_text("lineEdit_max_listing") # Backup - self.conf.backup_enable = self.get_check_box("checkBox_backup") - self.conf.backup_path = self.get_line_edit_text("lineEdit_backup_path") - self.conf.backup_frequence = self.get_time_edit("timeEdit_backup_frequence") - self.conf.backup_max = self.get_spin_box("spinBox_backup_max") + self._config.backup_enable = self.get_check_box("checkBox_backup") + self._config.backup_path = self.get_line_edit_text("lineEdit_backup_path") + self._config.backup_frequence = self.get_time_edit("timeEdit_backup_frequence") + self._config.backup_max = self.get_spin_box("spinBox_backup_max") # Stricklers - self.conf.stricklers = deepcopy(self._stricklers) + self._config.stricklers = deepcopy(self._stricklers) # Editor - self.conf.editor = self.get_line_edit_text("lineEdit_editor_cmd") + self._config.editor = self.get_line_edit_text("lineEdit_editor_cmd") # Language - self.conf.lang = Config.languages()[self.get_combobox_text("comboBox_language")] + self._config.lang = Config.languages()[self.get_combobox_text("comboBox_language")] self.end() @@ -230,13 +228,13 @@ class ConfigureWindow(ASubWindow, ListedSubWindow): self.end() def end(self): - self.conf.save() + self._config.save() self.close() # Debug def set_debug(self): - self.conf.debug = not self.conf.debug - logger.info(f"Debug mode set : {self.conf.debug}") + self._config.debug = not self._config.debug + logger.info(f"Debug mode set : {self._config.debug}") self.parent.setup_debug_mode() # Solvers @@ -246,6 +244,7 @@ class ConfigureWindow(ASubWindow, ListedSubWindow): for index in indexes: self.edit_solver = ConfigureSolverWindow( data=self.solver_table_model.rows[index.row()], + config=self._config, parent=self ) if self.edit_solver.exec_(): diff --git a/src/View/DummyWindow.py b/src/View/DummyWindow.py index 05117bca15659184948745eac437321b3a282d8b..768d6fbc7ce67427df18ed3671c13009f6d3132a 100644 --- a/src/View/DummyWindow.py +++ b/src/View/DummyWindow.py @@ -16,9 +16,14 @@ # -*- coding: utf-8 -*- -from View.ASubWindow import ASubWindow +from View.Tools.PamhyrWindow import PamhyrWindow -class DummyWindow(ASubWindow): - def __init__(self, title="Dummy", parent=None): - super(DummyWindow, self).__init__(name=title, ui="dummy", parent=parent) - self.ui.setWindowTitle(title) +class DummyWindow(PamhyrWindow): + __ui = "Dummy" + __name = "Pamhyr Dummy Window" + + def __init__(self, parent=None): + super(DummyWindow, self).__init__( + title = self.__name, + parent = parent, + ) diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index 47e148508b1d80c3877b5bebfd9bb8995da15e91..cf253dd5d4408f954988c7604cffbce7f58b8328 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -36,27 +36,27 @@ from PyQt5.QtWidgets import ( ) from PyQt5.uic import loadUi -from View.ASubWindow import WindowToolKit -from View.ListedSubWindow import ListedSubWindow +from View.Tools.ASubWindow import WindowToolKit +from View.Tools.ListedSubWindow import ListedSubWindow from View.DummyWindow import DummyWindow from View.Configure.Window import ConfigureWindow from View.Study.Window import NewStudyWindow from View.About.Window import AboutWindow from View.Network.Window import NetworkWindow -from View.Geometry.Window import GeometryWindow -from View.BoundaryCondition.Window import BoundaryConditionWindow -from View.LateralContribution.Window import LateralContributionWindow -from View.InitialConditions.Window import InitialConditionsWindow -from View.Stricklers.Window import StricklersWindow -from View.Frictions.Window import FrictionsWindow -from View.SedimentLayers.Window import SedimentLayersWindow -from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow -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 View.Geometry.Window import GeometryWindow +# from View.BoundaryCondition.Window import BoundaryConditionWindow +# from View.LateralContribution.Window import LateralContributionWindow +# from View.InitialConditions.Window import InitialConditionsWindow +# from View.Stricklers.Window import StricklersWindow +# from View.Frictions.Window import FrictionsWindow +# from View.SedimentLayers.Window import SedimentLayersWindow +# from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow +# 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 @@ -108,7 +108,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): self.conf = conf # Model - self.model = None + self._study = None # Results self._last_results = None @@ -133,8 +133,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): def set_title(self): title = "(dbg) " if self.conf.debug else "" - if self.model is not None: - title += f"Pamhyr2 - {self.model.name}" + if self._study is not None: + title += f"Pamhyr2 - {self._study.name}" self.setWindowTitle(title) else: title += "Pamhyr2" @@ -216,7 +216,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): super(ApplicationWindow, self).changeEvent(event) def close(self): - if self.model is not None and not self.model.is_saved: + if self._study is not None and not self._study.is_saved: self._close_question = True if self.dialog_close(): # PAMHYR is close correctly (no crash) @@ -233,7 +233,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): def closeEvent(self, event): if not self._close_question: - if self.model is not None and not self.model.is_saved: + if self._study is not None and not self._study.is_saved: if self.dialog_close(cancel = False): # PAMHYR is close correctly (no crash) self.conf.set_close_correctly() @@ -291,16 +291,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): ######### def get_model(self): - return self.model + return self._study def set_model(self, model): - self.model = model + self._study = model self.update_enable_action() - self.conf.set_last_study(self.model.filename) + self.conf.set_last_study(self._study.filename) self.set_title() def close_model(self): - self.model = None + self._study = None self.update_enable_action() self.conf.set_close_correctly() self.set_title() @@ -314,7 +314,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): Returns: Nothing """ - no_model = self.model is None + no_model = self._study is None for action in no_model_action: self.enable_actions(action, no_model) @@ -342,7 +342,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): Nothing """ self.set_model(Study.open(filename)) - logger.info(f"Open Study - {self.model.name}") + logger.info(f"Open Study - {self._study.name}") self.set_title() def save_study(self): @@ -354,22 +354,22 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): Returns: Nothing """ - if self.model.filename is None or self.model.filename == "": + if self._study.filename is None or self._study.filename == "": file_name, _ = QFileDialog.getSaveFileName( self, "Save File", "", "Pamhyr(*.pamhyr)" ) if file_name.rsplit(".", 1)[-1] == "pamhyr": - self.model.filename = file_name + self._study.filename = file_name else: - self.model.filename = file_name + ".pamhyr" + self._study.filename = file_name + ".pamhyr" - if self.model.is_saved: + if self._study.is_saved: return logger.info("Save...") - self.model.save() + self._study.save() def save_as_study(self): """Save current study as new file @@ -386,11 +386,11 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): ) if file_name[-4:] == ".pamhyr": - self.model.filename = file_name + self._study.filename = file_name else: - self.model.filename = file_name + ".pamhyr" + self._study.filename = file_name + ".pamhyr" - self.model.save() + self._study.save() ################## # MSG AND DIALOG # @@ -456,7 +456,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): Returns: Nothing """ - self.config = ConfigureWindow(conf=self.conf, parent=self) + self.config = ConfigureWindow(config=self.conf, parent=self) self.config.show() def open_about(self): @@ -476,7 +476,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): Returns: Nothing """ - if self.model is None: + if self._study is None: dialog = QFileDialog(self) dialog.setFileMode(QFileDialog.FileMode.ExistingFile) dialog.setDefaultSuffix(".pamhyr") @@ -494,7 +494,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): Returns: Nothing """ - if self.model is None: + if self._study is None: self.new_study = NewStudyWindow(parent=self) self.new_study.show() @@ -504,8 +504,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): Returns: Nothing """ - if not self.model is None: - self.new_study = NewStudyWindow(study=self.model, parent=self) + if not self._study is None: + self.new_study = NewStudyWindow(study=self._study, parent=self) self.new_study.show() def open_network(self): @@ -514,9 +514,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): Returns: Nothing """ - if self.model is not None: + if self._study is not None: if not self.sub_win_exists("River network"): - self.network = NetworkWindow(model=self.model, parent=self) + self.network = NetworkWindow(study=self._study, parent=self) self.network.show() else: self.network.activateWindow() @@ -527,14 +527,14 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): Returns: Nothing """ - if (self.model is not None and self.model.river.has_current_reach()): + if (self._study is not None and self._study.river.has_current_reach()): geometry = self.sub_win_filter_first( "Geometry", - contain = [self.model.river.current_reach().name] + contain = [self._study.river.current_reach().name] ) if geometry is None: - geometry = GeometryWindow(model=self.model, parent=self) + geometry = GeometryWindow(model=self._study, parent=self) geometry.show() else: geometry.activateWindow() @@ -548,7 +548,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): ) if bound is None: - bound = BoundaryConditionWindow(study = self.model, parent = self) + bound = BoundaryConditionWindow(study = self._study, parent = self) bound.show() else: bound.activateWindow() @@ -560,7 +560,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): ) if lateral is None: - lateral = LateralContributionWindow(study = self.model, parent = self) + lateral = LateralContributionWindow(study = self._study, parent = self) lateral.show() else: lateral.activateWindow() @@ -573,7 +573,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): if strick is None: strick = StricklersWindow( - study = self.model, + study = self._study, config = self.conf, parent = self ) @@ -582,17 +582,17 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): strick.activateWindow() def open_frictions(self): - if (self.model is not None and - self.model.river.has_current_reach()): + if (self._study is not None and + self._study.river.has_current_reach()): frictions = self.sub_win_filter_first( "Frictions", - contain = [self.model.river.current_reach().name] + contain = [self._study.river.current_reach().name] ) if frictions is None: frictions = FrictionsWindow( - study = self.model, + study = self._study, parent = self ) frictions.show() @@ -602,15 +602,15 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): self.msg_select_reach() def open_initial_conditions(self): - if self.model.river.has_current_reach(): + if self._study.river.has_current_reach(): initial = self.sub_win_filter_first( "Initial condition", - contain = [self.model.river.current_reach().name] + contain = [self._study.river.current_reach().name] ) if initial is None: initial = InitialConditionsWindow( - study = self.model, + study = self._study, parent = self ) initial.show() @@ -627,7 +627,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): if params is None: params = SolverParametersWindow( - study = self.model, + study = self._study, parent = self ) params.show() @@ -636,31 +636,31 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): def open_sediment_layers(self): sl = SedimentLayersWindow( - study = self.model, + study = self._study, parent = self ) sl.show() def open_reach_sediment_layers(self): sl = ReachSedimentLayersWindow( - study = self.model, + study = self._study, parent = self ) sl.show() def run_solver(self): - if self.model is None: + if self._study is None: return run = SelectSolverWindow( - study = self.model, + study = self._study, config = self.conf, parent = self ) if run.exec(): solver = run.solver check = CheckListWindow( - study = self.model, + study = self._study, config = self.conf, solver = solver, parent = self @@ -669,7 +669,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): def solver_log(self, solver): sol = SolverLogWindow( - study = self.model, + study = self._study, config = self.conf, solver = solver, parent = self @@ -693,7 +693,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): if res is None: res = ResultsWindow( - study = self.model, + study = self._study, solver = solver, results = results, parent = self @@ -708,18 +708,18 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): def open_debug(self): repl = ReplWindow( - study = self.model, + study = self._study, config = self.conf, parent = self ) repl.show() def open_sqlite(self): - if self.model is None: + if self._study is None: logger.debug("No study open for sql debuging...") return - file = self.model.filename + file = self._study.filename _ = subprocess.Popen( f"sqlitebrowser {file}", shell=True diff --git a/src/View/Network/Table.py b/src/View/Network/Table.py index 733a910d5e8194c62cf0928aa7a5fdc4b6fc363f..da74d8135d65275889c18e5e6d914835240e8d2e 100644 --- a/src/View/Network/Table.py +++ b/src/View/Network/Table.py @@ -22,7 +22,6 @@ import traceback from Model.Network.Node import Node from Model.Network.Edge import Edge from Model.Network.Graph import Graph -from View.ASubWindow import ASubWindow from View.Network.GraphWidget import GraphWidget from View.Network.UndoCommand import * from View.Tools.PamhyrTable import PamhyrTableModel diff --git a/src/View/Network/Window.py b/src/View/Network/Window.py index 95e575ea8fd94d6c1b547ef55ef662e264535a30..a54c0527b4a1a57a976f78e02fb1360020977831 100644 --- a/src/View/Network/Window.py +++ b/src/View/Network/Window.py @@ -16,6 +16,8 @@ # -*- coding: utf-8 -*- +import logging + from PyQt5.QtCore import QCoreApplication from PyQt5.QtGui import ( @@ -36,7 +38,7 @@ from PyQt5.QtWidgets import ( from Model.River import RiverNode, RiverReach, River -from View.ASubWindow import ASubMainWindow +from View.Tools.PamhyrWindow import PamhyrWindow from View.Network.GraphWidget import GraphWidget from View.Network.UndoCommand import * from View.Network.translate import ( @@ -47,36 +49,30 @@ from View.Network.Table import ( ComboBoxDelegate, NodeTableModel, EdgeTableModel, ) -_translate = QCoreApplication.translate +logger = logging.getLogger() +_translate = QCoreApplication.translate -class NetworkWindow(ASubMainWindow): - def __init__(self, model=None, title="River network", parent=None): - self._title = title - self._model = model - self._graph = self._model.river - self.setup_title() +class NetworkWindow(PamhyrWindow): + _pamhyr_ui = "Network" + _pamhyr_name = "River network" + def __init__(self, study=None, config=None, parent=None): super(NetworkWindow, self).__init__( - name=title, ui="Network", parent=parent + title = self._pamhyr_name + " - " + study.name, + study = study, + config = config, + options = ['undo'], + parent=parent, ) - self.ui.setWindowTitle(self._title) - self.setup_sc() + self._graph = study.river + self.setup_graph() self.setup_table() self.setup_connections() - def setup_title(self): - self._title = self._title + " - " + self._model.name - - def setup_sc(self): - self._undo_stack = QUndoStack() - - self.undo_sc = QShortcut(QKeySequence.Undo, self) - self.redo_sc = QShortcut(QKeySequence.Redo, self) - def setup_table(self): retranslate() @@ -143,9 +139,6 @@ class NetworkWindow(ASubMainWindow): self.clicked_del ) - self.undo_sc.activated.connect(self.undo) - self.redo_sc.activated.connect(self.redo) - def clicked_add(self): if self.get_action_checkable("action_toolBar_add"): self.set_action_checkable("action_toolBar_del", False) @@ -166,13 +159,15 @@ class NetworkWindow(ASubMainWindow): if key == Qt.Key_Escape: self._graph_widget.reset_selection - def undo(self): + # Redefine undo/redo method + + def _undo(self): self._undo_stack.undo() self._reachs_model.update() self._nodes_model.update() self._graph_widget.display_update() - def redo(self): + def _redo(self): self._undo_stack.redo() self._reachs_model.update() self._nodes_model.update() diff --git a/src/View/Study/Window.py b/src/View/Study/Window.py index 7218f9d36571cc315142ea9a3bb6ad7aa207a867..871d0545afdaacf7c3704ca30854bbf38ec06e52 100644 --- a/src/View/Study/Window.py +++ b/src/View/Study/Window.py @@ -17,7 +17,7 @@ # -*- coding: utf-8 -*- from Model.Study import Study -from View.ASubWindow import ASubWindow +from View.Tools.PamhyrWindow import PamhyrDialog from PyQt5.QtCore import QCoreApplication @@ -27,27 +27,37 @@ from PyQt5.QtWidgets import ( _translate = QCoreApplication.translate -class NewStudyWindow(ASubWindow): - def __init__(self, study=None, title="New Study", parent=None): - super(NewStudyWindow, self).__init__(name=title, ui="NewStudy", parent=parent) - self.ui.setWindowTitle(title) +class NewStudyWindow(PamhyrDialog): + _pamhyr_ui = "NewStudy" + _pamhyr_name = "Edit/New Study" - self.parent = parent - self.study = study + def __init__(self, study=None, config = None, parent=None): + if study is not None: + name = f"Edit study - {study.name}" + else: + name = "New study" + + super(NewStudyWindow, self).__init__( + title = name, + study = study, + config = config, + options = [], + parent = parent + ) - if not self.study is None: - self.set_line_edit_text("lineEdit_name", self.study.name) - self.set_text_edit_text("textEdit_description", self.study.description) - self.set_datetime_edit("dateTimeEdit_date", self.study.date) + if not self._study is None: + self.set_line_edit_text("lineEdit_name", self._study.name) + self.set_text_edit_text("textEdit_description", self._study.description) + self.set_datetime_edit("dateTimeEdit_date", self._study.date) self.find(QLabel, "label_creation_date_data").setText( - self.study.creation_date.isoformat(sep=" ") + self._study.creation_date.isoformat(sep=" ") ) self.find(QLabel, "label_last_modification_data").setText( - self.study.last_save_date.isoformat(sep=" ") + self._study.last_save_date.isoformat(sep=" ") ) - if self.study.time_system == "date": + if self._study.time_system == "date": self.set_radio_button("radioButton_date", True) self.find(QLabel, "label_date").setEnabled(True) self.find(QDateTimeEdit, "dateTimeEdit_date").setEnabled(True) @@ -76,18 +86,18 @@ class NewStudyWindow(ASubWindow): name = self.get_line_edit_text("lineEdit_name") description = self.get_text_edit_text("textEdit_description") - if self.study is None: + if self._study is None: study = Study.new(name, description) if self.get_radio_button("radioButton_date"): date = self.get_datetime_edit("dateTimeEdit_date") study.use_date(date) self.parent.set_model(study) else: - self.study.name = name - self.study.description = description + self._study.name = name + self._study.description = description if self.get_radio_button("radioButton_date"): date = self.get_datetime_edit("dateTimeEdit_date") - self.study.use_date(date) + self._study.use_date(date) else: - self.study.use_time() + self._study.use_time() self.done(True) diff --git a/src/View/ASubWindow.py b/src/View/Tools/ASubWindow.py similarity index 97% rename from src/View/ASubWindow.py rename to src/View/Tools/ASubWindow.py index 4e1c13279313adb77683afe7a3e9a4a9c36e6bba..9ac63c2d91be9bb1e44879f0a5b1b2b5865c7b40 100644 --- a/src/View/ASubWindow.py +++ b/src/View/Tools/ASubWindow.py @@ -463,11 +463,11 @@ class ASubWindowFeatures(object): # Top level interface class ASubMainWindow(QMainWindow, ASubWindowFeatures, WindowToolKit): - def __init__(self, name="", ui="dummy", parent=None): + def __init__(self, name="", ui="dummy", parent=None, **kwargs): super(ASubMainWindow, self).__init__(parent=parent) if ui is not None: self.ui = loadUi( - os.path.join(os.path.dirname(__file__), "ui", f"{ui}.ui"), + os.path.join(os.path.dirname(__file__), "..", "ui", f"{ui}.ui"), self ) @@ -496,10 +496,10 @@ class ASubMainWindow(QMainWindow, ASubWindowFeatures, WindowToolKit): return self.ui.findChild(qtype, name) class ASubWindow(QDialog, ASubWindowFeatures, WindowToolKit): - def __init__(self, name="", ui="dummy", parent=None): + def __init__(self, name="", ui="dummy", parent=None, **kwargs): super(ASubWindow, self).__init__(parent=parent) self.ui = loadUi( - os.path.join(os.path.dirname(__file__), "ui", f"{ui}.ui"), + os.path.join(os.path.dirname(__file__), "..", "ui", f"{ui}.ui"), self ) self.name = name @@ -530,7 +530,7 @@ class AWidget(QWidget, ASubWindowFeatures): def __init__(self, ui="", parent=None): super(AWidget, self).__init__(parent=parent) self.ui = loadUi( - os.path.join(os.path.dirname(__file__), "ui", "Widgets", f"{ui}.ui"), + os.path.join(os.path.dirname(__file__), "..", "ui", "Widgets", f"{ui}.ui"), self ) self.parent = parent diff --git a/src/View/ListedSubWindow.py b/src/View/Tools/ListedSubWindow.py similarity index 98% rename from src/View/ListedSubWindow.py rename to src/View/Tools/ListedSubWindow.py index b4dfe416d1dc62899f54dc88eddc36c5e78058aa..f671cc6041515869660220f9d331c7e2281ac674 100644 --- a/src/View/ListedSubWindow.py +++ b/src/View/Tools/ListedSubWindow.py @@ -22,7 +22,7 @@ from functools import reduce logger = logging.getLogger() class ListedSubWindow(object): - def __init__(self): + def __init__(self, **kwargs): super(ListedSubWindow, self).__init__() self.sub_win_cnt = 0 self.sub_win_list = [] diff --git a/src/View/Tools/PamhyrWindow.py b/src/View/Tools/PamhyrWindow.py new file mode 100644 index 0000000000000000000000000000000000000000..d6ae675247696462aa7b2e21554169c7c9e56a8c --- /dev/null +++ b/src/View/Tools/PamhyrWindow.py @@ -0,0 +1,189 @@ +# PamhyrWindow.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +# -*- coding: utf-8 -*- + +import logging + +from PyQt5.QtGui import ( + QKeySequence, +) + +from PyQt5.QtWidgets import ( + QUndoStack, QShortcut, +) + +from View.Tools.ASubWindow import ASubMainWindow, ASubWindow +from View.Tools.ListedSubWindow import ListedSubWindow + +logger = logging.getLogger() + +class PamhyrWindowTools(object): + def __init__(self, options = ["undo", "copy"], parent = None, **kwargs): + super(PamhyrWindowTools, self).__init__() + + self._undo_stack = None + + if "undo" in options: + self._init_undo() + + if "copy" in options: + self._init_copy() + + # Undo/Redo + + def _init_undo(self): + self._undo_stack = QUndoStack() + + self._undo_sc = QShortcut(QKeySequence.Undo, self) + self._redo_sc = QShortcut(QKeySequence.Redo, self) + + self._undo_sc.activated.connect(self._undo) + self._redo_sc.activated.connect(self._redo) + + def _undo(self): + if self._undo_stack is not None: + self._undo_stack.undo() + self._update() + + def _redo(self): + if self._undo_stack is not None: + self._undo_stack.redo() + self._update() + + # Copy/Paste + + def _init_copy(self): + self._copy_sc = QShortcut(QKeySequence.Copy, self) + self._paste_sc = QShortcut(QKeySequence.Paste, self) + + self._copy_sc.activated.connect(self._copy) + self._paste_sc.activated.connect(self._paste) + + def _copy(self): + if self._copy_stack is not None: + self._copy_stack.copy() + self._update() + + def _paste(self): + if self._copy_stack is not None: + self._copy_stack.redo() + self._update() + + # Display + + def _set_title(self): + """Apply `self._title` at current window title displayed + + Returns: + Nothing + """ + self.ui.setWindowTitle(self._title) + + def _update(self): + """Update window display component + + Returns: + Nothing + """ + self._set_title() + + # Hash methods + + @classmethod + def _hash(cls, data): + """Compute window hash + + Args: + data: window data parameters + + Returns: + The hash + """ + hash_str = cls._pamhyr_name + hash_str += cls._pamhyr_ui + + for el in data: + hash_str += repr(el) + + h = hash(hash_str) + logger.debug(f"Compute hash = {h} for window {cls._pamhyr_name}") + + return h + + def hash(self): + """Compute window hash + + Returns: + The hash + """ + data = [ + self._study, + self._config, + ] + + return self._hash() + + +class PamhyrWindow(ASubMainWindow, ListedSubWindow, PamhyrWindowTools): + _pamhyr_ui = "dummy" + _pamhyr_name = "PamhyrWindow" + + def __init__(self, + title = "Pamhyr2", + study = None, config = None, + options = ["undo", "copy"], + parent = None): + self._title = title + self._study = study + self._config = config + self._parent = parent + + logger.info(self._pamhyr_name) + + super(PamhyrWindow, self).__init__( + name = self._pamhyr_name, + ui = self._pamhyr_ui, + parent = parent, + ) + + self._set_title() + + +class PamhyrDialog(ASubWindow, ListedSubWindow, PamhyrWindowTools): + _pamhyr_ui = "dummy" + _pamhyr_name = "PamhyrWindow" + + def __init__(self, + title = "Pamhyr2", + study = None, config = None, + options = ["undo", "copy"], + parent = None): + self._title = title + self._study = study + self._config = config + self._parent = parent + + logger.info(self._pamhyr_name) + logger.info(self._pamhyr_ui) + + super(PamhyrDialog, self).__init__( + name = self._pamhyr_name, + ui = self._pamhyr_ui, + parent = parent, + ) + + self._set_title()