0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-14 11:41:49 +02:00

refactor: widget_hierarchy.py changed into general purpose modul to extract values from widgets using handlers

This commit is contained in:
wyzula-jan
2023-11-08 11:06:37 +01:00
parent ebd0e588d4
commit 9308f60b88

View File

@ -10,40 +10,41 @@ from PyQt5.QtWidgets import (
QVBoxLayout,
)
from abc import ABC, abstractmethod
class WidgetHandler:
@staticmethod
def get_value(widget):
raise NotImplementedError
@staticmethod
def set_value(widget, value):
raise NotImplementedError
class WidgetHandler(ABC):
"""Abstract base class for all widget handlers."""
@abstractmethod
def get_value(self, widget: QWidget):
"""Retrieve value from the widget instance."""
pass
@abstractmethod
def set_value(self, widget: QWidget, value):
"""Set a value on the widget instance."""
pass
class LineEditHandler(WidgetHandler):
@staticmethod
def get_value(widget):
def get_value(self, widget: QLineEdit) -> str:
return widget.text()
@staticmethod
def set_value(widget, value):
def set_value(self, widget: QLineEdit, value: str) -> None:
widget.setText(value)
class ComboBoxHandler(WidgetHandler):
@staticmethod
def get_value(widget):
def get_value(self, widget: QComboBox) -> int:
return widget.currentIndex()
@staticmethod
def set_value(widget, value):
def set_value(self, widget: QComboBox, value: int) -> None:
widget.setCurrentIndex(value)
class TableWidgetHandler(WidgetHandler):
@staticmethod
def get_value(widget):
def get_value(self, widget: QTableWidget) -> list:
return [
[
widget.item(row, col).text() if widget.item(row, col) else ""
@ -52,8 +53,7 @@ class TableWidgetHandler(WidgetHandler):
for row in range(widget.rowCount())
]
@staticmethod
def set_value(widget, value):
def set_value(self, widget: QTableWidget, value) -> None:
for row, row_values in enumerate(value):
for col, cell_value in enumerate(row_values):
item = QTableWidgetItem(str(cell_value))
@ -61,40 +61,87 @@ class TableWidgetHandler(WidgetHandler):
class SpinBoxHandler(WidgetHandler):
@staticmethod
def get_value(widget):
def get_value(self, widget):
return widget.value()
@staticmethod
def set_value(widget, value):
def set_value(self, widget, value):
widget.setValue(value)
HANDLERS = {
# TODO remove when widgetIO works
# HANDLERS = {
# QLineEdit: LineEditHandler,
# QComboBox: ComboBoxHandler,
# QTableWidget: TableWidgetHandler,
# QSpinBox: SpinBoxHandler,
# QDoubleSpinBox: SpinBoxHandler,
# }
#
##################### Public interface for getting and setting values #####################
# def get_value(widget):
# handler_class = HANDLERS.get(type(widget))
# if handler_class:
# return handler_class.get_value(widget)
# return None
#
#
# def set_value(widget, value):
# handler_class = HANDLERS.get(type(widget))
# if handler_class:
# handler_class.set_value(widget, value)
class WidgetIO:
"""Public interface for getting and setting values using handler mapping"""
_handlers = {
QLineEdit: LineEditHandler,
QComboBox: ComboBoxHandler,
QTableWidget: TableWidgetHandler,
QSpinBox: SpinBoxHandler,
QDoubleSpinBox: SpinBoxHandler,
}
}
def get_value(widget):
handler_class = HANDLERS.get(type(widget))
@staticmethod
def get_value(widget, ignore_errors=False):
"""
Retrieve value from the widget instance.
Args:
widget: Widget instance.
ignore_errors(bool, optional): Whether to ignore if no handler is found.
"""
handler_class = WidgetIO._handlers.get(type(widget))
if handler_class:
return handler_class.get_value(widget)
return handler_class().get_value(widget) # Instantiate the handler
if not ignore_errors:
raise ValueError(f"No handler for widget type: {type(widget)}")
return None
def set_value(widget, value):
handler_class = HANDLERS.get(type(widget))
@staticmethod
def set_value(widget, value, ignore_errors=False):
"""
Set a value on the widget instance.
Args:
widget: Widget instance.
value: Value to set.
ignore_errors(bool, optional): Whether to ignore if no handler is found.
"""
handler_class = WidgetIO._handlers.get(type(widget))
if handler_class:
handler_class.set_value(widget, value)
handler_class().set_value(widget, value) # Instantiate the handler
elif not ignore_errors:
raise ValueError(f"No handler for widget type: {type(widget)}")
def print_widget_hierarchy(
##################### Public interface for exporting and importing widget hierarchies #####################
class WidgetHierarchy:
@staticmethod
def print_widget_hierarchy(
widget, indent: int = 0, grab_values: bool = False, prefix: str = ""
) -> None:
) -> None:
"""
Print the widget hierarchy to the console.
Args:
@ -105,7 +152,7 @@ def print_widget_hierarchy(
"""
widget_info = f"{widget.__class__.__name__} ({widget.objectName()})"
if grab_values:
value = get_value(widget)
value = WidgetIO.get_value(widget, ignore_errors=True)
value_str = f" [value: {value}]" if value is not None else ""
widget_info += value_str
@ -115,17 +162,19 @@ def print_widget_hierarchy(
for child in children:
child_prefix = prefix + " "
arrow = "├─ " if child != children[-1] else "└─ "
print_widget_hierarchy(child, indent + 1, grab_values, prefix=child_prefix + arrow)
WidgetHierarchy.print_widget_hierarchy(
child, indent + 1, grab_values, prefix=child_prefix + arrow
)
def export_config_to_dict(
@staticmethod
def export_config_to_dict(
widget,
config=None,
indent=0,
grab_values: bool = False,
print_hierarchy: bool = False,
save_all: bool = True,
) -> dict:
) -> dict:
"""
Export the widget hierarchy to a dictionary.
Args:
@ -142,8 +191,8 @@ def export_config_to_dict(
config = {}
widget_info = f"{widget.__class__.__name__} ({widget.objectName()})"
if grab_values:
value = get_value(widget)
if grab_values and type(widget) in WidgetIO._handlers:
value = WidgetIO.get_value(widget, ignore_errors=True)
if value is not None or save_all:
if widget_info not in config:
config[widget_info] = {}
@ -151,10 +200,10 @@ def export_config_to_dict(
config[widget_info]["value"] = value
if print_hierarchy:
print_widget_hierarchy(widget, indent, grab_values)
WidgetHierarchy.print_widget_hierarchy(widget, indent, grab_values)
for child in widget.children():
child_config = export_config_to_dict(
child_config = WidgetHierarchy.export_config_to_dict(
child, None, indent + 1, grab_values, print_hierarchy, save_all
)
if child_config or save_all:
@ -164,8 +213,8 @@ def export_config_to_dict(
return config
def import_config_from_dict(widget, config: dict, set_values: bool = False) -> None:
@staticmethod
def import_config_from_dict(widget, config: dict, set_values: bool = False) -> None:
"""
Import the widget hierarchy from a dictionary.
Args:
@ -181,14 +230,17 @@ def import_config_from_dict(widget, config: dict, set_values: bool = False) -> N
if child_config is not None:
value = child_config.get("value")
if set_values and value is not None:
set_value(child, value)
import_config_from_dict(child, widget_config, set_values)
WidgetIO.set_value(child, value)
WidgetHierarchy.import_config_from_dict(child, widget_config, set_values)
# Example application to demonstrate the usage of the functions
if __name__ == "__main__":
app = QApplication([])
# Create instance of WidgetHierarchy
widget_hierarchy = WidgetHierarchy()
# Create a simple widget hierarchy for demonstration purposes
main_widget = QWidget()
layout = QVBoxLayout(main_widget)
@ -210,7 +262,9 @@ if __name__ == "__main__":
print(30 * "#")
print(f"Widget hierarchy for {main_widget.objectName()}:")
print(30 * "#")
config_dict = export_config_to_dict(main_widget, grab_values=True, print_hierarchy=True)
config_dict = widget_hierarchy.export_config_to_dict(
main_widget, grab_values=True, print_hierarchy=True
)
print(30 * "#")
print(f"Config dict: {config_dict}")
@ -223,10 +277,12 @@ if __name__ == "__main__":
"QSpinBox ()": {"value": 10},
}
}
import_config_from_dict(main_widget, new_config_dict, set_values=True)
widget_hierarchy.import_config_from_dict(main_widget, new_config_dict, set_values=True)
print(30 * "#")
config_dict_new = export_config_to_dict(main_widget, grab_values=True, print_hierarchy=True)
config_dict_new_reduced = export_config_to_dict(
config_dict_new = widget_hierarchy.export_config_to_dict(
main_widget, grab_values=True, print_hierarchy=True
)
config_dict_new_reduced = widget_hierarchy.export_config_to_dict(
main_widget, grab_values=True, print_hierarchy=True, save_all=False
)
print(30 * "#")