generated from dopt-python/py311
Dev #7
@@ -244,13 +244,16 @@ def page_consulting_to_db(
|
||||
with db.ENGINE.begin() as conn:
|
||||
if consultation_data.vorgang_id is None:
|
||||
# insert new "Vorgang"
|
||||
insert_data = consultation_data.model_dump(exclude={"vorgang_id", "beratungen"})
|
||||
insert_data_process = consultation_data.model_dump(
|
||||
exclude={"vorgang_id", "beratungen"}
|
||||
)
|
||||
logger.debug(
|
||||
"[Consulting Page] Call insert 'Vorgang' with data:\n%s", pformat(insert_data)
|
||||
"[Consulting Page] Call insert 'Vorgang' with data:\n%s",
|
||||
pformat(insert_data_process),
|
||||
)
|
||||
|
||||
stmt = db.beratung_vorgang.insert()
|
||||
ret = conn.execute(stmt, insert_data)
|
||||
ret = conn.execute(stmt, insert_data_process)
|
||||
if ret.rowcount == 0:
|
||||
raise IOError("Entry was not inserted correctly")
|
||||
prim_keys = ret.inserted_primary_key
|
||||
@@ -261,9 +264,14 @@ def page_consulting_to_db(
|
||||
|
||||
else:
|
||||
logger.debug(
|
||||
"[Consulting Page] VorgangID already set. ID: %d",
|
||||
"[Consulting Page] VorgangID already set. ID: %d. Update...",
|
||||
consultation_data.vorgang_id,
|
||||
)
|
||||
update_data_process = consultation_data.model_dump(exclude={"beratungen"})
|
||||
stmt = db.beratung_vorgang.update().where(
|
||||
db.beratung_vorgang.c.vorgang_id == consultation_data.vorgang_id
|
||||
)
|
||||
conn.execute(stmt, update_data_process)
|
||||
|
||||
rows_for_db_insert: list[dict[str, Any]] = []
|
||||
rows_for_db_update: list[dict[str, Any]] = []
|
||||
@@ -337,12 +345,24 @@ def page_consulting_from_db(
|
||||
beratungs_typ=consultation_data_db["beratungs_typ"],
|
||||
erstellt=consultation_data_db["erstellt"],
|
||||
aktualisiert=consultation_data_db["aktualisiert"],
|
||||
geloescht=consultation_data_db["geloescht"],
|
||||
beratungen=[],
|
||||
)
|
||||
|
||||
# get all consultation sessions of this process
|
||||
if consultation_data.geloescht is not None:
|
||||
logger.info(
|
||||
(
|
||||
"[Consulting Page] Obtained entry for ID=%d. This entry was marked "
|
||||
"as deleted."
|
||||
),
|
||||
cons_id,
|
||||
)
|
||||
|
||||
# get all consultation sessions of this process, only the ones
|
||||
# which are not marked as deleted
|
||||
stmt = db.beratung_einzelberatung.select().where(
|
||||
db.beratung_einzelberatung.c.vorgang_id == cons_id
|
||||
db.beratung_einzelberatung.c.vorgang_id == cons_id,
|
||||
db.beratung_einzelberatung.c.geloescht.is_(None),
|
||||
)
|
||||
ret = conn.execute(stmt)
|
||||
# empty results possible
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
import enum
|
||||
import json
|
||||
from typing import Annotated, Any, Final, Literal
|
||||
|
||||
@@ -38,7 +39,7 @@ def translate_pydantic_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"]
|
||||
error["msg"] = "[fehlende Übersetzung, nur Englisch]: " + error["msg"]
|
||||
translated_errors.append(error)
|
||||
continue
|
||||
|
||||
@@ -346,6 +347,11 @@ class Grunderfassung_Sprachen(BaseModel):
|
||||
|
||||
|
||||
# ** Consulting
|
||||
class ConsultingType(enum.StrEnum):
|
||||
PAUSCHAL = enum.auto()
|
||||
INDIVIDUAL = enum.auto()
|
||||
|
||||
|
||||
class Beratungsgespraech_Vorgang(BaseModel):
|
||||
model_config = ConfigDict(str_strip_whitespace=True)
|
||||
|
||||
@@ -353,11 +359,12 @@ class Beratungsgespraech_Vorgang(BaseModel):
|
||||
un_id: int | None
|
||||
pers_id: int | None
|
||||
titel: str
|
||||
beratungs_typ: Literal["pauschal", "individuell"]
|
||||
beratungs_typ: ConsultingType
|
||||
|
||||
# default in SQLAlchemy with lambda and timezone-aware datetime
|
||||
erstellt: AwareDatetime | None = Field(default=None, exclude=True)
|
||||
aktualisiert: AwareDatetime | None = Field(default=None, exclude=True) # see above
|
||||
geloescht: AwareDatetime | None = None
|
||||
|
||||
beratungen: list[Beratungsgespraech_Einzelgespraech]
|
||||
|
||||
@@ -379,3 +386,4 @@ class Beratungsgespraech_Einzelgespraech(BaseModel):
|
||||
# default in SQLAlchemy with lambda and timezone-aware datetime
|
||||
erstellt: AwareDatetime | None = Field(default=None, exclude=True)
|
||||
aktualisiert: AwareDatetime | None = Field(default=None, exclude=True) # see above
|
||||
geloescht: AwareDatetime | None = None
|
||||
|
||||
+126
-97
@@ -3,10 +3,8 @@ from __future__ import annotations
|
||||
import copy
|
||||
import dataclasses as dc
|
||||
import datetime
|
||||
import enum
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
from collections import defaultdict
|
||||
from collections.abc import Container, Iterable, Sequence
|
||||
@@ -33,10 +31,13 @@ from PySide6.QtCore import (
|
||||
QDate,
|
||||
QDateTime,
|
||||
QEvent,
|
||||
QLibraryInfo,
|
||||
QLocale,
|
||||
QObject,
|
||||
Qt,
|
||||
QTimer,
|
||||
QtMsgType,
|
||||
QTranslator,
|
||||
Signal,
|
||||
qInstallMessageHandler,
|
||||
)
|
||||
@@ -81,6 +82,7 @@ from wce_crm.data_models import (
|
||||
COLUMN_SEP,
|
||||
Beratungsgespraech_Einzelgespraech,
|
||||
Beratungsgespraech_Vorgang,
|
||||
ConsultingType,
|
||||
FlatBaseModel,
|
||||
Grunderfassung_Personen,
|
||||
Grunderfassung_Unternehmen,
|
||||
@@ -344,11 +346,6 @@ class Page_InitRecPerson_State(PageState[Module]):
|
||||
pers_id: RecId | None = None
|
||||
|
||||
|
||||
class ConsultingType(enum.StrEnum):
|
||||
PAUSCHAL = enum.auto()
|
||||
INDIVIDUAL = enum.auto()
|
||||
|
||||
|
||||
@dc.dataclass(slots=True, kw_only=True)
|
||||
class Page_Consulting_State(PageState[Module]):
|
||||
session: Session
|
||||
@@ -360,6 +357,7 @@ class Page_Consulting_State(PageState[Module]):
|
||||
cons_sessions: list[Page_Consulting_ConsultingSession_State] = dc.field(
|
||||
default_factory=list
|
||||
)
|
||||
ist_geloescht: bool = False
|
||||
|
||||
|
||||
@dc.dataclass(slots=True, kw_only=True)
|
||||
@@ -377,6 +375,7 @@ class Page_Consulting_ConsultingSession_State(PageState[Module]):
|
||||
)
|
||||
anmerkungen: str | None = None
|
||||
rueckmeldung: str | None = None
|
||||
ist_geloescht: bool = False
|
||||
|
||||
|
||||
@dc.dataclass(slots=True, kw_only=True)
|
||||
@@ -845,29 +844,6 @@ def get_form_data(
|
||||
else:
|
||||
value = get_widget_value(widget)
|
||||
|
||||
# elif isinstance(widget, QDateEdit):
|
||||
# qt_date = widget.date()
|
||||
# value = qt_date.toPython()
|
||||
# elif isinstance(widget, FlexibleDateInput):
|
||||
# value = widget.get_pydate()
|
||||
# elif isinstance(widget, FlexibleDateTimeInput):
|
||||
# value = widget.get_pydatetime()
|
||||
# elif isinstance(widget, QComboBox):
|
||||
# value = widget.currentData()
|
||||
# elif isinstance(
|
||||
# widget,
|
||||
# (
|
||||
# DynamicListWidget,
|
||||
# DynamicDropdownWidgetNumeric,
|
||||
# DynamicDropdownWidgetOption,
|
||||
# CustomWidget,
|
||||
# ),
|
||||
# ):
|
||||
# # this is a special data structure with some assumptions of the widget's internals
|
||||
# # DynamicListWidget: this is a list -> each dynamic list contains a list
|
||||
# # of such dictionaries (handled below)
|
||||
# value = widget.get_form_data()
|
||||
|
||||
if isinstance(value, dict):
|
||||
raw_data.update(value)
|
||||
else:
|
||||
@@ -1854,9 +1830,11 @@ class FlexibleDateInput(QWidget):
|
||||
# valid or invalid QDate
|
||||
return QDate.fromString(self.line_edit.text(), "dd.MM.yyyy")
|
||||
|
||||
def get_pydate(self) -> datetime.date:
|
||||
def get_pydate(self) -> datetime.date | None:
|
||||
# valid or invalid QDate
|
||||
date = self.get_date()
|
||||
if not date.isValid():
|
||||
return None
|
||||
py_date = cast(datetime.date, date.toPython())
|
||||
|
||||
return py_date
|
||||
@@ -2065,7 +2043,7 @@ class FlexibleDateTimeInput(QWidget):
|
||||
# valid or invalid QDateTime
|
||||
return QDateTime.fromString(self.line_edit.text(), "dd.MM.yyyy hh:mm")
|
||||
|
||||
def get_pydatetime(self) -> datetime.datetime:
|
||||
def get_pydatetime(self) -> datetime.datetime | None:
|
||||
"""returns current value of the field as UTC datetime
|
||||
|
||||
Returns
|
||||
@@ -2075,6 +2053,8 @@ class FlexibleDateTimeInput(QWidget):
|
||||
"""
|
||||
# valid or invalid datetime
|
||||
dt = self.get_datetime()
|
||||
if not dt.isValid():
|
||||
return None
|
||||
py_dt = cast(datetime.datetime, dt.toPython())
|
||||
py_dt = py_dt.replace(tzinfo=TIMEZONE_CEST)
|
||||
|
||||
@@ -2488,7 +2468,6 @@ class DynamicDropdownWidgetOption(QWidget):
|
||||
sub_form = SubForm(container, prefix_parent=self.prefix, index=number_form)
|
||||
|
||||
form_field_def = copy.copy(self.assigned_form_fields)
|
||||
# form_field_def.label = form_field_def.enhanced_label(f"{number_form}")
|
||||
|
||||
sub_form.full_keys = _build_ui_recursively(
|
||||
schema=form_field_def,
|
||||
@@ -2746,6 +2725,7 @@ class Page_NewInitRec(QWidget):
|
||||
self,
|
||||
new_state: Page_NewInitRec_State,
|
||||
) -> None:
|
||||
set_page_state(self.STATE, new_state)
|
||||
self._sync_state_to_GUI()
|
||||
|
||||
def get_state(self) -> Page_NewInitRec_State:
|
||||
@@ -3371,42 +3351,6 @@ class Page_CompanyProfile(QWidget):
|
||||
txt = f"Unternehmen: {name}"
|
||||
self.title_company_name.setText(txt)
|
||||
|
||||
# def load_from_id(
|
||||
# self,
|
||||
# id_: InitRecId,
|
||||
# ) -> None:
|
||||
# assert id_ is not None, "tried to load with InitRecId None"
|
||||
# assert id_, "tried to load with invalid InitRecId"
|
||||
# logger_gui.debug(f"Called function to load with ID: {id_}")
|
||||
|
||||
# if id_ < 0:
|
||||
# # just clear and do nothing else
|
||||
# logger_gui.debug("just reset with ID < 0")
|
||||
# self.table_master_data.reset()
|
||||
# self.set_company_name("")
|
||||
# self.current_id = id_
|
||||
# return
|
||||
|
||||
# if id_ == self.current_id:
|
||||
# logger_gui.debug("ID did not change. Do nothing")
|
||||
# self.current_id = id_
|
||||
# return
|
||||
|
||||
# init_rec = backend.initrec_company_get_initial_recording(id_)
|
||||
# ma_id = cast(ExtMaId, init_rec["Partnersuche__un_suche"])
|
||||
# assert ma_id is not None, "no ma_id obtained"
|
||||
# comp_info = backend.initrec_comp_search_get_info(ma_id)
|
||||
|
||||
# data: dict[str, Any] = {}
|
||||
|
||||
# for feature, value in comp_info.items():
|
||||
# if feature in self.COMPANY_FEATURES_MASTER_DATA:
|
||||
# data[self.COMPANY_FEATURES_MASTER_DATA[feature]] = value
|
||||
|
||||
# self.table_master_data.load_data(data)
|
||||
# self.set_company_name(data["Name:"])
|
||||
# self.current_id = id_
|
||||
|
||||
|
||||
class MasterDataTable(QWidget):
|
||||
def __init__(self):
|
||||
@@ -3668,13 +3612,6 @@ class Page_Consulting(QWidget):
|
||||
separator1.setFrameShadow(QFrame.Shadow.Sunken)
|
||||
container_layout.addWidget(separator1)
|
||||
|
||||
# layout_change_title = QHBoxLayout()
|
||||
# self.change_title_text = QLineEdit(placeholderText="Unternehmensname eingeben...")
|
||||
# layout_change_title.addWidget(self.change_title_text)
|
||||
# change_title_btn = QPushButton("ändern")
|
||||
# layout_change_title.addWidget(change_title_btn)
|
||||
# change_title_btn.clicked.connect(self.set_company_name)
|
||||
# container_layout.addLayout(layout_change_title)
|
||||
btn_get_data_table = QPushButton("Debug call 'get_state' from table and page")
|
||||
btn_get_data_table.clicked.connect(self._debug_get_state)
|
||||
container_layout.addWidget(btn_get_data_table)
|
||||
@@ -3937,13 +3874,23 @@ class Page_Consulting(QWidget):
|
||||
self.STATE.un_id = data.un_id
|
||||
self.STATE.pers_id = data.pers_id
|
||||
self.STATE.titel = data.titel
|
||||
self.STATE.ist_geloescht = data.geloescht is not None
|
||||
|
||||
if update_only:
|
||||
for gui_state, pydantic_state in zip(self.STATE.cons_sessions, data.beratungen):
|
||||
relevant_gui_states = [s for s in self.STATE.cons_sessions if not s.ist_geloescht]
|
||||
rel_cons_session_states = [s for s in data.beratungen if s.geloescht is None]
|
||||
print(f">>>>>>> {pformat(relevant_gui_states)}")
|
||||
assert len(relevant_gui_states) == len(rel_cons_session_states)
|
||||
for gui_state, pydantic_state in zip(
|
||||
relevant_gui_states, rel_cons_session_states
|
||||
):
|
||||
gui_state.beratung_id = pydantic_state.beratung_id
|
||||
else:
|
||||
self.STATE.cons_sessions.clear()
|
||||
for pydantic_state in data.beratungen:
|
||||
# Deleted sessions are not part of the retrieved data from the backend if this
|
||||
# page is initialised from a fresh backend call to get data. (Updates do
|
||||
# indeed have data which must be filtered -- see above)
|
||||
cons_session_state = Page_Consulting_ConsultingSession_State(
|
||||
session=self.STATE.session,
|
||||
nutzer_id=pydantic_state.nutzer_id,
|
||||
@@ -3989,10 +3936,32 @@ class Page_Consulting(QWidget):
|
||||
|
||||
pydantic_sessions: list[Beratungsgespraech_Einzelgespraech] = []
|
||||
|
||||
timestamp_deleted: datetime.datetime | None = None
|
||||
if self.STATE.ist_geloescht:
|
||||
timestamp_deleted = datetime.datetime.now(datetime.UTC)
|
||||
|
||||
for row in self.STATE.cons_sessions:
|
||||
logger_page_consulting.debug("[Consulting Page] Row state:\n%s", row)
|
||||
if row.beratung_id is None and row.ist_geloescht:
|
||||
logger_page_consulting.debug(
|
||||
(
|
||||
"[Consulting Page] Session which was never saved in the database "
|
||||
"and is marked for deletion - ignore."
|
||||
)
|
||||
)
|
||||
continue
|
||||
|
||||
timestamp_deleted_session: datetime.datetime | None = None
|
||||
if timestamp_deleted is not None:
|
||||
# if process is deleted, all sessions must be marked as deleted
|
||||
timestamp_deleted_session = timestamp_deleted
|
||||
elif row.ist_geloescht:
|
||||
timestamp_deleted_session = datetime.datetime.now(datetime.UTC)
|
||||
|
||||
cons_session_dict = dc.asdict(row)
|
||||
cons_session = Beratungsgespraech_Einzelgespraech(
|
||||
vorgang_id=self.STATE.vorgang_id,
|
||||
geloescht=timestamp_deleted_session,
|
||||
**cons_session_dict,
|
||||
)
|
||||
pydantic_sessions.append(cons_session)
|
||||
@@ -4003,6 +3972,7 @@ class Page_Consulting(QWidget):
|
||||
pers_id=self.STATE.pers_id,
|
||||
titel=self.STATE.titel,
|
||||
beratungs_typ=self.STATE.beratungs_typ, # type: ignore
|
||||
geloescht=timestamp_deleted,
|
||||
beratungen=pydantic_sessions,
|
||||
)
|
||||
|
||||
@@ -4016,6 +3986,10 @@ class Page_Consulting(QWidget):
|
||||
if DEBUG_NO_DATABASE:
|
||||
return
|
||||
logger_page_consulting.debug("[Consulting Page] Validated Pydantic successfully.")
|
||||
logger_page_consulting.debug(
|
||||
"[Consulting Page] Pydantic model:\n%s", consulting_process
|
||||
)
|
||||
|
||||
# !! should be placed in a try block to handle errors
|
||||
res = backend.page_consulting_to_db(consulting_process)
|
||||
if res.status != STATUS_HANDLER.SUCCESS:
|
||||
@@ -4042,21 +4016,20 @@ class Page_Consulting(QWidget):
|
||||
msg_box.exec()
|
||||
return
|
||||
|
||||
updated_data = res.unwrap()
|
||||
updated_consulting_process = res.unwrap()
|
||||
logger_page_consulting.info(
|
||||
"[Consulting Page] Load state from modified Pydantic model"
|
||||
)
|
||||
self._load_from_pydantic(updated_data, update_only=True)
|
||||
self._load_from_pydantic(updated_consulting_process, update_only=True)
|
||||
|
||||
logger_page_consulting.info("[Consulting Page] Data saved successfully")
|
||||
# TODO status message successful to user in GUI
|
||||
msg_box = get_message_box(
|
||||
QMessageBox.Icon.Information,
|
||||
"Speichern erfolgreich",
|
||||
"Die Daten wurden erfolgreich gespeichert",
|
||||
)
|
||||
msg_box.exec()
|
||||
|
||||
# TODO check triggers for rest of application
|
||||
# self.update_triggered.emit()
|
||||
# self._activate_delete()
|
||||
finally:
|
||||
@@ -4173,7 +4146,7 @@ class Page_Consulting_ConsultingSession(QWidget):
|
||||
self.btn_delete.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
|
||||
self.btn_delete.setStyleSheet("color: #cc0000; font-weight: bold;")
|
||||
self.btn_delete.clicked.connect(lambda: self.delete_request.emit(self))
|
||||
self.btn_delete.clicked.connect(self._delete_request)
|
||||
self.btn_delete.setFixedWidth(30)
|
||||
layout.addWidget(self.btn_delete)
|
||||
|
||||
@@ -4206,7 +4179,17 @@ class Page_Consulting_ConsultingSession(QWidget):
|
||||
layout.setStretch(i, stretch)
|
||||
|
||||
self.setSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed)
|
||||
self._sync_state_to_GUI() # ?? only needed if entry is from database?
|
||||
self._sync_state_to_GUI()
|
||||
|
||||
def _delete_request(self) -> None:
|
||||
confirm = get_user_confirmation(
|
||||
self,
|
||||
"Löschen bestätigen",
|
||||
"Soll der Eintrag wirklich gelöscht werden?",
|
||||
)
|
||||
if confirm:
|
||||
self.STATE.ist_geloescht = True
|
||||
self.delete_request.emit(self)
|
||||
|
||||
def _sync_state_to_GUI(self) -> None:
|
||||
logger_page_consulting.debug(
|
||||
@@ -4276,7 +4259,7 @@ class Page_Consulting_Table(QWidget):
|
||||
self.btn_add.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
self.btn_add.setObjectName("BlueAddButton") # ID vergeben
|
||||
main_layout.addWidget(self.btn_add)
|
||||
self.btn_add.clicked.connect(lambda: self.add_row(None))
|
||||
self.btn_add.clicked.connect(lambda: self.add_row(None, False))
|
||||
|
||||
self.btn_add.setStyleSheet("""
|
||||
#BlueAddButton {
|
||||
@@ -4417,7 +4400,8 @@ class Page_Consulting_Table(QWidget):
|
||||
|
||||
def add_row(
|
||||
self,
|
||||
row_state: Page_Consulting_ConsultingSession_State | None = None,
|
||||
row_state: Page_Consulting_ConsultingSession_State | None,
|
||||
state_exists: bool,
|
||||
) -> None:
|
||||
if row_state is None:
|
||||
row_state = Page_Consulting_ConsultingSession_State(
|
||||
@@ -4429,10 +4413,13 @@ class Page_Consulting_Table(QWidget):
|
||||
|
||||
row = Page_Consulting_ConsultingSession(state=row_state)
|
||||
row.delete_request.connect(self.remove_row)
|
||||
# sys.exit(0)
|
||||
|
||||
index = self.container_layout.count() - 1
|
||||
self.container_layout.insertWidget(index, row)
|
||||
self.STATE.child_modules.append(row)
|
||||
if not state_exists:
|
||||
self.STATE.row_states.append(row.get_state())
|
||||
|
||||
def remove_row(
|
||||
self,
|
||||
@@ -4440,36 +4427,49 @@ class Page_Consulting_Table(QWidget):
|
||||
) -> None:
|
||||
self.container_layout.removeWidget(table_row_widget)
|
||||
self.STATE.child_modules.remove(table_row_widget)
|
||||
# do not remove the corresponding state since it is tracked
|
||||
# to be post-processed when the database saving operation is triggered
|
||||
table_row_widget.deleteLater()
|
||||
|
||||
def reset(self) -> None:
|
||||
def remove_all_rows(self) -> None:
|
||||
while self.STATE.child_modules:
|
||||
self.remove_row(self.STATE.child_modules[0])
|
||||
|
||||
def _sync_state_to_GUI(self) -> None:
|
||||
self.setUpdatesEnabled(False)
|
||||
|
||||
self.reset()
|
||||
self.remove_all_rows()
|
||||
# states_to_show = [s for s in self.STATE.row_states if not s.ist_geloescht]
|
||||
# for row_state in states_to_show:
|
||||
for row_state in self.STATE.row_states:
|
||||
self.add_row(row_state)
|
||||
if not row_state.ist_geloescht:
|
||||
self.add_row(row_state, True)
|
||||
|
||||
self.setUpdatesEnabled(True)
|
||||
|
||||
def _sync_GUI_to_state(self) -> None:
|
||||
logger_page_consulting.debug("[Page -- Consulting] Table: Call syncing GUI to state")
|
||||
row_data: list[Page_Consulting_ConsultingSession_State] = []
|
||||
logger_page_consulting.debug(
|
||||
(
|
||||
"[Page -- Consulting] Table: Row data is managed when entries are added. "
|
||||
"There is no action needed. All states are obtained by reference and set "
|
||||
"by their row components/widgets. Therefore, this method calls the "
|
||||
"method `get_state` of all ACTIVE components to update their respective "
|
||||
"states with the current user inputs."
|
||||
)
|
||||
)
|
||||
|
||||
logger_page_consulting.debug(
|
||||
"[Page -- Consulting] Table - Child modules: %s",
|
||||
pformat(self.STATE.child_modules),
|
||||
)
|
||||
# Child modules are ACTIVE elements, viewable and changeable by the user.
|
||||
# The states are already part of this widget and linked by reference, but
|
||||
# the current user input must be synced with these states. Therefore, the
|
||||
# `get_state` method of these children is called, which implicitly updates
|
||||
# their state. The returned state reference is not needed.
|
||||
for row in self.STATE.child_modules:
|
||||
row_data.append(row.get_state())
|
||||
|
||||
assert len(row_data) == len(self.STATE.child_modules), (
|
||||
"mismatch in row count and data length"
|
||||
)
|
||||
self.STATE.row_states = row_data
|
||||
_ = row.get_state()
|
||||
|
||||
def get_state(self) -> Page_Consulting_Table_State:
|
||||
logger_page_consulting.debug("[Page Consulting -- Table] Syncing GUI to state...")
|
||||
@@ -4536,7 +4536,6 @@ def clear_layout(
|
||||
if layout is None:
|
||||
return
|
||||
|
||||
# for idx in range(start_idx, layout.count()):
|
||||
while layout.count():
|
||||
child = layout.takeAt(0)
|
||||
if child is None:
|
||||
@@ -4864,6 +4863,25 @@ def get_message_box(
|
||||
return msg_box
|
||||
|
||||
|
||||
def get_user_confirmation(
|
||||
parent_widget: QWidget,
|
||||
title: str,
|
||||
message: str,
|
||||
) -> bool:
|
||||
response = QMessageBox.question(
|
||||
parent_widget,
|
||||
title,
|
||||
message,
|
||||
buttons=(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No),
|
||||
defaultButton=QMessageBox.StandardButton.No,
|
||||
)
|
||||
|
||||
if response == QMessageBox.StandardButton.Yes:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def pydantic_validation_error_handling(
|
||||
val_error: ValidationError,
|
||||
) -> None:
|
||||
@@ -4959,15 +4977,26 @@ if TYPE_CHECKING:
|
||||
_w1: type[WrapperModule] = Page_InitRecCompany
|
||||
_w2: type[WrapperModule] = Page_InitRecPerson
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
def main() -> None:
|
||||
sys.excepthook = global_exception_handler
|
||||
qInstallMessageHandler(qt_message_handler)
|
||||
|
||||
try:
|
||||
app = QApplication(sys.argv)
|
||||
app.setStyleSheet(QSS)
|
||||
|
||||
translator = QTranslator()
|
||||
translation_path = QLibraryInfo.path(QLibraryInfo.LibraryPath.TranslationsPath)
|
||||
if translator.load(QLocale.system(), "qtbase", "_", translation_path):
|
||||
app.installTranslator(translator)
|
||||
|
||||
window = MainWindow()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
except Exception as err:
|
||||
logger_gui.critical("Fehler beim Starten der Anwendung:\n%s", str(err), exc_info=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user