From 05ca37c64de61cab57af1c7fa5abe34c5fa7a395 Mon Sep 17 00:00:00 2001 From: Christoph Schmidt <christoph.,schmidt@tugraz.at> Date: Sat, 6 Jan 2024 15:07:26 +0100 Subject: [PATCH] No QApplication is now needed in case no UI is created --- examples/example/main.py | 45 ------------- examples/example3/ApplicationConfig.py | 39 +++++++++++ examples/example3/LaserConfig.py | 14 ++++ examples/example3/main.py | 66 +++++++++++++++++++ src/confighandler/controller/Field.py | 20 ++++-- .../controller/fields/FieldBool.py | 4 +- .../controller/fields/FieldFloat.py | 4 +- .../controller/fields/FieldInt.py | 4 +- .../controller/fields/FieldList.py | 5 +- .../controller/fields/FieldPath.py | 5 +- .../controller/fields/FieldSelectableList.py | 5 +- .../controller/fields/FieldString.py | 5 +- .../controller/fields/FieldTuple.py | 5 +- 13 files changed, 161 insertions(+), 60 deletions(-) create mode 100644 examples/example3/ApplicationConfig.py create mode 100644 examples/example3/LaserConfig.py create mode 100644 examples/example3/main.py diff --git a/examples/example/main.py b/examples/example/main.py index 029077c..7875e90 100644 --- a/examples/example/main.py +++ b/examples/example/main.py @@ -10,7 +10,6 @@ from ApplicationConfig import ApplicationConfig if __name__ == "__main__": - app = QApplication(sys.argv) # setup the logging module+ logging.basicConfig(level=logging.DEBUG) @@ -19,48 +18,4 @@ if __name__ == "__main__": config.module_log_enabled = True config.module_log_level = logging.DEBUG - #config.load('./configs/ApplicationConfig.yaml') - #config.autosave(enable=True, path='./') - # print(config.wafer_version) - # config.wafer_version.get() - # config.wafer_number.get() - # print(config.wafer_version) - - window = QMainWindow() - wdg = QWidget() - grd = QtWidgets.QGridLayout() - wdg.setLayout(grd) - grd.addWidget(config.view.widget(), 0, 0) - # grd.addWidget(config.view.widget(), 1, 0) - - tree = QTreeWidget() - - tree.setColumnCount(3) - tree.setHeaderLabels(["Name", "Type", "asdf"]) - tree.addTopLevelItem(config.view.ui_tree_widget_item(tree)) - grd.addWidget(tree, 2, 0) - - btn_set = QtWidgets.QPushButton("Set Wafer Number to 5") - btn_set.clicked.connect(lambda: config.wafer_number.set("5")) - grd.addWidget(btn_set, 3, 0) - - btn_save = QtWidgets.QPushButton("Save Config") - #btn_save.clicked.connect(lambda: config.save('./configs/ApplicationConfig.yaml')) - grd.addWidget(btn_save, 4, 0) - - # Add a new combo box - combo = QtWidgets.QComboBox() - grd.addWidget(combo, 5, 0) - # config.wafer_list1.view.add_new_view(combo) - - # config.wafer_list1.connect(test) - - window.setCentralWidget(wdg) - # print(config.load('config.yaml')) - - window.show() - - sys.exit(app.exec()) - # config.wafer_nr = "1234" - # config.save("test.yaml") diff --git a/examples/example3/ApplicationConfig.py b/examples/example3/ApplicationConfig.py new file mode 100644 index 0000000..480a53f --- /dev/null +++ b/examples/example3/ApplicationConfig.py @@ -0,0 +1,39 @@ +import logging +import sys +from pathlib import Path +import confighandler as cfg +from confighandler.controller.SelectableList import SelectableList +from LaserConfig import LaserConfig + + +class ApplicationConfig(cfg.ConfigNode): + + def __init__(self) -> None: + super().__init__() + + self.output_directory: cfg.Field[Path] = cfg.Field(Path("../../tests/t_{wafer_number}")) + + self.wafer_version: cfg.Field[str] = cfg.Field("v1.0", + friendly_name="wafer_version", + description="The version of the wafer") + + self.wafer_number: cfg.Field[int] = cfg.Field(1, + friendly_name="wafer_number", + description="The version of the wafer") + + self.check: cfg.Field[bool] = cfg.Field(False, friendly_name="testcheck", + description="Testcheck") + + self.wafer_nr: cfg.Field[str] = cfg.Field("12345ABCD_{wafer_number}", + friendly_name="wafer_nr", + description="The version of the wafer") + + self.wafer_number2: cfg.Field[tuple] = cfg.Field((1, 2), + friendly_name="wafer_number2", + description="The version of the wafer") + + self.wafer_list: cfg.Field[list] = cfg.Field([1, 2], + friendly_name="wafer_list", + description="The version of the wafer") + + self.register() diff --git a/examples/example3/LaserConfig.py b/examples/example3/LaserConfig.py new file mode 100644 index 0000000..3d1956b --- /dev/null +++ b/examples/example3/LaserConfig.py @@ -0,0 +1,14 @@ +import confighandler as cfg + + +class LaserConfig(cfg.ConfigNode): + + def __init__(self, internal_log, internal_log_level) -> None: + super().__init__(internal_log=internal_log, internal_log_level=internal_log_level) + self.wavelength_range = cfg.Field(850) + self.velocity = cfg.Field(2.0) + self.acceleration = cfg.Field(1.0) + self.deceleration = cfg.Field(1.0) + self.port = cfg.Field("USB 0") + + self.register() diff --git a/examples/example3/main.py b/examples/example3/main.py new file mode 100644 index 0000000..029077c --- /dev/null +++ b/examples/example3/main.py @@ -0,0 +1,66 @@ +import logging +import sys +sys.path.append('../../src') +import time + +from PySide6 import QtWidgets +from PySide6.QtCore import Signal, QObject +from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QTreeWidget +from ApplicationConfig import ApplicationConfig + + +if __name__ == "__main__": + app = QApplication(sys.argv) + + # setup the logging module+ + logging.basicConfig(level=logging.DEBUG) + + config = ApplicationConfig() + config.module_log_enabled = True + config.module_log_level = logging.DEBUG + + #config.load('./configs/ApplicationConfig.yaml') + #config.autosave(enable=True, path='./') + # print(config.wafer_version) + # config.wafer_version.get() + # config.wafer_number.get() + # print(config.wafer_version) + + window = QMainWindow() + wdg = QWidget() + grd = QtWidgets.QGridLayout() + wdg.setLayout(grd) + grd.addWidget(config.view.widget(), 0, 0) + # grd.addWidget(config.view.widget(), 1, 0) + + tree = QTreeWidget() + + tree.setColumnCount(3) + tree.setHeaderLabels(["Name", "Type", "asdf"]) + tree.addTopLevelItem(config.view.ui_tree_widget_item(tree)) + grd.addWidget(tree, 2, 0) + + btn_set = QtWidgets.QPushButton("Set Wafer Number to 5") + btn_set.clicked.connect(lambda: config.wafer_number.set("5")) + grd.addWidget(btn_set, 3, 0) + + btn_save = QtWidgets.QPushButton("Save Config") + #btn_save.clicked.connect(lambda: config.save('./configs/ApplicationConfig.yaml')) + grd.addWidget(btn_save, 4, 0) + + # Add a new combo box + combo = QtWidgets.QComboBox() + grd.addWidget(combo, 5, 0) + # config.wafer_list1.view.add_new_view(combo) + + # config.wafer_list1.connect(test) + + window.setCentralWidget(wdg) + # print(config.load('config.yaml')) + + window.show() + + sys.exit(app.exec()) + # config.wafer_nr = "1234" + + # config.save("test.yaml") diff --git a/src/confighandler/controller/Field.py b/src/confighandler/controller/Field.py index ace8d1f..a2ae326 100644 --- a/src/confighandler/controller/Field.py +++ b/src/confighandler/controller/Field.py @@ -8,9 +8,12 @@ Description: import logging import re +from abc import abstractmethod from pathlib import Path from typing import Generic, T, TypeVar +from PySide6.QtWidgets import QApplication + import confighandler from confighandler.controller.CObject import CObject from confighandler.controller.CSignal import CSignal @@ -45,13 +48,19 @@ class Field(Generic[T], CObject): self.keywords = {} # The view, usd for handling the UI - self.view = FieldView(self) - + if QApplication.instance() is not None: + self.view = self.create_view() + else: + self.view = None # Connected properties that should bet set if the field changes self.props = [] self._module_logger.debug(f"Field {self.field_name} created with value {value} of type {type(value)}") + @abstractmethod + def create_view(self): + return FieldView(self) + def __new__(cls, value, friendly_name: str = None, description: str = None): # print(f"Field {cls.__name__} created with value {value} of type {type(value)} -> {isinstance(value, int)}") if isinstance(value, str): @@ -188,7 +197,6 @@ class Field(Generic[T], CObject): if self._allowed_types is None: raise TypeError(f"No allowed types for {self.__class__.__name__}") - if not isinstance(self._allowed_types, tuple) or len(self._allowed_types) < 2: raise TypeError(f"Allowed types not defined correctly for {self.__class__.__name__}") @@ -209,7 +217,8 @@ class Field(Generic[T], CObject): # No valid type has been found if not type_allowed: - raise TypeError(f"Value for field {self.field_name} must be of type {self._allowed_types[0]}, not {type(value)}") + raise TypeError( + f"Value for field {self.field_name} must be of type {self._allowed_types[0]}, not {type(value)}") else: # Valid type found, convert to first arg value = self._allowed_types[0](value) @@ -244,7 +253,8 @@ class Field(Generic[T], CObject): def _on_keyword_changed(self): self.set(self._value_to_emit) - self.view.value_changed.emit(self._value_to_emit) + if self.view is not None: + self.view.value_changed.emit(self._value_to_emit) def _yaml_repr(self): raise NotImplementedError() diff --git a/src/confighandler/controller/fields/FieldBool.py b/src/confighandler/controller/fields/FieldBool.py index 4817fab..eb5e57f 100644 --- a/src/confighandler/controller/fields/FieldBool.py +++ b/src/confighandler/controller/fields/FieldBool.py @@ -13,8 +13,10 @@ from confighandler.view.fields.FieldViewBool import FieldViewBool class FieldBool(Field): def __init__(self, value: bool, friendly_name: str = None, description: str = None): super().__init__(value, friendly_name, description) - self.view = FieldViewBool(self) self._allowed_types = (bool, [int]) + def create_view(self): + return FieldViewBool(self) + def _yaml_repr(self): return bool(self.value) diff --git a/src/confighandler/controller/fields/FieldFloat.py b/src/confighandler/controller/fields/FieldFloat.py index d9dc772..4b82fbe 100644 --- a/src/confighandler/controller/fields/FieldFloat.py +++ b/src/confighandler/controller/fields/FieldFloat.py @@ -13,8 +13,10 @@ from confighandler.view.fields.FieldViewFloat import FieldViewFloat class FieldFloat(Field): def __init__(self, value: float, friendly_name: str = None, description: str = None): super().__init__(value, friendly_name, description) - self.view = FieldViewFloat(self) self._allowed_types = (int, [float]) + def create_view(self): + return FieldViewFloat(self) + def _yaml_repr(self): return float(self.value) diff --git a/src/confighandler/controller/fields/FieldInt.py b/src/confighandler/controller/fields/FieldInt.py index e9824ee..2309f47 100644 --- a/src/confighandler/controller/fields/FieldInt.py +++ b/src/confighandler/controller/fields/FieldInt.py @@ -13,8 +13,10 @@ from confighandler.view.fields.FieldViewInt import FieldViewInt class FieldInt(Field): def __init__(self, value: int, friendly_name: str = None, description: str = None): super().__init__(value, friendly_name, description) - self.view = FieldViewInt(self) self._allowed_types = (int, None) + def create_view(self): + return FieldViewInt(self) + def _yaml_repr(self): return int(self.value) diff --git a/src/confighandler/controller/fields/FieldList.py b/src/confighandler/controller/fields/FieldList.py index b97c442..07e03ee 100644 --- a/src/confighandler/controller/fields/FieldList.py +++ b/src/confighandler/controller/fields/FieldList.py @@ -13,8 +13,11 @@ from confighandler.view.fields.FieldViewList import FieldViewList class FieldList(Field): def __init__(self, value: tuple, friendly_name: str = None, description: str = None): super().__init__(value, friendly_name, description) - self.view = FieldViewList(self) + self._allowed_types = (list, [tuple]) + def create_view(self): + return FieldViewList(self) + def _yaml_repr(self): return str(self.value) diff --git a/src/confighandler/controller/fields/FieldPath.py b/src/confighandler/controller/fields/FieldPath.py index 2c8552b..0ce98c9 100644 --- a/src/confighandler/controller/fields/FieldPath.py +++ b/src/confighandler/controller/fields/FieldPath.py @@ -19,14 +19,13 @@ class FieldPath(Field): def __init__(self, value: str, friendly_name: str = None, description: str = None): super().__init__(value, friendly_name, description) - # self._value_replaced_keywords = self.replace_keywords(self.value) - self.view = FieldViewPath(self) self._input = self.value self._allowed_types = (Path, [pathlib.PurePosixPath, pathlib.PurePath, pathlib.PureWindowsPath, str]) - # self.ui_btn_opens = [] + def create_view(self): + return FieldViewPath(self) # ================================================================================================================== # Getter and Setter for value retrival # ================================================================================================================== diff --git a/src/confighandler/controller/fields/FieldSelectableList.py b/src/confighandler/controller/fields/FieldSelectableList.py index 984f927..138ada0 100644 --- a/src/confighandler/controller/fields/FieldSelectableList.py +++ b/src/confighandler/controller/fields/FieldSelectableList.py @@ -14,9 +14,12 @@ import confighandler as ch class FieldSelectableList(ch.Field): def __init__(self, value: ch.SelectableList, friendly_name: str = None, description: str = None): super().__init__(value, friendly_name, description) - self.view = ch.FieldViewSelectableList(self) + self._allowed_types = (int, None) + def create_view(self): + return ch.FieldViewSelectableList(self) + def get_list(self) -> list: return list(self._value) diff --git a/src/confighandler/controller/fields/FieldString.py b/src/confighandler/controller/fields/FieldString.py index 84a4e1c..2738a53 100644 --- a/src/confighandler/controller/fields/FieldString.py +++ b/src/confighandler/controller/fields/FieldString.py @@ -14,8 +14,11 @@ class FieldString(Field): def __init__(self, value, friendly_name: str = None, description: str = None): super().__init__(value, friendly_name, description) self._value_replaced_keywords = self.replace_keywords(self.value) - self.view = FieldViewString(self) + self._allowed_types = (str, []) + def create_view(self): + return FieldViewString(self) + def _yaml_repr(self): return f"\"{self.value}\"" diff --git a/src/confighandler/controller/fields/FieldTuple.py b/src/confighandler/controller/fields/FieldTuple.py index b5d0803..a31f148 100644 --- a/src/confighandler/controller/fields/FieldTuple.py +++ b/src/confighandler/controller/fields/FieldTuple.py @@ -13,9 +13,12 @@ from confighandler.view.fields.FieldViewTuple import FieldViewTuple class FieldTuple(Field): def __init__(self, value: tuple, friendly_name: str = None, description: str = None): super().__init__(value, friendly_name, description) - self.view = FieldViewTuple(self) + self._allowed_types = (tuple, None) + def create_view(self): + return FieldViewTuple(self) + def _yaml_repr(self): return str(self.value) -- GitLab