refactoring: Add PamhyrWindow and PamhyrDialog (WIP).

setup.py
Pierre-Antoine Rouby 2023-09-25 15:10:30 +02:00
parent 9c7f1f7ba9
commit fa32e42933
11 changed files with 408 additions and 194 deletions

View File

@ -19,14 +19,17 @@
import os import os
import logging import logging
from View.ASubWindow import ASubWindow from View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
logger = logging.getLogger() logger = logging.getLogger()
class AboutWindow(ASubWindow): class AboutWindow(PamhyrDialog):
_pamhyr_ui = "about"
_pamhyr_name = "About"
def _path_file(self, filename): def _path_file(self, filename):
return os.path.abspath( return os.path.abspath(
os.path.join( os.path.join(
@ -35,10 +38,14 @@ class AboutWindow(ASubWindow):
) )
) )
def __init__(self, study = None, config = None, parent=None):
def __init__(self, title="About", parent=None): super(AboutWindow, self).__init__(
super(AboutWindow, self).__init__(name=title, ui="about", parent=parent) title = _translate("About", "About"),
self.ui.setWindowTitle(title) study = study,
config = config,
options = [],
parent = parent
)
# Version # Version
with open(self._path_file("VERSION"), "r") as f: with open(self._path_file("VERSION"), "r") as f:

View File

@ -16,7 +16,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from View.ASubWindow import ASubWindow from View.Tools.PamhyrWindow import PamhyrDialog
from Solver.Solvers import solver_type_list from Solver.Solvers import solver_type_list
from Solver.GenericSolver import GenericSolver from Solver.GenericSolver import GenericSolver
@ -24,12 +24,22 @@ from PyQt5.QtWidgets import (
QPushButton, QPushButton,
) )
class ConfigureSolverWindow(ASubWindow): class ConfigureSolverWindow(PamhyrDialog):
def __init__(self, data=None, title="Configuration : Add Solver", parent=None): _pamhyr_ui = "ConfigureAddSolverDialog"
_pamhyr_name = "Add/Edit Solver"
def __init__(self, data=None, config=None, parent=None):
if data is not None:
name = f"Edit Solver - {data.name}"
else:
name = "Add a new Solver"
super(ConfigureSolverWindow, self).__init__( super(ConfigureSolverWindow, self).__init__(
name=title, ui="ConfigureAddSolverDialog", parent=parent title = name,
config = config,
options = [],
parent=parent
) )
self.ui.setWindowTitle(title)
# Combo box item # Combo box item
for solver in solver_type_list: for solver in solver_type_list:
@ -37,10 +47,10 @@ class ConfigureSolverWindow(ASubWindow):
# Data to return # Data to return
self.data = data self.data = data
if not self.data is None: if self.data is not None:
self.copy_data() self.copy_data()
self.connect() self.setup_connection()
def copy_data(self): def copy_data(self):
self.set_combobox_text("comboBox_solver", self.data.type) self.set_combobox_text("comboBox_solver", self.data.type)
@ -53,7 +63,7 @@ class ConfigureSolverWindow(ASubWindow):
self.set_line_edit_text("lineEdit_output", self.data._path_output) self.set_line_edit_text("lineEdit_output", self.data._path_output)
self.set_line_edit_text("lineEdit_output_cmd", self.data._cmd_output) self.set_line_edit_text("lineEdit_output_cmd", self.data._cmd_output)
def connect(self): def setup_connection(self):
# File button # File button
buttons = { buttons = {
"pushButton_input": (lambda: self.file_dialog( "pushButton_input": (lambda: self.file_dialog(

View File

@ -21,8 +21,7 @@ import logging
from copy import deepcopy from copy import deepcopy
from config import Config from config import Config
from View.ASubWindow import ASubWindow from View.Tools.PamhyrWindow import PamhyrDialog
from View.ListedSubWindow import ListedSubWindow
from View.Stricklers.Table import TableModel from View.Stricklers.Table import TableModel
from View.Stricklers.translate import * from View.Stricklers.translate import *
@ -95,50 +94,42 @@ class SolverTableModel(QAbstractTableModel):
self.layoutChanged.emit() self.layoutChanged.emit()
class ConfigureWindow(ASubWindow, ListedSubWindow): class ConfigureWindow(PamhyrDialog):
def __init__(self, conf=None, title="Configure", parent=None): _pamhyr_ui = "ConfigureDialog"
_pamhyr_name = "Configure"
def __init__(self, config=None, parent=None):
if config is None:
config = Config()
super(ConfigureWindow, self).__init__( super(ConfigureWindow, self).__init__(
name=title, ui="ConfigureDialog", parent=parent title = self._pamhyr_name,
config = config,
options = [],
parent=parent
) )
self.ui.setWindowTitle(title)
if conf is None: self.setup_custom_sc()
self.conf = Config() self.setup_solver()
else: self.setup_stricklers()
self.conf = conf self.setup_data()
self.setup_connection()
self.setup_sc() def setup_solver(self):
# Solver
table = self.find(QTableView, "tableView_solver") table = self.find(QTableView, "tableView_solver")
self.solver_table_model = SolverTableModel( self.solver_table_model = SolverTableModel(
headers = ["name", "type", "description"], headers = ["name", "type", "description"],
rows = conf.solvers rows = self._config.solvers
) )
table.setModel(self.solver_table_model) table.setModel(self.solver_table_model)
table.setSelectionBehavior(QAbstractItemView.SelectRows) table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True) table.setAlternatingRowColors(True)
table.resizeColumnsToContents()
# Meshing_Tool def setup_stricklers(self):
self.set_line_edit_text("lineEdit_meshing_tool", self.conf.meshing_tool)
# Const
self.set_line_edit_text("lineEdit_segment", str(self.conf.segment))
self.set_line_edit_text("lineEdit_max_listing", str(self.conf.max_listing))
# Backup
self.set_check_box("checkBox_backup", self.conf.backup_enable)
self.set_line_edit_text("lineEdit_backup_path", self.conf.backup_path)
self.set_time_edit("timeEdit_backup_frequence", self.conf.backup_frequence)
self.set_spin_box("spinBox_backup_max", self.conf.backup_max)
self.find(QTableView, "tableView_solver").resizeColumnsToContents()
self.connect()
# Stricklers
table = self.find(QTableView, f"tableView_stricklers") table = self.find(QTableView, f"tableView_stricklers")
self._stricklers = deepcopy(self.conf.stricklers) self._stricklers = deepcopy(self._config.stricklers)
self._stricklers_table = TableModel( self._stricklers_table = TableModel(
data = self._stricklers, data = self._stricklers,
undo = self._undo_stack, undo = self._undo_stack,
@ -148,26 +139,35 @@ class ConfigureWindow(ASubWindow, ListedSubWindow):
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True) table.setAlternatingRowColors(True)
def setup_data(self):
# Meshing_Tool
self.set_line_edit_text("lineEdit_meshing_tool", self._config.meshing_tool)
# Const
self.set_line_edit_text("lineEdit_segment", str(self._config.segment))
self.set_line_edit_text("lineEdit_max_listing", str(self._config.max_listing))
# Backup
self.set_check_box("checkBox_backup", self._config.backup_enable)
self.set_line_edit_text("lineEdit_backup_path", self._config.backup_path)
self.set_time_edit("timeEdit_backup_frequence", self._config.backup_frequence)
self.set_spin_box("spinBox_backup_max", self._config.backup_max)
# Editor # Editor
self.set_line_edit_text("lineEdit_editor_cmd", str(self.conf.editor)) self.set_line_edit_text("lineEdit_editor_cmd", str(self._config.editor))
# Language # Language
languages = Config.languages() languages = Config.languages()
for lang in languages: for lang in languages:
self.combobox_add_item("comboBox_language", lang) self.combobox_add_item("comboBox_language", lang)
if self.conf.lang == languages[lang]: if self._config.lang == languages[lang]:
self.set_combobox_text("comboBox_language", lang) self.set_combobox_text("comboBox_language", lang)
def setup_sc(self): def setup_custom_sc(self):
self._undo_stack = QUndoStack() self._debug_sc = QShortcut(QKeySequence("Ctrl+G"), self)
self._debug_sc.activated.connect(self.set_debug)
self.debug_sc = QShortcut(QKeySequence("Ctrl+G"), self) def setup_connection(self):
self.undo_sc = QShortcut(QKeySequence.Undo, self)
self.redo_sc = QShortcut(QKeySequence.Redo, self)
self.copy_sc = QShortcut(QKeySequence.Copy, self)
self.paste_sc = QShortcut(QKeySequence.Paste, self)
def connect(self):
buttons = { buttons = {
# Solvers # Solvers
"pushButton_solver_add": self.add_solver, "pushButton_solver_add": self.add_solver,
@ -195,33 +195,31 @@ class ConfigureWindow(ASubWindow, ListedSubWindow):
for button in buttons: for button in buttons:
self.find(QPushButton, button).clicked.connect(buttons[button]) self.find(QPushButton, button).clicked.connect(buttons[button])
self.debug_sc.activated.connect(self.set_debug)
def accept(self): def accept(self):
# Solvers # Solvers
self.conf.solvers = self.solver_table_model.rows.copy() self._config.solvers = self.solver_table_model.rows.copy()
# Meshing_Tool # Meshing_Tool
self.conf.meshing_tool = self.get_line_edit_text("lineEdit_meshing_tool") self._config.meshing_tool = self.get_line_edit_text("lineEdit_meshing_tool")
# Const # Const
self.conf.segment = self.get_line_edit_text("lineEdit_segment") self._config.segment = self.get_line_edit_text("lineEdit_segment")
self.conf.max_listing = self.get_line_edit_text("lineEdit_max_listing") self._config.max_listing = self.get_line_edit_text("lineEdit_max_listing")
# Backup # Backup
self.conf.backup_enable = self.get_check_box("checkBox_backup") self._config.backup_enable = self.get_check_box("checkBox_backup")
self.conf.backup_path = self.get_line_edit_text("lineEdit_backup_path") self._config.backup_path = self.get_line_edit_text("lineEdit_backup_path")
self.conf.backup_frequence = self.get_time_edit("timeEdit_backup_frequence") self._config.backup_frequence = self.get_time_edit("timeEdit_backup_frequence")
self.conf.backup_max = self.get_spin_box("spinBox_backup_max") self._config.backup_max = self.get_spin_box("spinBox_backup_max")
# Stricklers # Stricklers
self.conf.stricklers = deepcopy(self._stricklers) self._config.stricklers = deepcopy(self._stricklers)
# Editor # Editor
self.conf.editor = self.get_line_edit_text("lineEdit_editor_cmd") self._config.editor = self.get_line_edit_text("lineEdit_editor_cmd")
# Language # Language
self.conf.lang = Config.languages()[self.get_combobox_text("comboBox_language")] self._config.lang = Config.languages()[self.get_combobox_text("comboBox_language")]
self.end() self.end()
@ -230,13 +228,13 @@ class ConfigureWindow(ASubWindow, ListedSubWindow):
self.end() self.end()
def end(self): def end(self):
self.conf.save() self._config.save()
self.close() self.close()
# Debug # Debug
def set_debug(self): def set_debug(self):
self.conf.debug = not self.conf.debug self._config.debug = not self._config.debug
logger.info(f"Debug mode set : {self.conf.debug}") logger.info(f"Debug mode set : {self._config.debug}")
self.parent.setup_debug_mode() self.parent.setup_debug_mode()
# Solvers # Solvers
@ -246,6 +244,7 @@ class ConfigureWindow(ASubWindow, ListedSubWindow):
for index in indexes: for index in indexes:
self.edit_solver = ConfigureSolverWindow( self.edit_solver = ConfigureSolverWindow(
data=self.solver_table_model.rows[index.row()], data=self.solver_table_model.rows[index.row()],
config=self._config,
parent=self parent=self
) )
if self.edit_solver.exec_(): if self.edit_solver.exec_():

View File

@ -16,9 +16,14 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from View.ASubWindow import ASubWindow from View.Tools.PamhyrWindow import PamhyrWindow
class DummyWindow(ASubWindow): class DummyWindow(PamhyrWindow):
def __init__(self, title="Dummy", parent=None): __ui = "Dummy"
super(DummyWindow, self).__init__(name=title, ui="dummy", parent=parent) __name = "Pamhyr Dummy Window"
self.ui.setWindowTitle(title)
def __init__(self, parent=None):
super(DummyWindow, self).__init__(
title = self.__name,
parent = parent,
)

View File

@ -36,27 +36,27 @@ from PyQt5.QtWidgets import (
) )
from PyQt5.uic import loadUi from PyQt5.uic import loadUi
from View.ASubWindow import WindowToolKit from View.Tools.ASubWindow import WindowToolKit
from View.ListedSubWindow import ListedSubWindow from View.Tools.ListedSubWindow import ListedSubWindow
from View.DummyWindow import DummyWindow from View.DummyWindow import DummyWindow
from View.Configure.Window import ConfigureWindow from View.Configure.Window import ConfigureWindow
from View.Study.Window import NewStudyWindow from View.Study.Window import NewStudyWindow
from View.About.Window import AboutWindow from View.About.Window import AboutWindow
from View.Network.Window import NetworkWindow from View.Network.Window import NetworkWindow
from View.Geometry.Window import GeometryWindow # from View.Geometry.Window import GeometryWindow
from View.BoundaryCondition.Window import BoundaryConditionWindow # from View.BoundaryCondition.Window import BoundaryConditionWindow
from View.LateralContribution.Window import LateralContributionWindow # from View.LateralContribution.Window import LateralContributionWindow
from View.InitialConditions.Window import InitialConditionsWindow # from View.InitialConditions.Window import InitialConditionsWindow
from View.Stricklers.Window import StricklersWindow # from View.Stricklers.Window import StricklersWindow
from View.Frictions.Window import FrictionsWindow # from View.Frictions.Window import FrictionsWindow
from View.SedimentLayers.Window import SedimentLayersWindow # from View.SedimentLayers.Window import SedimentLayersWindow
from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow # from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow
from View.SolverParameters.Window import SolverParametersWindow # from View.SolverParameters.Window import SolverParametersWindow
from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow # from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow
from View.CheckList.Window import CheckListWindow # from View.CheckList.Window import CheckListWindow
from View.Results.Window import ResultsWindow # from View.Results.Window import ResultsWindow
from View.Debug.Window import ReplWindow # from View.Debug.Window import ReplWindow
from Model.Study import Study from Model.Study import Study
@ -108,7 +108,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
self.conf = conf self.conf = conf
# Model # Model
self.model = None self._study = None
# Results # Results
self._last_results = None self._last_results = None
@ -133,8 +133,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def set_title(self): def set_title(self):
title = "(dbg) " if self.conf.debug else "" title = "(dbg) " if self.conf.debug else ""
if self.model is not None: if self._study is not None:
title += f"Pamhyr2 - {self.model.name}" title += f"Pamhyr2 - {self._study.name}"
self.setWindowTitle(title) self.setWindowTitle(title)
else: else:
title += "Pamhyr2" title += "Pamhyr2"
@ -216,7 +216,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
super(ApplicationWindow, self).changeEvent(event) super(ApplicationWindow, self).changeEvent(event)
def close(self): def close(self):
if self.model is not None and not self.model.is_saved: if self._study is not None and not self._study.is_saved:
self._close_question = True self._close_question = True
if self.dialog_close(): if self.dialog_close():
# PAMHYR is close correctly (no crash) # PAMHYR is close correctly (no crash)
@ -233,7 +233,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def closeEvent(self, event): def closeEvent(self, event):
if not self._close_question: if not self._close_question:
if self.model is not None and not self.model.is_saved: if self._study is not None and not self._study.is_saved:
if self.dialog_close(cancel = False): if self.dialog_close(cancel = False):
# PAMHYR is close correctly (no crash) # PAMHYR is close correctly (no crash)
self.conf.set_close_correctly() self.conf.set_close_correctly()
@ -291,16 +291,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
######### #########
def get_model(self): def get_model(self):
return self.model return self._study
def set_model(self, model): def set_model(self, model):
self.model = model self._study = model
self.update_enable_action() self.update_enable_action()
self.conf.set_last_study(self.model.filename) self.conf.set_last_study(self._study.filename)
self.set_title() self.set_title()
def close_model(self): def close_model(self):
self.model = None self._study = None
self.update_enable_action() self.update_enable_action()
self.conf.set_close_correctly() self.conf.set_close_correctly()
self.set_title() self.set_title()
@ -314,7 +314,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
no_model = self.model is None no_model = self._study is None
for action in no_model_action: for action in no_model_action:
self.enable_actions(action, no_model) self.enable_actions(action, no_model)
@ -342,7 +342,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Nothing Nothing
""" """
self.set_model(Study.open(filename)) self.set_model(Study.open(filename))
logger.info(f"Open Study - {self.model.name}") logger.info(f"Open Study - {self._study.name}")
self.set_title() self.set_title()
def save_study(self): def save_study(self):
@ -354,22 +354,22 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
if self.model.filename is None or self.model.filename == "": if self._study.filename is None or self._study.filename == "":
file_name, _ = QFileDialog.getSaveFileName( file_name, _ = QFileDialog.getSaveFileName(
self, "Save File", self, "Save File",
"", "Pamhyr(*.pamhyr)" "", "Pamhyr(*.pamhyr)"
) )
if file_name.rsplit(".", 1)[-1] == "pamhyr": if file_name.rsplit(".", 1)[-1] == "pamhyr":
self.model.filename = file_name self._study.filename = file_name
else: else:
self.model.filename = file_name + ".pamhyr" self._study.filename = file_name + ".pamhyr"
if self.model.is_saved: if self._study.is_saved:
return return
logger.info("Save...") logger.info("Save...")
self.model.save() self._study.save()
def save_as_study(self): def save_as_study(self):
"""Save current study as new file """Save current study as new file
@ -386,11 +386,11 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
) )
if file_name[-4:] == ".pamhyr": if file_name[-4:] == ".pamhyr":
self.model.filename = file_name self._study.filename = file_name
else: else:
self.model.filename = file_name + ".pamhyr" self._study.filename = file_name + ".pamhyr"
self.model.save() self._study.save()
################## ##################
# MSG AND DIALOG # # MSG AND DIALOG #
@ -456,7 +456,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
self.config = ConfigureWindow(conf=self.conf, parent=self) self.config = ConfigureWindow(config=self.conf, parent=self)
self.config.show() self.config.show()
def open_about(self): def open_about(self):
@ -476,7 +476,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
if self.model is None: if self._study is None:
dialog = QFileDialog(self) dialog = QFileDialog(self)
dialog.setFileMode(QFileDialog.FileMode.ExistingFile) dialog.setFileMode(QFileDialog.FileMode.ExistingFile)
dialog.setDefaultSuffix(".pamhyr") dialog.setDefaultSuffix(".pamhyr")
@ -494,7 +494,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
if self.model is None: if self._study is None:
self.new_study = NewStudyWindow(parent=self) self.new_study = NewStudyWindow(parent=self)
self.new_study.show() self.new_study.show()
@ -504,8 +504,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
if not self.model is None: if not self._study is None:
self.new_study = NewStudyWindow(study=self.model, parent=self) self.new_study = NewStudyWindow(study=self._study, parent=self)
self.new_study.show() self.new_study.show()
def open_network(self): def open_network(self):
@ -514,9 +514,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
if self.model is not None: if self._study is not None:
if not self.sub_win_exists("River network"): if not self.sub_win_exists("River network"):
self.network = NetworkWindow(model=self.model, parent=self) self.network = NetworkWindow(study=self._study, parent=self)
self.network.show() self.network.show()
else: else:
self.network.activateWindow() self.network.activateWindow()
@ -527,14 +527,14 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Returns: Returns:
Nothing Nothing
""" """
if (self.model is not None and self.model.river.has_current_reach()): if (self._study is not None and self._study.river.has_current_reach()):
geometry = self.sub_win_filter_first( geometry = self.sub_win_filter_first(
"Geometry", "Geometry",
contain = [self.model.river.current_reach().name] contain = [self._study.river.current_reach().name]
) )
if geometry is None: if geometry is None:
geometry = GeometryWindow(model=self.model, parent=self) geometry = GeometryWindow(model=self._study, parent=self)
geometry.show() geometry.show()
else: else:
geometry.activateWindow() geometry.activateWindow()
@ -548,7 +548,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
) )
if bound is None: if bound is None:
bound = BoundaryConditionWindow(study = self.model, parent = self) bound = BoundaryConditionWindow(study = self._study, parent = self)
bound.show() bound.show()
else: else:
bound.activateWindow() bound.activateWindow()
@ -560,7 +560,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
) )
if lateral is None: if lateral is None:
lateral = LateralContributionWindow(study = self.model, parent = self) lateral = LateralContributionWindow(study = self._study, parent = self)
lateral.show() lateral.show()
else: else:
lateral.activateWindow() lateral.activateWindow()
@ -573,7 +573,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if strick is None: if strick is None:
strick = StricklersWindow( strick = StricklersWindow(
study = self.model, study = self._study,
config = self.conf, config = self.conf,
parent = self parent = self
) )
@ -582,17 +582,17 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
strick.activateWindow() strick.activateWindow()
def open_frictions(self): def open_frictions(self):
if (self.model is not None and if (self._study is not None and
self.model.river.has_current_reach()): self._study.river.has_current_reach()):
frictions = self.sub_win_filter_first( frictions = self.sub_win_filter_first(
"Frictions", "Frictions",
contain = [self.model.river.current_reach().name] contain = [self._study.river.current_reach().name]
) )
if frictions is None: if frictions is None:
frictions = FrictionsWindow( frictions = FrictionsWindow(
study = self.model, study = self._study,
parent = self parent = self
) )
frictions.show() frictions.show()
@ -602,15 +602,15 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
self.msg_select_reach() self.msg_select_reach()
def open_initial_conditions(self): def open_initial_conditions(self):
if self.model.river.has_current_reach(): if self._study.river.has_current_reach():
initial = self.sub_win_filter_first( initial = self.sub_win_filter_first(
"Initial condition", "Initial condition",
contain = [self.model.river.current_reach().name] contain = [self._study.river.current_reach().name]
) )
if initial is None: if initial is None:
initial = InitialConditionsWindow( initial = InitialConditionsWindow(
study = self.model, study = self._study,
parent = self parent = self
) )
initial.show() initial.show()
@ -627,7 +627,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if params is None: if params is None:
params = SolverParametersWindow( params = SolverParametersWindow(
study = self.model, study = self._study,
parent = self parent = self
) )
params.show() params.show()
@ -636,31 +636,31 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def open_sediment_layers(self): def open_sediment_layers(self):
sl = SedimentLayersWindow( sl = SedimentLayersWindow(
study = self.model, study = self._study,
parent = self parent = self
) )
sl.show() sl.show()
def open_reach_sediment_layers(self): def open_reach_sediment_layers(self):
sl = ReachSedimentLayersWindow( sl = ReachSedimentLayersWindow(
study = self.model, study = self._study,
parent = self parent = self
) )
sl.show() sl.show()
def run_solver(self): def run_solver(self):
if self.model is None: if self._study is None:
return return
run = SelectSolverWindow( run = SelectSolverWindow(
study = self.model, study = self._study,
config = self.conf, config = self.conf,
parent = self parent = self
) )
if run.exec(): if run.exec():
solver = run.solver solver = run.solver
check = CheckListWindow( check = CheckListWindow(
study = self.model, study = self._study,
config = self.conf, config = self.conf,
solver = solver, solver = solver,
parent = self parent = self
@ -669,7 +669,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def solver_log(self, solver): def solver_log(self, solver):
sol = SolverLogWindow( sol = SolverLogWindow(
study = self.model, study = self._study,
config = self.conf, config = self.conf,
solver = solver, solver = solver,
parent = self parent = self
@ -693,7 +693,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if res is None: if res is None:
res = ResultsWindow( res = ResultsWindow(
study = self.model, study = self._study,
solver = solver, solver = solver,
results = results, results = results,
parent = self parent = self
@ -708,18 +708,18 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
def open_debug(self): def open_debug(self):
repl = ReplWindow( repl = ReplWindow(
study = self.model, study = self._study,
config = self.conf, config = self.conf,
parent = self parent = self
) )
repl.show() repl.show()
def open_sqlite(self): def open_sqlite(self):
if self.model is None: if self._study is None:
logger.debug("No study open for sql debuging...") logger.debug("No study open for sql debuging...")
return return
file = self.model.filename file = self._study.filename
_ = subprocess.Popen( _ = subprocess.Popen(
f"sqlitebrowser {file}", f"sqlitebrowser {file}",
shell=True shell=True

View File

@ -22,7 +22,6 @@ import traceback
from Model.Network.Node import Node from Model.Network.Node import Node
from Model.Network.Edge import Edge from Model.Network.Edge import Edge
from Model.Network.Graph import Graph from Model.Network.Graph import Graph
from View.ASubWindow import ASubWindow
from View.Network.GraphWidget import GraphWidget from View.Network.GraphWidget import GraphWidget
from View.Network.UndoCommand import * from View.Network.UndoCommand import *
from View.Tools.PamhyrTable import PamhyrTableModel from View.Tools.PamhyrTable import PamhyrTableModel

View File

@ -16,6 +16,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import ( from PyQt5.QtGui import (
@ -36,7 +38,7 @@ from PyQt5.QtWidgets import (
from Model.River import RiverNode, RiverReach, River from Model.River import RiverNode, RiverReach, River
from View.ASubWindow import ASubMainWindow from View.Tools.PamhyrWindow import PamhyrWindow
from View.Network.GraphWidget import GraphWidget from View.Network.GraphWidget import GraphWidget
from View.Network.UndoCommand import * from View.Network.UndoCommand import *
from View.Network.translate import ( from View.Network.translate import (
@ -47,36 +49,30 @@ from View.Network.Table import (
ComboBoxDelegate, NodeTableModel, EdgeTableModel, ComboBoxDelegate, NodeTableModel, EdgeTableModel,
) )
logger = logging.getLogger()
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class NetworkWindow(ASubMainWindow): class NetworkWindow(PamhyrWindow):
def __init__(self, model=None, title="River network", parent=None): _pamhyr_ui = "Network"
self._title = title _pamhyr_name = "River network"
self._model = model
self._graph = self._model.river
self.setup_title()
def __init__(self, study=None, config=None, parent=None):
super(NetworkWindow, self).__init__( super(NetworkWindow, self).__init__(
name=title, ui="Network", parent=parent title = self._pamhyr_name + " - " + study.name,
study = study,
config = config,
options = ['undo'],
parent=parent,
) )
self.ui.setWindowTitle(self._title)
self.setup_sc() self._graph = study.river
self.setup_graph() self.setup_graph()
self.setup_table() self.setup_table()
self.setup_connections() self.setup_connections()
def setup_title(self):
self._title = self._title + " - " + self._model.name
def setup_sc(self):
self._undo_stack = QUndoStack()
self.undo_sc = QShortcut(QKeySequence.Undo, self)
self.redo_sc = QShortcut(QKeySequence.Redo, self)
def setup_table(self): def setup_table(self):
retranslate() retranslate()
@ -143,9 +139,6 @@ class NetworkWindow(ASubMainWindow):
self.clicked_del self.clicked_del
) )
self.undo_sc.activated.connect(self.undo)
self.redo_sc.activated.connect(self.redo)
def clicked_add(self): def clicked_add(self):
if self.get_action_checkable("action_toolBar_add"): if self.get_action_checkable("action_toolBar_add"):
self.set_action_checkable("action_toolBar_del", False) self.set_action_checkable("action_toolBar_del", False)
@ -166,13 +159,15 @@ class NetworkWindow(ASubMainWindow):
if key == Qt.Key_Escape: if key == Qt.Key_Escape:
self._graph_widget.reset_selection self._graph_widget.reset_selection
def undo(self): # Redefine undo/redo method
def _undo(self):
self._undo_stack.undo() self._undo_stack.undo()
self._reachs_model.update() self._reachs_model.update()
self._nodes_model.update() self._nodes_model.update()
self._graph_widget.display_update() self._graph_widget.display_update()
def redo(self): def _redo(self):
self._undo_stack.redo() self._undo_stack.redo()
self._reachs_model.update() self._reachs_model.update()
self._nodes_model.update() self._nodes_model.update()

View File

@ -17,7 +17,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from Model.Study import Study from Model.Study import Study
from View.ASubWindow import ASubWindow from View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
@ -27,27 +27,37 @@ from PyQt5.QtWidgets import (
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
class NewStudyWindow(ASubWindow): class NewStudyWindow(PamhyrDialog):
def __init__(self, study=None, title="New Study", parent=None): _pamhyr_ui = "NewStudy"
super(NewStudyWindow, self).__init__(name=title, ui="NewStudy", parent=parent) _pamhyr_name = "Edit/New Study"
self.ui.setWindowTitle(title)
self.parent = parent def __init__(self, study=None, config = None, parent=None):
self.study = study if study is not None:
name = f"Edit study - {study.name}"
else:
name = "New study"
if not self.study is None: super(NewStudyWindow, self).__init__(
self.set_line_edit_text("lineEdit_name", self.study.name) title = name,
self.set_text_edit_text("textEdit_description", self.study.description) study = study,
self.set_datetime_edit("dateTimeEdit_date", self.study.date) config = config,
options = [],
parent = parent
)
if not self._study is None:
self.set_line_edit_text("lineEdit_name", self._study.name)
self.set_text_edit_text("textEdit_description", self._study.description)
self.set_datetime_edit("dateTimeEdit_date", self._study.date)
self.find(QLabel, "label_creation_date_data").setText( self.find(QLabel, "label_creation_date_data").setText(
self.study.creation_date.isoformat(sep=" ") self._study.creation_date.isoformat(sep=" ")
) )
self.find(QLabel, "label_last_modification_data").setText( self.find(QLabel, "label_last_modification_data").setText(
self.study.last_save_date.isoformat(sep=" ") self._study.last_save_date.isoformat(sep=" ")
) )
if self.study.time_system == "date": if self._study.time_system == "date":
self.set_radio_button("radioButton_date", True) self.set_radio_button("radioButton_date", True)
self.find(QLabel, "label_date").setEnabled(True) self.find(QLabel, "label_date").setEnabled(True)
self.find(QDateTimeEdit, "dateTimeEdit_date").setEnabled(True) self.find(QDateTimeEdit, "dateTimeEdit_date").setEnabled(True)
@ -76,18 +86,18 @@ class NewStudyWindow(ASubWindow):
name = self.get_line_edit_text("lineEdit_name") name = self.get_line_edit_text("lineEdit_name")
description = self.get_text_edit_text("textEdit_description") description = self.get_text_edit_text("textEdit_description")
if self.study is None: if self._study is None:
study = Study.new(name, description) study = Study.new(name, description)
if self.get_radio_button("radioButton_date"): if self.get_radio_button("radioButton_date"):
date = self.get_datetime_edit("dateTimeEdit_date") date = self.get_datetime_edit("dateTimeEdit_date")
study.use_date(date) study.use_date(date)
self.parent.set_model(study) self.parent.set_model(study)
else: else:
self.study.name = name self._study.name = name
self.study.description = description self._study.description = description
if self.get_radio_button("radioButton_date"): if self.get_radio_button("radioButton_date"):
date = self.get_datetime_edit("dateTimeEdit_date") date = self.get_datetime_edit("dateTimeEdit_date")
self.study.use_date(date) self._study.use_date(date)
else: else:
self.study.use_time() self._study.use_time()
self.done(True) self.done(True)

View File

@ -463,11 +463,11 @@ class ASubWindowFeatures(object):
# Top level interface # Top level interface
class ASubMainWindow(QMainWindow, ASubWindowFeatures, WindowToolKit): class ASubMainWindow(QMainWindow, ASubWindowFeatures, WindowToolKit):
def __init__(self, name="", ui="dummy", parent=None): def __init__(self, name="", ui="dummy", parent=None, **kwargs):
super(ASubMainWindow, self).__init__(parent=parent) super(ASubMainWindow, self).__init__(parent=parent)
if ui is not None: if ui is not None:
self.ui = loadUi( self.ui = loadUi(
os.path.join(os.path.dirname(__file__), "ui", f"{ui}.ui"), os.path.join(os.path.dirname(__file__), "..", "ui", f"{ui}.ui"),
self self
) )
@ -496,10 +496,10 @@ class ASubMainWindow(QMainWindow, ASubWindowFeatures, WindowToolKit):
return self.ui.findChild(qtype, name) return self.ui.findChild(qtype, name)
class ASubWindow(QDialog, ASubWindowFeatures, WindowToolKit): class ASubWindow(QDialog, ASubWindowFeatures, WindowToolKit):
def __init__(self, name="", ui="dummy", parent=None): def __init__(self, name="", ui="dummy", parent=None, **kwargs):
super(ASubWindow, self).__init__(parent=parent) super(ASubWindow, self).__init__(parent=parent)
self.ui = loadUi( self.ui = loadUi(
os.path.join(os.path.dirname(__file__), "ui", f"{ui}.ui"), os.path.join(os.path.dirname(__file__), "..", "ui", f"{ui}.ui"),
self self
) )
self.name = name self.name = name
@ -530,7 +530,7 @@ class AWidget(QWidget, ASubWindowFeatures):
def __init__(self, ui="", parent=None): def __init__(self, ui="", parent=None):
super(AWidget, self).__init__(parent=parent) super(AWidget, self).__init__(parent=parent)
self.ui = loadUi( self.ui = loadUi(
os.path.join(os.path.dirname(__file__), "ui", "Widgets", f"{ui}.ui"), os.path.join(os.path.dirname(__file__), "..", "ui", "Widgets", f"{ui}.ui"),
self self
) )
self.parent = parent self.parent = parent

View File

@ -22,7 +22,7 @@ from functools import reduce
logger = logging.getLogger() logger = logging.getLogger()
class ListedSubWindow(object): class ListedSubWindow(object):
def __init__(self): def __init__(self, **kwargs):
super(ListedSubWindow, self).__init__() super(ListedSubWindow, self).__init__()
self.sub_win_cnt = 0 self.sub_win_cnt = 0
self.sub_win_list = [] self.sub_win_list = []

View File

@ -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()