extended loading

This commit is contained in:
2026-05-20 10:09:05 +02:00
parent e46e494500
commit e97999713e

View File

@@ -16,7 +16,16 @@ from typing import Annotated, Any, Protocol, TypeAlias, TypedDict
import babel
from pydantic import BaseModel, ConfigDict, EmailStr, Field, ValidationError, field_validator
from PySide6.QtCore import QDate, QModelIndex, QStringListModel, Qt, QTimer, Signal
from PySide6.QtCore import (
QDate,
QEvent,
QModelIndex,
QObject,
QStringListModel,
Qt,
QTimer,
Signal,
)
from PySide6.QtGui import QAction, QStandardItem, QStandardItemModel
from PySide6.QtWidgets import (
QApplication,
@@ -193,8 +202,12 @@ def pprint_registry(widget_registry: WidgetRegistry) -> None:
class CustomForm(Protocol):
def get_form_data(self) -> dict[str, Any]: ...
def set_form_data(self, data: Any) -> None: ...
def reset_form(self) -> None: ...
def validate_form_data(self) -> list[str]: ...
def _build_ui_recursively(
schema: Sequence[FormField],
@@ -202,6 +215,7 @@ def _build_ui_recursively(
widget_registry: WidgetRegistry,
prefix: str = "",
) -> None:
no_scroll_filter = NoScrollFilter(parent_layout)
for field in schema:
full_key = f"{prefix}.{field.key}" if prefix else field.key
widget: QWidget
@@ -232,6 +246,7 @@ def _build_ui_recursively(
"widget": widget,
"form_field": field,
}
widget.installEventFilter(no_scroll_filter)
if field.tooltip:
tooltip_layout = _add_tooltip(widget, field.tooltip)
@@ -252,6 +267,7 @@ def _build_ui_recursively(
"widget": widget,
"form_field": field,
}
widget.installEventFilter(no_scroll_filter)
if field.tooltip:
tooltip_layout = _add_tooltip(widget, field.tooltip)
@@ -293,6 +309,7 @@ def _build_ui_recursively(
"widget": widget,
"form_field": field,
}
widget.installEventFilter(no_scroll_filter)
if field.tooltip:
tooltip_layout = _add_tooltip(widget, field.tooltip)
@@ -321,6 +338,7 @@ def _build_ui_recursively(
"widget": widget,
"form_field": field,
}
widget.installEventFilter(no_scroll_filter)
if field.tooltip:
tooltip_layout = _add_tooltip(widget, field.tooltip)
@@ -359,6 +377,7 @@ def _build_ui_recursively(
"widget": widget,
"form_field": field,
}
widget.installEventFilter(no_scroll_filter)
if field.tooltip:
tooltip_layout = _add_tooltip(widget, field.tooltip)
@@ -618,19 +637,11 @@ class Grunderfassung_Unternehmen(BaseModel):
Projektrelevanz: Grunderfassung_Projektrelevanz | None = None
Kontaktperson: Grunderfassung_Kontaktperson | None = None
Stammdaten: Grunderfassung_Stammdaten | None = None
WeitereInfos: Grunderfassung_WeitereInfos | None = None
Schulbildung: list[Grunderfassung_Schulbildung] | None = None
class Grunderfassung_Schulbildung(BaseModel):
model_config = ConfigDict(str_strip_whitespace=True)
SB_abschluss: str | None
SB_abschlussgrad: str | None
SB_schule: str | None
SB_ort: str | None
SB_land: str | None
SB_abschlussjahr: str | None
SB_bemerkungsfeld: str | None
HoehereBildung: list[Grunderfassung_HoehereBildung] | None = None
Arbeitserfahrung: list[Grunderfassung_Arbeitserfahrung] | None = None
Sprachkenntnisse: list[Grunderfassung_Sprachen] | None = None
class Grunderfassung_Projektrelevanz(BaseModel):
@@ -719,6 +730,65 @@ class Grunderfassung_Stammdaten_AnzahlKinder(BaseModel):
alter: list[ValidAge | None] | None = None
class Grunderfassung_WeitereInfos(BaseModel):
model_config = ConfigDict(str_strip_whitespace=True)
WI_deutsch_sprache: str | None
WI_aufenthaltstitel: str | None
WI_gueltigkeit_aufenthaltstitel: datetime.date | None
WI_arbeitsstatus: str | None
WI_meldung_institution: str | None
class Grunderfassung_Schulbildung(BaseModel):
model_config = ConfigDict(str_strip_whitespace=True)
SB_abschluss: str | None
SB_abschlussgrad: str | None
SB_schule: str | None
SB_ort: str | None
SB_land: str | None
SB_abschlussjahr: str | None
SB_bemerkungsfeld: str | None
class Grunderfassung_HoehereBildung(BaseModel):
model_config = ConfigDict(str_strip_whitespace=True)
HB_anerkennung: str | None
HB_abschlussgrad: str | None
HB_abschlussgrad_dokument: str | None
HB_organisation: str | None
HB_beruf: str | None
HB_land: str | None
HB_ort: str | None
HB_abschlussjahr: str | None
HB_bemerkungsfeld: str | None
class Grunderfassung_Arbeitserfahrung(BaseModel):
model_config = ConfigDict(str_strip_whitespace=True)
AE_branche: str | None
AE_bezeichnung: str | None
AE_funktion: str | None
AE_unternehmen: str | None
AE_land: str | None
AE_zeitspanne: str | None
AE_beschaeftigungsart: str | None
AE_bemerkungsfeld: str | None
class Grunderfassung_Sprachen(BaseModel):
model_config = ConfigDict(str_strip_whitespace=True)
SP_sprache: str | None
SP_niveau: str | None
SP_nachweis: str | None
SP_art_nachweis: str | None
SP_datum_nachweis: datetime.date | None
class CompanyForm_Search(QWidget):
company_selected = Signal(int)
@@ -1032,21 +1102,21 @@ class WidgetRegistryEntry(TypedDict):
WidgetRegistry: TypeAlias = dict[str, WidgetRegistryEntry]
def search_widget_by_key(
def search_widgets_by_key(
widget_registry: WidgetRegistry,
key_part: str,
) -> QWidget | None:
) -> list[WidgetRegistryEntry]:
"""
needed for custom logic of auto-built forms,
search for specific keys and obtain the widget to assign
special logic or callbacks to them
"""
hit: QWidget | None = None
hits: list[WidgetRegistryEntry] = []
for key, entry in widget_registry.items():
if key_part in key:
hit = entry["widget"]
hits.append(entry)
return hit
return hits
FORM_FIELDS_CONTACT_PERSON = [
@@ -1258,14 +1328,6 @@ FORM_FIELDS_MASTER_DATA = [
required=False,
tooltip="* Wichtig zu erfragen aufgrund Lebensunterhaltssicherung",
),
# FormField(
# "Anzahl Kinder",
# FormFieldType.DYNAMIC_DROPDOWN,
# key="Stammdaten_anzahl_kinder",
# required=False,
# options=[(str(x), None) for x in range(11)],
# tooltip="* Wichtig zu erfragen aufgrund Lebensunterhaltssicherung",
# ),
FormField(
"Anzahl Kinder",
FormFieldType.DYNAMIC_DROPDOWN,
@@ -1293,6 +1355,7 @@ FORM_FIELDS_ADDITIONAL_DATA = [
"Deutsch als Kommunikationssprache",
FormFieldType.DROPDOWN,
required=False,
key="WI_deutsch_sprache",
options=[
("nein", None),
("ja, als Muttersprache", None),
@@ -1303,6 +1366,7 @@ FORM_FIELDS_ADDITIONAL_DATA = [
"Aufenthaltstitel",
FormFieldType.DROPDOWN,
required=False,
key="WI_aufenthaltstitel",
options=[
("anerkannter Flüchtling §§ 22 - 26 AufenthG", None),
("Aufenthaltsgestattung §55 AufenthG", None),
@@ -1325,11 +1389,13 @@ FORM_FIELDS_ADDITIONAL_DATA = [
"Gültigkeit Aufenthaltsstatus",
FormFieldType.DATE,
required=False,
key="WI_gueltigkeit_aufenthaltstitel",
),
FormField(
"Arbeitsstatus aktuell",
FormFieldType.DROPDOWN,
required=False,
key="WI_arbeitsstatus",
options=[
("Arbeitslos", None),
("Ausbildung/Qualifizierung Inland", None),
@@ -1345,6 +1411,7 @@ FORM_FIELDS_ADDITIONAL_DATA = [
"Gemeldet bei Institutionen ",
FormFieldType.DROPDOWN,
required=False,
key="WI_meldung_institution",
options=[
("bei keiner", None),
("Jobcenter mit Leistungsbezug", None),
@@ -1399,11 +1466,13 @@ FORM_FIELDS_HIGHER_EDUCATION = [
"Anerkennung",
FormFieldType.TEXT,
required=False,
key="HB_anerkennung",
),
FormField(
"Abschlussgrad",
FormFieldType.TEXT,
required=False,
key="HB_abschlussgrad",
tooltip=(
"bitte den Titel eingeben z.B. Doktor, Diplom oder "
"Betriebswirt (Fachschulabschluss)"
@@ -1413,16 +1482,19 @@ FORM_FIELDS_HIGHER_EDUCATION = [
"Abschlussgrad laut Dokument",
FormFieldType.TEXT,
required=False,
key="HB_abschlussgrad_dokument",
),
FormField(
"Hochschule / Ausbildungsbetrieb / Berufsschule",
FormFieldType.TEXT,
required=False,
key="HB_organisation",
),
FormField(
"Beruf / Fachrichtung",
FormFieldType.TEXT,
required=False,
key="HB_beruf",
tooltip=(
"bitte spezifizieren z.B. Allgemeinmedizin, Ingenieur Maschinenbau, "
"technischer Betriebswirt Datenverarbeitung"
@@ -1431,7 +1503,7 @@ FORM_FIELDS_HIGHER_EDUCATION = [
FormField(
"Land",
FormFieldType.EXTENDED_DROPDOWN,
key="country",
key="HB_land",
required=False,
placeholder="Suche...",
options=COUNTRY_LIST.for_dropdown,
@@ -1440,16 +1512,19 @@ FORM_FIELDS_HIGHER_EDUCATION = [
"Ort",
FormFieldType.TEXT,
required=False,
key="HB_ort",
),
FormField(
"Abschlussjahr",
FormFieldType.TEXT,
required=False,
key="HB_abschlussjahr",
),
FormField(
"Bemerkungsfeld",
FormFieldType.TEXT,
required=False,
key="HB_bemerkungsfeld",
tooltip="z.B. Promotionen oder den Studiengang angeben",
),
]
@@ -1459,17 +1534,20 @@ FORM_FIELDS_WORK_EXPERIENCE = [
"Branche",
FormFieldType.DROPDOWN,
required=False,
key="AE_branche",
options=[("DROPDOWN-LISTE AN ANDERER STELLE DEFINIERT", None)],
),
FormField(
"Berufsbezeichnung/Tätigkeit",
FormFieldType.TEXT,
required=False,
key="AE_bezeichnung",
),
FormField(
"Funktion",
FormFieldType.DROPDOWN,
required=False,
key="AE_funktion",
options=[
("Auszubildender", None),
("Fachkraft", None),
@@ -1487,11 +1565,12 @@ FORM_FIELDS_WORK_EXPERIENCE = [
"Unternehmen",
FormFieldType.TEXT,
required=False,
key="AE_unternehmen",
),
FormField(
"Land",
FormFieldType.EXTENDED_DROPDOWN,
key="country",
key="AE_land",
required=False,
placeholder="Suche...",
options=COUNTRY_LIST.for_dropdown,
@@ -1500,11 +1579,13 @@ FORM_FIELDS_WORK_EXPERIENCE = [
"Zeitspanne (von ... bis ...)",
FormFieldType.TEXT,
required=False,
key="AE_zeitspanne",
),
FormField(
"Beschäftsigungsart",
FormFieldType.DROPDOWN,
required=False,
key="AE_beschaeftigungsart",
options=[
("Vollzeit", None),
("Teilzeit", None),
@@ -1516,6 +1597,7 @@ FORM_FIELDS_WORK_EXPERIENCE = [
"Bemerkungsfeld",
FormFieldType.TEXT,
required=False,
key="AE_bemerkungsfeld",
),
]
@@ -1524,11 +1606,13 @@ FORM_FIELDS_LANGUAGES = [
"Sprache",
FormFieldType.TEXT,
required=False,
key="SP_sprache",
),
FormField(
"Niveau",
FormFieldType.DROPDOWN,
required=False,
key="SP_niveau",
options=[
("A1", None),
("A2", None),
@@ -1542,6 +1626,7 @@ FORM_FIELDS_LANGUAGES = [
"Nachweis",
FormFieldType.DROPDOWN,
required=False,
key="SP_nachweis",
options=[
("vorhanden", None),
("nicht vorhanden", None),
@@ -1551,93 +1636,74 @@ FORM_FIELDS_LANGUAGES = [
"Art des Nachweises (NUR WENN VORHANDEN)",
FormFieldType.TEXT,
required=False,
key="SP_art_nachweis",
),
FormField(
"Datum des Nachweises (NUR WENN VORHANDEN)",
FormFieldType.DATE,
required=False,
key="SP_datum_nachweis",
),
]
FORM_FIELDS = [
# FormField(
# "Status && Projektrelevanz",
# FormFieldType.GROUP,
# key="Projektrelevanz",
# children=[
# FormField(
# "Projektrelevanz",
# FormFieldType.DROPDOWN,
# key="Projektrelevanz_relevanz",
# required=True,
# options=[("ja", None), ("nein", None)],
# ),
# ],
# ),
# FormField(
# "Daten Kontaktperson",
# FormFieldType.GROUP,
# key="Kontaktperson",
# children=FORM_FIELDS_CONTACT_PERSON,
# ),
FormField(
"Status && Projektrelevanz",
FormFieldType.GROUP,
key="Projektrelevanz",
children=[
FormField(
"Projektrelevanz",
FormFieldType.DROPDOWN,
key="Projektrelevanz_relevanz",
required=True,
options=[("ja", None), ("nein", None)],
),
],
),
FormField(
"Daten Kontaktperson",
FormFieldType.GROUP,
key="Kontaktperson",
children=FORM_FIELDS_CONTACT_PERSON,
),
FormField(
"Stammdaten",
FormFieldType.GROUP,
key="Stammdaten",
children=FORM_FIELDS_MASTER_DATA,
),
FormField(
"Weitere Informationen",
FormFieldType.GROUP,
key="WeitereInfos",
children=FORM_FIELDS_ADDITIONAL_DATA,
),
FormField(
"Schulbildung",
FormFieldType.DYNAMIC_LIST,
children=FORM_FIELDS_SCHOOL,
key="Schulbildung",
),
# FormField(
# "Test Länderauswahl",
# FormFieldType.GROUP,
# key="countries",
# children=[
# FormField(
# "Länderauswahl",
# FormFieldType.EXTENDED_DROPDOWN,
# key="country",
# required=True,
# placeholder="Suche...",
# options=COUNTRY_LIST.for_dropdown,
# ),
# ],
# ),
# FormField(
# "Anzahl Kinder (dynamischer Dropdown)",
# FormFieldType.DYNAMIC_DROPDOWN,
# required=False,
# options=[(str(x), None) for x in range(11)],
# tooltip="* Wichtig zu erfragen aufgrund Lebensunterhaltssicherung",
# key="DynamicDropdown",
# children=[
# FormField(
# "Anzahl Kinder",
# FormFieldType.DROPDOWN,
# required=False,
# options=[(str(x), None) for x in range(11)],
# tooltip="* Wichtig zu erfragen aufgrund Lebensunterhaltssicherung",
# key="MainDropdown",
# children=[
# FormField("Alter Kind", FormFieldType.TEXT),
# ],
# ),
# ],
# ),
# FormFieldGroup("Daten Kontaktperson", FORM_FIELDS_CONTACT_PERSON),
# FormFieldGroup("Stammdaten (ERGÄNZUNG KINDERALTER DYNAMISCH)", FORM_FIELDS_MASTER_DATA),
# FormFieldGroup("weitere Informationen", FORM_FIELDS_ADDITIONAL_DATA),
# FormFieldGroup("Schule (MIT PLUS-ERWEITERUNG)", FORM_FIELDS_SCHOOL),
# FormFieldGroup("Studium/Ausbildung (MIT PLUS-ERWEITERUNG)", FORM_FIELDS_HIGHER_EDUCATION),
# FormFieldGroup("Arbeitserfahrung (MIT PLUS-ERWEITERUNG)", FORM_FIELDS_WORK_EXPERIENCE),
# FormFieldGroup("Sprachkenntnisse (MIT PLUS-ERWEITERUNG)", FORM_FIELDS_LANGUAGES),
# FormFieldGroup("Dynamische Liste", FORM_DYN_LIST),
# FormFieldGroup("Test-2", FORM_FIELD_DEF2),
FormField(
"Studium/Ausbildung",
FormFieldType.DYNAMIC_LIST,
children=FORM_FIELDS_HIGHER_EDUCATION,
key="HoehereBildung",
),
FormField(
"Arbeitserfahrung",
FormFieldType.DYNAMIC_LIST,
children=FORM_FIELDS_WORK_EXPERIENCE,
key="Arbeitserfahrung",
),
FormField(
"Sprachkenntnisse",
FormFieldType.DYNAMIC_LIST,
children=FORM_FIELDS_LANGUAGES,
key="Sprachkenntnisse",
),
]
@@ -1678,6 +1744,8 @@ class AutoForm(QWidget):
image: none;
}
""")
# --- special funtionality ---
self.no_scroll_filter = NoScrollFilter(self)
# --- LAYOUT ---
self.main_layout = QVBoxLayout(self)
@@ -1740,11 +1808,11 @@ class AutoForm(QWidget):
self.save_btn.setText(self.save_btn_txt_enabled)
def on_load_clicked(self) -> None:
# TODO change logic to database backend
print(">>>> LOAD CLICKED")
loaded_data = load_pydantic_model_dict()
# print("Loaded dictionary:")
# pprint(loaded)
# print(">>>> Widget registry:")
# pprint_registry(self.widget_registry)
@@ -1755,48 +1823,11 @@ class AutoForm(QWidget):
key_path = key.split(".")
value = _get_nested(loaded_data, key_path)
# print(f"Key: {key}")
# print(f"Value: {value}")
# Wenn kein Wert da ist (z.B. weil er optional ist), überspringen wir das Feld
if value is None:
continue
elif value is True:
value = "ja"
elif value is False:
value = "nein"
# 2. Das Widget entsprechend seinem Typ füllen
if isinstance(widget, QLineEdit):
widget.setText(str(value)) # str() zur Sicherheit, falls es ein int ist
elif isinstance(widget, QComboBox):
# MEGA WICHTIG: Wir suchen nicht den Text, sondern die unsichtbaren Daten!
# (z.B. suchen wir nach dem ISO-Code 'DE' oder der ID 1042)
index = widget.findData(value)
if index >= 0:
widget.setCurrentIndex(index)
elif isinstance(widget, (DynamicListWidget, DynamicDropdownWidget)):
print("\n-----------------\n\nCustom widget, skip...")
print(f"Key: {key}")
print("Widget type: ", type(widget).__name__)
print("current value or data format: ")
pprint(value)
if hasattr(widget, "set_form_data"):
widget.set_form_data(value) # type: ignore
continue
# elif hasattr(widget, "set_data"):
# # Wenn es eins unserer Custom-Widgets ist (Dropdown-Liste, Dynamische Liste)
# # übergeben wir die Liste einfach an das Widget selbst!
# widget.set_data(wert)
set_widget_value(widget, value)
def on_save_clicked(self) -> None:
self._disable_save()
errors = validate_form_data(self.widget_registry)
errors = self.validate_form_data()
if errors:
# errors: abort saving and show pop up window
@@ -1813,54 +1844,47 @@ class AutoForm(QWidget):
print("Erfolg! Alle Daten sind valide.")
print("Get form data call...")
form_data = self.get_form_data()
# post_proc_1 = form_data["Stammdaten"]["Stammdaten_anzahl_kinder"]
# Stammdaten_anzahl_kinder = post_proc_1[0]["Stammdaten_anzahl_kinder-[0]"][
# "'Stammdaten_anzahl_kinder'"
# ]
# Stammdaten_alter_kinder: list[str] = []
# if len(post_proc_1) > 1:
# for i in range(1, len(post_proc_1)):
# content = post_proc_1[i]
print("------------>>>>>>>>> Get form data")
pprint(form_data)
print("------------>>>>>>>>> Call Pydantic")
print("\n------------>>>>>>>>> Call Pydantic")
try:
validated_data = Grunderfassung_Unternehmen(**form_data)
# validated_data = Grunderfassung_Stammdaten(**form_data["Stammdaten"])
pprint(validated_data.model_dump())
except ValidationError as e:
# 4. Fehler abfangen und in der GUI anzeigen!
# catch errors and show them in GUI
fehler_texte = []
# Pydantic liefert eine detaillierte Fehlerliste
# Pydantic detailed error list
for error in e.errors():
print(error)
# error['loc'][0] enthält den Namen des Feldes (z.B. 'email')
# error['loc'][0] = name of field
fehlerhaftes_feld = str(error["loc"][0])
grund = error["msg"]
fehler_texte.append(f"- {fehlerhaftes_feld}: {grund}")
# Wir machen das betroffene Widget in PySide rot!
# formatting red
# if fehlerhaftes_feld in self.widgets:
# self.widgets[fehlerhaftes_feld].setStyleSheet(
# "border: 1px solid red; background: #fef2f2;"
# )
# Dem Nutzer gesammelt mitteilen, was schiefgelaufen ist
# tell user what went wrong
QMessageBox.warning(self, "Eingabefehler", "\n".join(fehler_texte))
else:
# !! keep this code must be called again
# !! this code is only called if the 'try' block was successful
self.reset_form()
save_pydantic_model_dict(validated_data)
finally:
# always re-enable save, even if error occurred
self._enable_save()
# ------------------------------------------------------------
def validate_form_data(self) -> list[str]:
return validate_form_data(self.widget_registry)
def reset_form(self) -> None:
reset_form(self.widget_registry)
@@ -1870,6 +1894,54 @@ class AutoForm(QWidget):
return raw_data
def set_widget_value(
widget: QWidget,
value: Any,
) -> None:
if value is None:
return
elif value is True:
value = "ja"
elif value is False:
value = "nein"
if isinstance(widget, QLineEdit):
widget.setText(str(value))
elif isinstance(widget, QPlainTextEdit):
widget.setPlainText(str(value))
elif isinstance(widget, QDateEdit):
assert isinstance(value, datetime.date)
set_date = QDate(value.year, value.month, value.day)
if not set_date.isValid():
raise ValueError(f"Could not parse date field value >{value}<")
widget.setDate(set_date)
elif isinstance(widget, QComboBox):
index = widget.findData(value)
if index >= 0:
widget.setCurrentIndex(index)
elif isinstance(widget, DynamicListWidget):
# print("\n-----------------\n\nCustom widget...")
# print(f"Key: {key}")
# print("Widget type: ", type(widget).__name__)
# print("current value or data format: ")
# pprint(value)
assert isinstance(value, list)
widget.set_form_data(value)
elif isinstance(widget, DynamicDropdownWidget):
# print("\n-----------------\n\nCustom widget, skip...")
# print(f"Key: {key}")
# print("Widget type: ", type(widget).__name__)
# print("current value or data format: ")
# pprint(value)
assert isinstance(value, dict)
widget.set_form_data(value)
@dc.dataclass(slots=True)
class SubForm:
entry_box: QWidget
@@ -1996,15 +2068,14 @@ class DynamicListWidget(QWidget):
# pprint_registry(self.widget_registry)
def reset_form(self) -> None:
reset_form(self.widget_registry)
while self.sub_forms:
self.remove_entry(self.sub_forms[0])
self.add_entry()
def validate_form_data(self) -> list[str]:
return validate_form_data(self.widget_registry)
def load_form_data(self) -> None:
# TODO add way to load data when initialised (probably with click)
...
def get_form_data(self):
raw_data = get_form_data(self.widget_registry)
@@ -2018,19 +2089,23 @@ class DynamicListWidget(QWidget):
while self.sub_forms:
self.remove_entry(self.sub_forms[0])
# empyt default row
# empty default row
if not data:
self.add_entry()
return
# TODO rework
for entry in data:
for sub_data in data:
self.add_entry()
current_sub_form = self.sub_forms[-1]
registry_entries = search_widgets_by_key(
self.widget_registry, f"-[{current_sub_form.index}]"
)
for reg_entry in registry_entries:
widget = reg_entry["widget"]
field_def = reg_entry["form_field"]
# get all relevant widgets and fill in the values
# current_sub_form = self.sub_forms[-1]
# fill in values
value = sub_data[field_def.key]
set_widget_value(widget, value)
class DynamicDropdownWidget(QWidget):
@@ -2163,10 +2238,6 @@ class DynamicDropdownWidget(QWidget):
def validate_form_data(self) -> list[str]:
return validate_form_data(self.widget_registry)
def load_form_data(self) -> None:
# TODO add way to load data when initialised (probably with click)
...
def get_form_data(self):
raw_data = get_form_data(self.widget_registry)
# each sub form has its own numbered key: We need to get rid of these
@@ -2202,32 +2273,21 @@ class DynamicDropdownWidget(QWidget):
while self.sub_forms:
self._remove_row()
# empty default line
# !! only dynamic list widget
# if not daten_liste:
# self._add_row()
# return
# fill in value of combobox field
entries = tuple(self.widget_registry.values())
assert len(entries) == 1
widget = entries[0]["widget"]
assert isinstance(widget, QComboBox)
value = data["anzahl"]
index = widget.findData(value)
if index >= 0:
widget.setCurrentIndex(index)
value = data[self.combobox_field.key]
set_widget_value(widget, value)
data_list: list[int | None] | None = data["alter"]
data_list: list[int | None] | None = data[self.assigned_form_field.key]
if not data_list:
return
# now there are as many new sub forms as the saved value for the dropdown
# assert this
assert len(data_list) == len(self.sub_forms)
print(">>>>>>> New Registry of dynamic dropdown:")
pprint_registry(self.widget_registry)
sub_form_index: int = 0
for key, entry in self.widget_registry.items():
if "-[0]" in key:
@@ -2235,13 +2295,28 @@ class DynamicDropdownWidget(QWidget):
continue
widget = entry["widget"]
value = data_list[sub_form_index]
if value is None:
value = ""
if isinstance(widget, QLineEdit):
widget.setText(str(value))
set_widget_value(widget, value)
sub_form_index += 1
class NoScrollFilter(QObject):
"""disables scrolling in fields which are not in focus"""
def eventFilter(
self,
obj: QObject,
event: QEvent,
) -> bool:
if event.type() == QEvent.Type.Wheel:
# ignored Qt gives event to parent (ScrollArea)
event.ignore()
# event was handled
return True
# propagate other events
return super().eventFilter(obj, event)
class ClickableCell(QFrame):
"""cell in the table on the startup screen"""