Source code for pymodaq_gui.managers.config_manager

from pathlib import Path

from qtpy import QtWidgets
from qtpy.QtWidgets import QMessageBox, QDialogButtonBox, QDialog

from pymodaq_utils.logger import set_logger, get_module_name

from pymodaq_gui.managers.parameter_manager import ParameterManager
from pymodaq_gui.parameter import ioxml, Parameter
from pymodaq_gui.utils import select_file
from pymodaq_gui.messenger import dialog as dialogbox


logger = set_logger(get_module_name(__file__))


[docs] class ConfigManager(ParameterManager): """ Manager class for handling configuration files and parameters. Provides functionality to create, load, modify, and save configuration files in XML format with a graphical user interface. Attributes: title (str): Display title for the configuration manager name (str): Internal name for the configuration manager config_path (Path): Path to the directory containing config files """ title = "Config" name = "config" def __init__(self, config_path: Path = "", msgbox=False): """ Initialize the ConfigManager. Args: config_path (Path, optional): Path to the configuration directory. Defaults to ''. msgbox (bool, optional): If True, shows a dialog box on initialization asking whether to create a new config or modify an existing one. Defaults to False. """ super().__init__(settings_name=self.name) self.config_path = config_path if msgbox: msgBox = QMessageBox() msgBox.setText(f"{self.title} Manager") msgBox.setInformativeText("What do you want to do?") cancel_button = msgBox.addButton(QMessageBox.StandardButton.Cancel) new_button = msgBox.addButton("New", QMessageBox.ButtonRole.ActionRole) modify_button = msgBox.addButton("Modify", QMessageBox.ButtonRole.AcceptRole) msgBox.setDefaultButton(QMessageBox.StandardButton.Cancel) ret = msgBox.exec() if msgBox.clickedButton() == new_button: self.set_new_config() elif msgBox.clickedButton() == modify_button: path = select_file(start_path=config_path, save=False, ext="xml") if path != "": self.set_config_from_file(str(path)) else: # cancel pass
[docs] def make_config(self): """ Create additional configuration parameters. Method to be subclassed to add custom parameters specific to the configuration needs of derived classes. Returns: list: List of parameter dictionaries to be added to the configuration. Empty list in base implementation. """ return []
[docs] def set_new_config(self, file: str = None, show=True): """ Create a new configuration with default parameters. Opens a dialog allowing the user to set up a new configuration file with a filename and any additional parameters defined in make_config(). Args: file (str, optional): Default filename for the new config. If None, uses "{title}_default". Defaults to None. """ if file is None: file = f"{self.title}_default" param = [ {"title": "Filename:", "name": "filename", "type": "str", "value": file}, ] additional_params = self.make_config() self.settings = Parameter.create( title=f"{self.title}", name=f"{self.name}", type="group", children=param + additional_params, ) logger.info("Creating a new remote file") if show: self.show_config()
[docs] def set_config_from_file(self, file_path: Path, show=True): """ Load an existing configuration from an XML file. Reads an XML configuration file and populates the settings tree with the parameters from the file. Args: file_path (Path): Path to the XML configuration file to load. show (bool, optional): If True, displays the configuration dialog after loading. Defaults to True. Note: If file_path is not a Path object, it will be converted to one. Only XML files are supported. """ if not isinstance(file_path, Path): file_path = Path(file_path) if file_path.suffix == ".xml": children = ioxml.XML_file_to_parameter(file_path) else: logger.exception("file_path must be of xml type") return self.settings = Parameter.create( title=f"{self.title}", name=f"{self.name}", type="group", children=children, ) if show: self.show_config()
[docs] def show_config(self, widget=None, overwrite=False): """ Display the configuration dialog for viewing and editing settings. Creates and shows a modal dialog containing the settings tree with Save and Cancel buttons. If the user clicks Save, the configuration is saved to file. Args: widget (QtWidgets.QWidget, optional): Additional widget to include in the dialog layout. Defaults to None. overwrite (bool, optional): If True, overwrites existing files without prompting. Defaults to False. Returns: bool: True if the file was successfully saved, False otherwise. """ dialog = QDialog() vlayout = QtWidgets.QVBoxLayout() vlayout.addWidget(self.settings_tree) dialog.setLayout(vlayout) buttonBox = QDialogButtonBox(parent=dialog) buttonBox.addButton("Save", QDialogButtonBox.ButtonRole.AcceptRole) buttonBox.accepted.connect(dialog.accept) buttonBox.addButton("Cancel", QDialogButtonBox.ButtonRole.RejectRole) buttonBox.rejected.connect(dialog.reject) vlayout.addWidget(buttonBox) dialog.setWindowTitle("Fill in information about this managers") if widget is not None and isinstance(widget, QtWidgets.QWidget): vlayout.addWidget(widget) res = dialog.exec() if res == QDialog.DialogCode.Accepted: return self.save_config(overwrite)
[docs] def save_config(self, overwrite=False): """ Save the current configuration to an XML file. Saves the settings to an XML file in the config_path directory using the filename specified in the settings. If the file already exists and overwrite is False, prompts the user for confirmation before overwriting. Args: overwrite (bool, optional): If True, overwrites existing files without prompting. If False, asks for user confirmation before overwriting. Defaults to False. Returns: bool: True if the file was successfully saved, False otherwise. Note: The filename is retrieved from the 'filename' parameter in settings. The file is saved with a .xml extension in the config_path directory. """ filename = self.settings.child("filename").value() saved = False try: ioxml.parameter_to_xml_file(self.settings, self.config_path.joinpath(filename), overwrite=overwrite) saved = True except FileExistsError as currenterror: logger.warning(f"{currenterror} File {filename}.xml exists") user_agreed = dialogbox( title="Overwrite confirmation", message="File exist do you want to overwrite it ?", ) if user_agreed: ioxml.parameter_to_xml_file(self.settings, self.config_path.joinpath(filename)) logger.warning(f"File {filename}.xml overwriten at user request") saved = True else: logger.warning(f"File {filename}.xml wasn't saved at user request") return saved