generated from dopt-python/py311
refactoring
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
def _get_leafs(data):
|
||||
if isinstance(data, dict):
|
||||
for value in data.values():
|
||||
yield from _get_leafs(value)
|
||||
elif isinstance(data, (list, tuple, set)):
|
||||
for item in data:
|
||||
yield from _get_leafs(item)
|
||||
else:
|
||||
yield data
|
||||
|
||||
|
||||
def _get_leaf_dicts(data):
|
||||
if isinstance(data, dict):
|
||||
has_inner_dicts = False
|
||||
|
||||
for value in data.values():
|
||||
for inner_dict in _get_leaf_dicts(value):
|
||||
has_inner_dicts = True
|
||||
yield inner_dict
|
||||
|
||||
if not has_inner_dicts:
|
||||
yield data
|
||||
|
||||
elif isinstance(data, (list, tuple, set)):
|
||||
for item in data:
|
||||
yield from _get_leaf_dicts(item)
|
||||
@@ -147,7 +147,7 @@ def initrec_company_get_initial_recording(
|
||||
row = ret.fetchone()
|
||||
assert row, "row was not obtained"
|
||||
|
||||
return row._asdict()
|
||||
return row._asdict() # type: ignore
|
||||
|
||||
|
||||
def initrec_company_delete_initial_recording(
|
||||
@@ -196,7 +196,7 @@ def initrec_person_update_initial_recording(
|
||||
def initrec_person_get_initial_recording(
|
||||
id_: RecId,
|
||||
) -> dict[str, Any]:
|
||||
logger.debug("[Call backend] get_initial_recording")
|
||||
logger.debug("[Call backend] get_initial_recording person")
|
||||
stmt = db.grunderfassung_personen.select().where(
|
||||
db.grunderfassung_personen.c.pers_id == id_
|
||||
)
|
||||
@@ -209,7 +209,7 @@ def initrec_person_get_initial_recording(
|
||||
row = ret.fetchone()
|
||||
assert row, "row was not obtained"
|
||||
|
||||
return row._asdict()
|
||||
return row._asdict() # type: ignore
|
||||
|
||||
|
||||
def initrec_person_delete_initial_recording(
|
||||
|
||||
@@ -13,10 +13,47 @@ from pydantic import (
|
||||
field_validator,
|
||||
model_validator,
|
||||
)
|
||||
from pydantic_core import ErrorDetails
|
||||
|
||||
ValidAge = Annotated[int, Field(ge=0, le=99)]
|
||||
|
||||
|
||||
# // validation translation
|
||||
GERMAN_ERROR_MESSAGES: Final[dict[str, str]] = {
|
||||
"missing": "Dieses Feld ist ein Pflichtfeld.",
|
||||
"int_parsing": "Bitte eine gültige Ganzzahl eingeben.",
|
||||
"float_parsing": "Bitte eine gültige Dezimalzahl eingeben.",
|
||||
"string_too_short": "Der Text ist zu kurz. Er muss mindestens {min_length} Zeichen lang sein.",
|
||||
"string_too_long": "Der Text ist zu lang. Er darf maximal {max_length} Zeichen lang sein.",
|
||||
"greater_than": "Der Wert muss größer als {gt} sein.",
|
||||
}
|
||||
|
||||
|
||||
def translate_pydantic_errors(
|
||||
errors: list[ErrorDetails],
|
||||
) -> list[ErrorDetails]:
|
||||
translated_errors: list[ErrorDetails] = []
|
||||
|
||||
for error in errors:
|
||||
err_type = error.get("type", None)
|
||||
|
||||
if err_type is None or err_type not in GERMAN_ERROR_MESSAGES:
|
||||
error["msg"] = "[fehleden Übersetzung, nur Englisch]: " + error["msg"]
|
||||
translated_errors.append(error)
|
||||
continue
|
||||
|
||||
msg_template = GERMAN_ERROR_MESSAGES[err_type]
|
||||
ctx = error.get("ctx", {})
|
||||
try:
|
||||
error["msg"] = msg_template.format(**ctx)
|
||||
except KeyError:
|
||||
error["msg"] = msg_template
|
||||
|
||||
translated_errors.append(error)
|
||||
|
||||
return translated_errors
|
||||
|
||||
|
||||
def _parse_json(value: Any) -> str:
|
||||
if isinstance(value, datetime.date):
|
||||
return value.isoformat()
|
||||
|
||||
@@ -911,6 +911,7 @@ INITREC_COMP = [
|
||||
required=False,
|
||||
key="Metadaten_nutzer",
|
||||
readonly=True,
|
||||
ignore_get_data=True,
|
||||
),
|
||||
FormField(
|
||||
"Fallnummer",
|
||||
@@ -956,6 +957,7 @@ INITREC_PERSON = [
|
||||
required=False,
|
||||
key="Metadaten_nutzer",
|
||||
readonly=True,
|
||||
ignore_get_data=True,
|
||||
),
|
||||
FormField(
|
||||
"Wiedereintrittsdatum",
|
||||
|
||||
+224
-154
@@ -4,13 +4,11 @@ import copy
|
||||
import dataclasses as dc
|
||||
import datetime
|
||||
import enum
|
||||
import pickle
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
from collections import defaultdict
|
||||
from collections.abc import Container, Iterable, Sequence
|
||||
from pathlib import Path
|
||||
from pprint import pformat
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
@@ -26,7 +24,6 @@ from typing import (
|
||||
)
|
||||
from typing_extensions import override
|
||||
|
||||
from dopt_basics import datetime as dopt_dt
|
||||
from pydantic import (
|
||||
ValidationError,
|
||||
)
|
||||
@@ -36,7 +33,6 @@ from PySide6.QtCore import (
|
||||
QEvent,
|
||||
QObject,
|
||||
Qt,
|
||||
QTime,
|
||||
QTimer,
|
||||
QtMsgType,
|
||||
Signal,
|
||||
@@ -84,6 +80,7 @@ from wce_crm.data_models import (
|
||||
FlatBaseModel,
|
||||
Grunderfassung_Personen,
|
||||
Grunderfassung_Unternehmen,
|
||||
translate_pydantic_errors,
|
||||
)
|
||||
from wce_crm.form_defs import (
|
||||
INITREC_COMP,
|
||||
@@ -166,36 +163,6 @@ def unmerge_dict_to_list(
|
||||
return [dict(zip(keys, row)) for row in zip(*value_lists)]
|
||||
|
||||
|
||||
# TODO check removal or move to basics package
|
||||
def _get_leafs(data):
|
||||
if isinstance(data, dict):
|
||||
for value in data.values():
|
||||
yield from _get_leafs(value)
|
||||
elif isinstance(data, (list, tuple, set)):
|
||||
for item in data:
|
||||
yield from _get_leafs(item)
|
||||
else:
|
||||
yield data
|
||||
|
||||
|
||||
# TODO check removal or move to basics package
|
||||
def _get_leaf_dicts(data):
|
||||
if isinstance(data, dict):
|
||||
has_inner_dicts = False
|
||||
|
||||
for value in data.values():
|
||||
for inner_dict in _get_leaf_dicts(value):
|
||||
has_inner_dicts = True
|
||||
yield inner_dict
|
||||
|
||||
if not has_inner_dicts:
|
||||
yield data
|
||||
|
||||
elif isinstance(data, (list, tuple, set)):
|
||||
for item in data:
|
||||
yield from _get_leaf_dicts(item)
|
||||
|
||||
|
||||
def pprint_registry(widget_registry: WidgetRegistry) -> None:
|
||||
print("\n\n>>> Widget registry:")
|
||||
for key, entry in widget_registry.items():
|
||||
@@ -665,8 +632,6 @@ def _build_ui_recursively(
|
||||
else:
|
||||
full_key = field.key
|
||||
|
||||
widget: QWidget
|
||||
|
||||
match field.type:
|
||||
case FormFieldType.GROUP:
|
||||
group_box = QGroupBox(field.label)
|
||||
@@ -686,11 +651,6 @@ def _build_ui_recursively(
|
||||
widget_registry=widget_registry,
|
||||
prefix=prefix,
|
||||
)
|
||||
# TODO remove
|
||||
# widget_registry[full_key] = {
|
||||
# "widget": widget,
|
||||
# "form_field": field,
|
||||
# }
|
||||
keys.append(full_key)
|
||||
|
||||
return keys
|
||||
@@ -722,7 +682,7 @@ def reset_form(
|
||||
form_field = registry_entry["form_field"]
|
||||
|
||||
# TODO check if this behaviour is correct in other contexts, deactivated because of
|
||||
# TODO company search widget
|
||||
# company search widget
|
||||
# if form_field.readonly:
|
||||
# continue
|
||||
|
||||
@@ -1410,6 +1370,7 @@ class AutoForm(QWidget):
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self.STATE = state
|
||||
self.SESSION_USER_KEY: Final[str] = "Metadaten_nutzer"
|
||||
self.cfg = state.cfg
|
||||
self.setStyleSheet("""
|
||||
QGroupBox {
|
||||
@@ -1515,40 +1476,21 @@ class AutoForm(QWidget):
|
||||
|
||||
self.debug_form_data: dict[str, Any] = {}
|
||||
if self.add_buttons:
|
||||
self.layout_btn = QHBoxLayout()
|
||||
self.main_layout.addLayout(self.layout_btn)
|
||||
# save
|
||||
self.save_btn_txt_enabled = "Speichern (Strg + S)"
|
||||
self.save_btn_txt_disabled = "Wird gespeichert..."
|
||||
self.save_btn = QPushButton(self.save_btn_txt_enabled)
|
||||
self.save_btn.setShortcut("Ctrl+S")
|
||||
self.save_btn.setFixedHeight(50)
|
||||
self.save_btn.setSizePolicy(
|
||||
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed
|
||||
)
|
||||
self.edit_buttons = EditButtons(add_reset_btn=True)
|
||||
reset_btn = self.edit_buttons.reset_btn
|
||||
assert reset_btn
|
||||
self.save_btn = self.edit_buttons.save_btn
|
||||
self.reset_btn = reset_btn
|
||||
self.delete_btn = self.edit_buttons.delete_btn
|
||||
|
||||
self.save_btn.clicked.connect(self.save_data)
|
||||
self.layout_btn.addWidget(self.save_btn)
|
||||
# reset
|
||||
self.reset_btn = QPushButton("Zurücksetzen (Strg + Z)")
|
||||
self.reset_btn.setShortcut("Ctrl+Z")
|
||||
self.reset_btn.setFixedHeight(50)
|
||||
self.reset_btn.setSizePolicy(
|
||||
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed
|
||||
)
|
||||
self.reset_btn.clicked.connect(self.reset_form)
|
||||
self.layout_btn.addWidget(self.reset_btn)
|
||||
# delete
|
||||
self.delete_btn = QPushButton("Eintrag löschen (Strg + L)")
|
||||
self.delete_btn.setShortcut("Ctrl+L")
|
||||
self.delete_btn.setFixedHeight(50)
|
||||
self.delete_btn.setSizePolicy(
|
||||
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed
|
||||
)
|
||||
self.delete_btn.clicked.connect(self._delete_data)
|
||||
self.layout_btn.addWidget(self.delete_btn)
|
||||
|
||||
self.main_layout.addWidget(self.edit_buttons)
|
||||
|
||||
logger_auto_form.debug(
|
||||
"Initialised Auto Form Widget. Registry:%s",
|
||||
"[Auto-Form] Initialised Auto Form Widget. Registry:%s",
|
||||
pformat_registry(self.widget_registry),
|
||||
)
|
||||
|
||||
@@ -1561,11 +1503,11 @@ class AutoForm(QWidget):
|
||||
except ValueError:
|
||||
index = None
|
||||
self.STATE.rec_id = index
|
||||
logger_gui.debug("Set index to %d, new state: %s", index, self.STATE)
|
||||
logger_gui.debug("[Auto-Form] Set index to %s, new state: %s", index, self.STATE)
|
||||
|
||||
def _disable_save(self) -> None:
|
||||
self.save_btn.setEnabled(False)
|
||||
self.save_btn.setText(self.save_btn_txt_disabled)
|
||||
self.save_btn.setText(self.edit_buttons.save_btn_txt_disabled)
|
||||
|
||||
def _enable_save(
|
||||
self,
|
||||
@@ -1573,7 +1515,7 @@ class AutoForm(QWidget):
|
||||
) -> None:
|
||||
QTimer.singleShot(timeout, lambda: self.save_btn.setEnabled(True))
|
||||
QTimer.singleShot(timeout + 1, lambda: self.save_btn.setShortcut("Ctrl+S"))
|
||||
self.save_btn.setText(self.save_btn_txt_enabled)
|
||||
self.save_btn.setText(self.edit_buttons.save_btn_txt_enabled)
|
||||
|
||||
def _activate_delete(self) -> None:
|
||||
if self.STATE.rec_id is not None:
|
||||
@@ -1589,35 +1531,32 @@ class AutoForm(QWidget):
|
||||
|
||||
def _load_data(
|
||||
self,
|
||||
lookup_id: int | None = None,
|
||||
lookup_id: int | None,
|
||||
) -> None:
|
||||
if DEBUG_NO_DATABASE:
|
||||
return
|
||||
|
||||
logger_auto_form.info(">>>> LOAD CLICKED")
|
||||
if lookup_id is None:
|
||||
# only debugging
|
||||
lookup_id = self.STATE.rec_id
|
||||
logger_auto_form.info("[Auto-Form] Load data method...")
|
||||
self.reset_form()
|
||||
|
||||
logger_auto_form.debug("Lookup ID: %d", lookup_id)
|
||||
logger_auto_form.debug("[Auto-Form] Lookup ID: %s", lookup_id)
|
||||
|
||||
if lookup_id is not None and lookup_id > 0:
|
||||
if lookup_id is not None:
|
||||
logger_auto_form.debug("Load from DB:")
|
||||
loaded_data = self.cfg.data_get(lookup_id)
|
||||
else:
|
||||
logger_auto_form.error("Loading: Lookup ID 0 or NULL. Do nothing!")
|
||||
logger_auto_form.debug("[Auto-Form] Loading: Lookup ID NULL. Do nothing!")
|
||||
return
|
||||
|
||||
logger_auto_form.debug(
|
||||
"Loaded data dict:\n%s Passing to Pydantic...", pformat(loaded_data)
|
||||
"[Auto-Form] Loaded data dict:\n%s Passing to Pydantic...", pformat(loaded_data)
|
||||
)
|
||||
model = self.cfg.model(**loaded_data)
|
||||
logger_auto_form.debug("Loaded to Pydantic.")
|
||||
logger_auto_form.debug("Convert to GUI structure...")
|
||||
logger_auto_form.debug("[Auto-Form] Loaded to Pydantic.")
|
||||
logger_auto_form.debug("[Auto-Form] Convert to GUI structure...")
|
||||
form_data = model.to_gui()
|
||||
logger_auto_form.debug("Set form data...")
|
||||
logger_auto_form.debug("Form data:\n%s", pformat(form_data))
|
||||
logger_auto_form.debug("[Auto-Form] Set form data...")
|
||||
logger_auto_form.debug("[Auto-Form] Form data:\n%s", pformat(form_data))
|
||||
self._set_form_data(form_data)
|
||||
self.STATE.rec_id = lookup_id
|
||||
self._activate_delete()
|
||||
@@ -1625,12 +1564,13 @@ class AutoForm(QWidget):
|
||||
def reset_form(self) -> None:
|
||||
reset_form(self.widget_registry)
|
||||
self.STATE.rec_id = None
|
||||
self.STATE.form_data = None
|
||||
self._activate_delete()
|
||||
|
||||
def _get_form_data(self) -> dict[str, Any]:
|
||||
form_data = get_form_data(self.widget_registry)
|
||||
logger_auto_form.debug("\n\n>>>>>>> [AutoForm] Call get form data:")
|
||||
logger_auto_form.debug("Form Data:\n%s", pformat(form_data))
|
||||
logger_auto_form.debug("[Auto-Form] Call get form data:")
|
||||
logger_auto_form.debug("[Auto-Form] Form Data:\n%s", pformat(form_data))
|
||||
|
||||
if DEBUG_GET_SET:
|
||||
self.debug_form_data = form_data
|
||||
@@ -1641,7 +1581,7 @@ class AutoForm(QWidget):
|
||||
self,
|
||||
data: dict[str, Any],
|
||||
) -> None:
|
||||
logger_auto_form.debug("\n\n>>>>>>> [AutoForm] Call set form data:")
|
||||
logger_auto_form.debug("[Auto-Form] Call set form data...")
|
||||
if DEBUG_GET_SET:
|
||||
data = self.debug_form_data
|
||||
|
||||
@@ -1651,7 +1591,10 @@ class AutoForm(QWidget):
|
||||
self._load_data(self.STATE.rec_id)
|
||||
|
||||
def _sync_GUI_to_state(self) -> None:
|
||||
self.STATE.form_data = self._get_form_data()
|
||||
form_data = self._get_form_data()
|
||||
# TODO change usage of user ID (needs changes in model and backend)
|
||||
form_data[self.SESSION_USER_KEY] = self.STATE.session.user_name
|
||||
self.STATE.form_data = form_data
|
||||
|
||||
def validate(self) -> list[str]:
|
||||
return validate_form_data(self.widget_registry)
|
||||
@@ -1661,8 +1604,6 @@ class AutoForm(QWidget):
|
||||
new_state: AutoForm_State,
|
||||
) -> None:
|
||||
set_page_state(self.STATE, new_state)
|
||||
# self.STATE.rec_id = new_state.rec_id
|
||||
# self.STATE.form_data = new_state.form_data
|
||||
self._sync_state_to_GUI()
|
||||
|
||||
def get_state(self) -> AutoForm_State:
|
||||
@@ -1675,50 +1616,29 @@ class AutoForm(QWidget):
|
||||
errors = self.validate()
|
||||
|
||||
if errors:
|
||||
# errors: abort saving and show pop up window
|
||||
error_text = (
|
||||
"Bitte füllen Sie die folgenden Pflichtfelder aus:\n\n▸ "
|
||||
+ "\n▸ ".join(errors)
|
||||
logger_auto_form.error(
|
||||
"[Auto-Form] Error during GUI validation phase:\n%s", pformat(errors)
|
||||
)
|
||||
QMessageBox.warning(self, "Fehlende Angaben", error_text)
|
||||
GUI_validation_error_handling(errors)
|
||||
self._enable_save()
|
||||
return
|
||||
|
||||
# no errors: data can be saved
|
||||
logger_auto_form.info("Erfolg! Alle Daten sind valide.")
|
||||
logger_auto_form.info("Get form data call...")
|
||||
form_data = self._get_form_data()
|
||||
logger_auto_form.info("[Auto-Form] Success! All data is valid")
|
||||
logger_auto_form.info("[Auto-Form] Get form data call...")
|
||||
state = self.get_state()
|
||||
form_data = state.form_data
|
||||
assert form_data, "form data not set"
|
||||
|
||||
logger_auto_form.debug(
|
||||
"\n\n------------>>>>>>>>> Get form data\n%s", pformat(form_data)
|
||||
)
|
||||
logger_auto_form.debug("[Auto-Form] Get form data\n%s", pformat(form_data))
|
||||
|
||||
try:
|
||||
logger_auto_form.debug("------------>>>>>>>>> Call Pydantic")
|
||||
logger_auto_form.debug("[Auto-Form] Call Pydantic...")
|
||||
validated_data = self.cfg.model(**form_data)
|
||||
# # TODO add user?
|
||||
except ValidationError as e:
|
||||
# catch errors and show them in GUI
|
||||
error_texts = []
|
||||
|
||||
# Pydantic detailed error list
|
||||
for error in e.errors():
|
||||
logger_gui.error("Error during validation phase:\n%s", pformat(error))
|
||||
|
||||
error_field = str(error["loc"][0])
|
||||
reason = error["msg"]
|
||||
|
||||
error_texts.append(f"- {error_field}: {reason}")
|
||||
|
||||
# TODO: Is this needed and feasible?
|
||||
# formatting red
|
||||
# if fehlerhaftes_feld in self.widgets:
|
||||
# self.widgets[fehlerhaftes_feld].setStyleSheet(
|
||||
# "border: 1px solid red; background: #fef2f2;"
|
||||
# )
|
||||
|
||||
# tell user what went wrong
|
||||
QMessageBox.warning(self, "Eingabefehler", "\n".join(error_texts))
|
||||
logger_auto_form.error(
|
||||
"[Auto-Form] Error during Pydantic validation phase:\n%s", pformat(e.errors())
|
||||
)
|
||||
pydantic_validation_error_handling(e)
|
||||
else:
|
||||
if DEBUG_NO_DATABASE:
|
||||
return
|
||||
@@ -1726,20 +1646,20 @@ class AutoForm(QWidget):
|
||||
# save data to database
|
||||
db_data = validated_data.to_db(exclude=self.cfg.ignored_keys)
|
||||
logger_auto_form.debug(
|
||||
("Form data with 'exlude' (must be saved in the database):\n%s"),
|
||||
"[Auto-Form] Form data with 'exlude' (must be saved in the database):\n%s",
|
||||
pformat(db_data),
|
||||
)
|
||||
|
||||
if self.STATE.rec_id is None:
|
||||
logger_auto_form.debug("Insert triggered")
|
||||
logger_auto_form.debug("[Auto-Form] Insert triggered...")
|
||||
init_rec_id = self.cfg.data_insert(db_data)
|
||||
assert isinstance(init_rec_id, int)
|
||||
self.STATE.rec_id = init_rec_id
|
||||
else:
|
||||
logger_auto_form.debug("Update triggered")
|
||||
logger_auto_form.debug("[Auto-Form] Update triggered...")
|
||||
self.cfg.data_update(self.STATE.rec_id, db_data)
|
||||
|
||||
logger_auto_form.info("Data saved successfully")
|
||||
logger_auto_form.info("[Auto-Form] Data saved successfully")
|
||||
self.update_triggered.emit()
|
||||
self._activate_delete()
|
||||
finally:
|
||||
@@ -3688,19 +3608,6 @@ class Page_Consulting(QWidget):
|
||||
# state management
|
||||
self.STATE = Page_Consulting_State(session=session)
|
||||
|
||||
# self.current_id: InitRecId = -1
|
||||
# self.COMPANY_FETAURES_MASTER_DATA: dict[str, str] = {
|
||||
# "ma_unternehmensname": "Name:",
|
||||
# "ma_branche": "Branche:",
|
||||
# "ma_strasse": "Straße:",
|
||||
# "ma_hausnummer": "Hausnummer:",
|
||||
# "ma_plz": "PLZ:",
|
||||
# "ma_ort": "Ort:",
|
||||
# "ma_website": "Webseite:",
|
||||
# "ma_mail": "E-Mail:",
|
||||
# "ma_telefonnummer": "Telefon:",
|
||||
# }
|
||||
|
||||
# Hauptlayout der Seite
|
||||
outer_layout = QHBoxLayout(self)
|
||||
vert_layout = QVBoxLayout()
|
||||
@@ -3907,8 +3814,6 @@ class Page_Consulting(QWidget):
|
||||
self,
|
||||
new_state: Page_Consulting_State,
|
||||
) -> None:
|
||||
# TODO add correct loading behaviour
|
||||
# TODO add validation (correct type with necessary information)
|
||||
logger_page_consulting.debug("[Consulting] Loading with request:\n%s", new_state)
|
||||
set_page_state(self.STATE, new_state)
|
||||
# child modules
|
||||
@@ -4696,19 +4601,184 @@ def global_exception_handler(exc_type, exc_value, exc_traceback):
|
||||
# message to user
|
||||
# check if QApplication exists otherwise crashing of crash handler possible)
|
||||
if QApplication.instance():
|
||||
msg_box = QMessageBox()
|
||||
msg_box.setIcon(QMessageBox.Icon.Critical)
|
||||
msg_box.setWindowTitle("Kritischer Fehler")
|
||||
msg_box.setText(
|
||||
"Ein unerwarteter Fehler ist aufgetreten. Die Details wurden protokolliert."
|
||||
msg_box = get_error_message_box(
|
||||
QMessageBox.Icon.Critical,
|
||||
"Kritischer Fehler",
|
||||
"Ein unerwarteter Fehler ist aufgetreten. Die Details wurden protokolliert.",
|
||||
error_msg,
|
||||
)
|
||||
# details for user or screenshots
|
||||
msg_box.setDetailedText(error_msg)
|
||||
# msg_box.setIcon(QMessageBox.Icon.Critical)
|
||||
# msg_box.setWindowTitle("Kritischer Fehler")
|
||||
# msg_box.setText(
|
||||
# "Ein unerwarteter Fehler ist aufgetreten. Die Details wurden protokolliert."
|
||||
# )
|
||||
# # details for user or screenshots
|
||||
# msg_box.setDetailedText(error_msg)
|
||||
msg_box.exec()
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def get_error_message_box(
|
||||
msg_type: QMessageBox.Icon,
|
||||
title: str,
|
||||
message: str,
|
||||
detailed_text: str | None = None,
|
||||
) -> QMessageBox:
|
||||
msg_box = QMessageBox()
|
||||
msg_box.setIcon(msg_type)
|
||||
msg_box.setWindowTitle(title)
|
||||
msg_box.setText(message)
|
||||
if detailed_text is not None:
|
||||
msg_box.setDetailedText(detailed_text)
|
||||
|
||||
return msg_box
|
||||
|
||||
|
||||
def pydantic_validation_error_handling(
|
||||
val_error: ValidationError,
|
||||
) -> None:
|
||||
error_texts: list[str] = []
|
||||
translated_errors = translate_pydantic_errors(val_error.errors())
|
||||
|
||||
for error in translated_errors:
|
||||
error_field = str(error["loc"][0])
|
||||
reason = error["msg"]
|
||||
path = " → ".join(error["loc"][:-1]) # type: ignore
|
||||
|
||||
error_texts.append(f"- {error_field}: {reason}, (Pfad: {path})")
|
||||
|
||||
msg_box = get_error_message_box(
|
||||
QMessageBox.Icon.Warning,
|
||||
"Fehler bei der Validierung der Eingabedaten",
|
||||
(
|
||||
"Bei der Validierung der Eingaben ist ein Fehler aufgetreten. Details "
|
||||
"sind unten angefügt."
|
||||
),
|
||||
"\n".join(error_texts),
|
||||
)
|
||||
msg_box.exec()
|
||||
|
||||
|
||||
def GUI_validation_error_handling(
|
||||
errors: list[str],
|
||||
) -> None:
|
||||
error_text = "Bitte füllen Sie die folgenden Pflichtfelder aus:\n\n▸ " + "\n▸ ".join(
|
||||
errors
|
||||
)
|
||||
msg_box = get_error_message_box(
|
||||
QMessageBox.Icon.Warning,
|
||||
"Fehlende oder fehlerhafte Angaben",
|
||||
error_text,
|
||||
)
|
||||
msg_box.exec()
|
||||
|
||||
|
||||
# @dc.dataclass(slots=True)
|
||||
# class EditButton:
|
||||
# btn: QWidget
|
||||
# txt_enabled: str
|
||||
# txt_disabled: str
|
||||
|
||||
|
||||
# @dc.dataclass(slots=True, kw_only=True)
|
||||
# class EditButtonLayout:
|
||||
# layout: QLayout
|
||||
# save: EditButton
|
||||
# delete: EditButton
|
||||
# reset: EditButton | None
|
||||
|
||||
|
||||
class EditButtons(QWidget):
|
||||
def __init__(
|
||||
self,
|
||||
add_reset_btn: bool,
|
||||
) -> None:
|
||||
super().__init__()
|
||||
|
||||
layout_btn = QHBoxLayout(self)
|
||||
layout_btn.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
# main_layout.addLayout(layout_btn) # TODO add in component
|
||||
# save
|
||||
self.save_btn_txt_enabled = "Speichern (Strg + S)"
|
||||
self.save_btn_txt_disabled = "Wird gespeichert..."
|
||||
self.save_btn = QPushButton(self.save_btn_txt_enabled)
|
||||
self.save_btn.setShortcut("Ctrl+S")
|
||||
self.save_btn.setFixedHeight(50)
|
||||
self.save_btn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
|
||||
# save_btn.clicked.connect(save_data) # TODO add in component
|
||||
layout_btn.addWidget(self.save_btn)
|
||||
|
||||
# reset
|
||||
self.reset_button: QPushButton | None = None
|
||||
if add_reset_btn:
|
||||
self.reset_btn = QPushButton("Zurücksetzen (Strg + Z)")
|
||||
self.reset_btn.setShortcut("Ctrl+Z")
|
||||
self.reset_btn.setFixedHeight(50)
|
||||
self.reset_btn.setSizePolicy(
|
||||
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed
|
||||
)
|
||||
# reset_btn.clicked.connect(reset_form) # TODO add in component
|
||||
layout_btn.addWidget(self.reset_btn)
|
||||
|
||||
# delete
|
||||
self.delete_btn = QPushButton("Eintrag löschen (Strg + L)")
|
||||
self.delete_btn.setShortcut("Ctrl+L")
|
||||
self.delete_btn.setFixedHeight(50)
|
||||
self.delete_btn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
|
||||
# delete_btn.clicked.connect(self._delete_data) # TODO add in component
|
||||
layout_btn.addWidget(self.delete_btn)
|
||||
|
||||
|
||||
# def get_edit_buttons(
|
||||
# add_reset_btn: bool,
|
||||
# ) -> EditButtonLayout:
|
||||
# layout_btn = QHBoxLayout()
|
||||
# # main_layout.addLayout(layout_btn) # TODO add in component
|
||||
# # save
|
||||
# save_btn_txt_enabled = "Speichern (Strg + S)"
|
||||
# save_btn_txt_disabled = "Wird gespeichert..."
|
||||
# save_btn = QPushButton(save_btn_txt_enabled)
|
||||
# save_btn.setShortcut("Ctrl+S")
|
||||
# save_btn.setFixedHeight(50)
|
||||
# save_btn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
|
||||
# # save_btn.clicked.connect(save_data) # TODO add in component
|
||||
# edit_button_save = EditButton(save_btn, "Speichern (Strg + S)", "Wird gespeichert...")
|
||||
# layout_btn.addWidget(save_btn)
|
||||
|
||||
# # reset
|
||||
# edit_button_reset: EditButton | None = None
|
||||
# if add_reset_btn:
|
||||
# reset_btn = QPushButton("Zurücksetzen (Strg + Z)")
|
||||
# reset_btn.setShortcut("Ctrl+Z")
|
||||
# reset_btn.setFixedHeight(50)
|
||||
# reset_btn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
|
||||
# # reset_btn.clicked.connect(reset_form) # TODO add in component
|
||||
# edit_button_reset = EditButton(
|
||||
# save_btn, "Zurücksetzen (Strg + Z)", "Zurücksetzen (Strg + Z)"
|
||||
# )
|
||||
# layout_btn.addWidget(reset_btn)
|
||||
|
||||
# # delete
|
||||
# delete_btn = QPushButton("Eintrag löschen (Strg + L)")
|
||||
# delete_btn.setShortcut("Ctrl+L")
|
||||
# delete_btn.setFixedHeight(50)
|
||||
# delete_btn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
|
||||
# edit_button_delete = EditButton(
|
||||
# save_btn, "Eintrag löschen (Strg + L)", "Eintrag löschen (Strg + L)"
|
||||
# )
|
||||
# # delete_btn.clicked.connect(self._delete_data) # TODO add in component
|
||||
# layout_btn.addWidget(delete_btn)
|
||||
|
||||
# return EditButtonLayout(
|
||||
# layout=layout_btn,
|
||||
# save=edit_button_save,
|
||||
# delete=edit_button_delete,
|
||||
# reset=edit_button_reset,
|
||||
# )
|
||||
|
||||
|
||||
def qt_message_handler(mode, context, message):
|
||||
"""forwards internal Qt C++ warnings to Python loggers"""
|
||||
if mode == QtMsgType.QtInfoMsg:
|
||||
|
||||
Reference in New Issue
Block a user