Skip to content

Commit

Permalink
choices
Browse files Browse the repository at this point in the history
  • Loading branch information
JoschD committed Nov 17, 2023
1 parent 018339c commit f4d3dc5
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 8 deletions.
6 changes: 3 additions & 3 deletions omc3_gui/segment_by_segment/measurement_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ class OpticsMeasurement:
model_dir: Path = metafield("Model", "Path to the model folder", default=None)
accel: str = metafield("Accelerator", "Name of the accelerator", default=None)
output_dir: Path = metafield("Output", "Path to the sbs-output folder", default=None)
year: str = metafield("Year", "Year of the measurement (model)", default=None)
ring: int = metafield("Ring", "Ring of the accelerator", default=None)
beam: int = metafield("Beam", "Beam of the accelerator", default=None)
year: str = metafield("Year", "Year of the measurement (model)", default=None, choices=LHC_MODEL_YEARS)
ring: int = metafield("Ring", "Ring of the accelerator", default=None, choices=(1, 2, 3, 4))
beam: int = metafield("Beam", "Beam of the accelerator", default=None, choices=(1, 2))
elements: Dict[str, Segment] = None # List of elements
segments: Dict[str, Segment] = None # List of segments

Expand Down
12 changes: 9 additions & 3 deletions omc3_gui/segment_by_segment/measurement_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ def __init__(self, parent=None, optics_measurement: OpticsMeasurement = None):
self._update_ui()

def _set_size(self, width: int = -1, height: int = -1):
# Set position to the center of the parent
parent = self.parent()
# Set position to the center of the parent (does not work in WSL for me, jdilly 2023)
# parent = self.parent()
# if parent is not None:
# parent_geo = parent.geometry()
# parent_pos = parent.mapToGlobal(parent.pos()) # multiscreen support
Expand Down Expand Up @@ -61,7 +61,7 @@ def _build_gui(self):
self._dataclass_ui = DataClassUI.build_dataclass_ui(
field_def=[
FieldUIDef(name="measurement_dir", editable=False),
*(FieldUIDef(name) for name in ("output_dir", "accel", "beam", "year", "ring"))
*(FieldUIDef(name) for name in ("model_dir", "output_dir", "accel", "beam", "year", "ring"))
],
dclass=OpticsMeasurement,
)
Expand All @@ -79,6 +79,12 @@ def _update_ui(self):
self._dataclass_ui.reset_labels()

def accept(self):
try:
self._dataclass_ui.check_choices(only_modified=True)
except ValueError as e:
QtWidgets.QMessageBox.critical(self, "Error", str(e))
return

self._dataclass_ui.update_model()
super().accept()

Expand Down
31 changes: 29 additions & 2 deletions omc3_gui/utils/dataclass_ui.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
"""
DataClass UI
------------
This module allows to generate a simple UI's for dataclasses,
which allows to edit the values of a dataclass.
"""
from functools import partial
import inspect
import re
from dataclasses import MISSING, Field, dataclass, field, fields
from pathlib import Path
from typing import Callable, Dict, Optional, Sequence, Tuple, Union
from typing import Callable, Dict, List, Optional, Sequence, Tuple, Union
from omc3_gui.utils import file_dialogs

from qtpy import QtWidgets
Expand Down Expand Up @@ -151,6 +158,25 @@ def update_model(self):
for name in self.fields.keys():
self.update_model_from_widget(name)

def check_choices(self, only_modified: bool = False):
""" Checks all edit-widgets for valid choices. """
fields_choices = []
for name in self.fields.keys():
field = self.model.__dataclass_fields__[name]
field_ui = self.fields[field.name]
if only_modified and not field_ui.modified:
continue

choices = field.metadata.get("choices")
if choices is not None:
value = self.fields[field.name].get_value()
if value not in choices:
fields_choices.append(f"{field_ui.label.text()}: {value} not in {choices}")

if fields_choices:
full_str = "\n".join(fields_choices)
raise ValueError(f'The following fields contain wrong values:\n{full_str}')

@classmethod
def build_dataclass_ui(cls,
field_def: Sequence[Union[FieldUIDef, str]], dclass: Union[type, object] = None) -> 'DataClassUI':
Expand Down Expand Up @@ -243,10 +269,11 @@ def build_dataclass_ui(cls,
# Type-to-Widget Helpers ----------------------------------------------------------------

class QFullIntSpinBox(QtWidgets.QSpinBox):
""" Like a QSpinBox, but overwriting default range(0,100) with maximum integer range. """

def __init__(self, parent: Optional[QtWidgets.QWidget] = None) -> None:
super().__init__(parent)
self.setRange(-2**31, 2**31 - 1)
self.setRange(-2**31, 2**31 - 1) # range of signed 32-bit integers


TYPE_TO_WIDGET_MAP = {
Expand Down

0 comments on commit f4d3dc5

Please sign in to comment.