generated from dopt-python/py311
prepare search in contact list as dynamic widget
This commit is contained in:
@@ -12,7 +12,7 @@ import uuid
|
||||
from collections.abc import Sequence
|
||||
from pathlib import Path
|
||||
from pprint import pprint
|
||||
from typing import Annotated, Any, Protocol, TypeAlias, TypedDict
|
||||
from typing import Annotated, Any, Protocol, TypeAlias, TypedDict, cast
|
||||
|
||||
import babel
|
||||
from pydantic import BaseModel, ConfigDict, EmailStr, Field, ValidationError, field_validator
|
||||
@@ -199,6 +199,92 @@ def pprint_registry(widget_registry: WidgetRegistry) -> None:
|
||||
print(f"\tfield type: {entry['form_field'].type}")
|
||||
|
||||
|
||||
class FormFieldType(enum.StrEnum):
|
||||
GROUP = enum.auto()
|
||||
TEXT = enum.auto()
|
||||
LONGTEXT = enum.auto()
|
||||
DATE = enum.auto()
|
||||
DATETIME = enum.auto()
|
||||
DROPDOWN = enum.auto()
|
||||
EXTENDED_DROPDOWN = enum.auto()
|
||||
DYNAMIC_LIST = enum.auto()
|
||||
DYNAMIC_DROPDOWN = enum.auto()
|
||||
TEXT_SEARCH = enum.auto()
|
||||
|
||||
|
||||
@dc.dataclass(slots=True)
|
||||
class DropdownOption:
|
||||
label: str
|
||||
_data: dc.InitVar[Any | None] = None
|
||||
data: Any = dc.field(init=False)
|
||||
|
||||
def __post_init__(
|
||||
self,
|
||||
_data: Any | None,
|
||||
) -> None:
|
||||
if _data is None:
|
||||
self.data = self.label
|
||||
else:
|
||||
self.data = _data
|
||||
|
||||
|
||||
@dc.dataclass(slots=True)
|
||||
class FormField:
|
||||
label: str
|
||||
type: FormFieldType
|
||||
children: Sequence[FormField] = dc.field(default_factory=list)
|
||||
parent: FormField | None = None
|
||||
required: bool = False
|
||||
placeholder: str = ""
|
||||
fill_value: str = ""
|
||||
readonly: bool = False
|
||||
options: dc.InitVar[Sequence[tuple[str, Any]]] = tuple()
|
||||
dropdown_options: Sequence[DropdownOption] = dc.field(default=tuple(), init=False)
|
||||
key: str = ""
|
||||
tooltip: str = ""
|
||||
info: str = ""
|
||||
init_label: str = dc.field(init=False)
|
||||
|
||||
def __post_init__(
|
||||
self,
|
||||
options: Sequence[tuple[str, Any]],
|
||||
) -> None:
|
||||
if not self.key:
|
||||
self.key = str(uuid.uuid4())
|
||||
|
||||
self.label = self.label.strip()
|
||||
self.init_label = self.label.replace("*", "").replace(":", "")
|
||||
if not self.label.endswith(":") and self.type is not FormFieldType.GROUP:
|
||||
self.label += ":"
|
||||
if self.required:
|
||||
self.label += "*"
|
||||
|
||||
# if (
|
||||
# self.type in (FormFieldType.DROPDOWN, FormFieldType.EXTENDED_DROPDOWN)
|
||||
# and not options
|
||||
# ):
|
||||
# raise ValueError("Invalid field definition: Dropdown requires options")
|
||||
if self.type in (FormFieldType.DROPDOWN, FormFieldType.EXTENDED_DROPDOWN):
|
||||
self.dropdown_options = tuple(DropdownOption(op[0], op[1]) for op in options)
|
||||
|
||||
if self.children:
|
||||
self.required = any((child.required for child in self.children))
|
||||
for child in self.children:
|
||||
child.parent = self
|
||||
|
||||
def enhanced_label(
|
||||
self,
|
||||
add_text: str,
|
||||
) -> str:
|
||||
enhanced_label = self.init_label + f" {add_text}"
|
||||
if not enhanced_label.endswith(":") and self.type is not FormFieldType.GROUP:
|
||||
enhanced_label += ":"
|
||||
if self.required:
|
||||
enhanced_label += "*"
|
||||
|
||||
return enhanced_label
|
||||
|
||||
|
||||
class CustomForm(Protocol):
|
||||
def get_form_data(self) -> dict[str, Any]: ...
|
||||
|
||||
@@ -254,6 +340,30 @@ def _build_ui_recursively(
|
||||
else:
|
||||
parent_layout.addRow(field.label, widget)
|
||||
|
||||
case FormFieldType.TEXT_SEARCH:
|
||||
widget = QLineEdit()
|
||||
if field.placeholder:
|
||||
widget.setPlaceholderText(field.placeholder)
|
||||
else:
|
||||
widget.setPlaceholderText("Tippen zum Suchen...")
|
||||
|
||||
search_completer = QCompleter()
|
||||
search_completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
|
||||
search_completer.setFilterMode(Qt.MatchFlag.MatchContains)
|
||||
widget.setCompleter(search_completer)
|
||||
|
||||
widget_registry[full_key] = {
|
||||
"widget": widget,
|
||||
"form_field": field,
|
||||
}
|
||||
widget.installEventFilter(no_scroll_filter)
|
||||
|
||||
if field.tooltip:
|
||||
tooltip_layout = _add_tooltip(widget, field.tooltip)
|
||||
parent_layout.addRow(field.label, tooltip_layout)
|
||||
else:
|
||||
parent_layout.addRow(field.label, widget)
|
||||
|
||||
case FormFieldType.LONGTEXT:
|
||||
widget = QPlainTextEdit()
|
||||
widget.setMaximumHeight(80)
|
||||
@@ -319,7 +429,6 @@ def _build_ui_recursively(
|
||||
|
||||
case FormFieldType.DROPDOWN:
|
||||
widget = QComboBox()
|
||||
assert field.dropdown_options
|
||||
widget.addItem(DROPDOWN_DEFAULT, None)
|
||||
for option in field.dropdown_options:
|
||||
widget.addItem(option.label, option.data)
|
||||
@@ -356,7 +465,6 @@ def _build_ui_recursively(
|
||||
completer.setFilterMode(Qt.MatchFlag.MatchContains)
|
||||
completer.setCompletionMode(QCompleter.CompletionMode.PopupCompletion)
|
||||
|
||||
assert field.dropdown_options
|
||||
widget.addItem(DROPDOWN_DEFAULT, None)
|
||||
for option in field.dropdown_options:
|
||||
widget.addItem(option.label, option.data)
|
||||
@@ -438,6 +546,8 @@ def reset_form(
|
||||
widget = registry_entry["widget"]
|
||||
form_field = registry_entry["form_field"]
|
||||
|
||||
# TODO check if this behaviour is correct in other contexts, deactivated because of
|
||||
# TODO company search widget
|
||||
if form_field.readonly:
|
||||
continue
|
||||
|
||||
@@ -554,9 +664,7 @@ def get_form_data(
|
||||
# pprint(form_data)
|
||||
elif isinstance(widget, DynamicDropdownWidget):
|
||||
# this is a special data structure with some assumptions of the widget's structure
|
||||
form_data = widget.get_form_data()
|
||||
value = form_data
|
||||
# value = [val for val in form_data.values()]
|
||||
value = widget.get_form_data()
|
||||
# print(">>>>>>>>> Key: ", key)
|
||||
# print(">>>>>>>>> Form Data after call:")
|
||||
# pprint(form_data)
|
||||
@@ -789,7 +897,7 @@ class Grunderfassung_Sprachen(BaseModel):
|
||||
SP_datum_nachweis: datetime.date | None
|
||||
|
||||
|
||||
class CompanyForm_Search(QWidget):
|
||||
class CompanyForm_Search_old(QWidget):
|
||||
company_selected = Signal(int)
|
||||
|
||||
def __init__(self):
|
||||
@@ -885,6 +993,602 @@ class CompanyForm_Search(QWidget):
|
||||
self.company_selected.emit(ma_id)
|
||||
|
||||
|
||||
class CompanyForm_Search_Data(TypedDict):
|
||||
ma_id: int
|
||||
|
||||
|
||||
class Grunderfassung_Suche(QWidget):
|
||||
# company_selected = Signal(int)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
# form_fields: Sequence[FormField],
|
||||
label: str = "Suche",
|
||||
prefix: str = "",
|
||||
):
|
||||
super().__init__()
|
||||
# self.form_fields = form_fields
|
||||
self.label = label
|
||||
self.prefix = prefix
|
||||
# self.widget_registry: WidgetRegistry = {}
|
||||
self.export_data: CompanyForm_Search_Data = {"ma_id": -1}
|
||||
self.PROPERTY_MA_ID = "user_ma_id"
|
||||
|
||||
main_layout = QVBoxLayout(self)
|
||||
main_layout.setContentsMargins(0, 0, 0, 0)
|
||||
form_layout = QFormLayout()
|
||||
form_layout.setSpacing(10)
|
||||
# TODO: remove title?
|
||||
title = QLabel(self.label)
|
||||
title.setStyleSheet("font-size: 14px; font-weight: bold;")
|
||||
main_layout.addWidget(title)
|
||||
# --- SEARCH ---
|
||||
self.company_search_input = QLineEdit(placeholderText="Tippen zum Suchen...")
|
||||
form_layout.addRow("Suche:", self.company_search_input)
|
||||
self.company_search_completer = QCompleter()
|
||||
self.company_search_completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
|
||||
self.company_search_completer.setFilterMode(Qt.MatchFlag.MatchContains)
|
||||
self.company_search_input.setCompleter(self.company_search_completer)
|
||||
self.company_search_completer.activated[QModelIndex].connect( # type: ignore
|
||||
self._selected_company_on_completer
|
||||
)
|
||||
self.company_search_input.textChanged.connect(self._search_company_change_manually)
|
||||
# --- FILLED FIELDS ---
|
||||
# name
|
||||
self.company_name = QLineEdit(placeholderText="Name des Partners")
|
||||
form_layout.addRow("Name Unternehmen/Netzwerkpartner:", self.company_name)
|
||||
# street
|
||||
street_layout = QHBoxLayout()
|
||||
street_layout.setContentsMargins(0, 0, 0, 0)
|
||||
street_layout.setSpacing(10)
|
||||
self.company_street = QLineEdit(placeholderText="Straße")
|
||||
self.company_streetnumber = QLineEdit(placeholderText="Nr.")
|
||||
self.company_streetnumber.setMaximumWidth(80)
|
||||
street_layout.addWidget(self.company_street, stretch=3)
|
||||
street_layout.addWidget(self.company_streetnumber, stretch=1)
|
||||
form_layout.addRow("Straße / Nr.:", street_layout)
|
||||
# ZIP, city
|
||||
# --- 3. Kombinierte Zeile: PLZ & Ort ---
|
||||
city_layout = QHBoxLayout()
|
||||
city_layout.setContentsMargins(0, 0, 0, 0)
|
||||
city_layout.setSpacing(10)
|
||||
self.company_zip = QLineEdit(placeholderText="PLZ")
|
||||
self.company_city = QLineEdit(placeholderText="Ort")
|
||||
self.company_zip.setMaximumWidth(100) # PLZ ist immer relativ kurz
|
||||
city_layout.addWidget(self.company_zip, stretch=1)
|
||||
city_layout.addWidget(self.company_city, stretch=3)
|
||||
form_layout.addRow("PLZ / Ort:", city_layout)
|
||||
|
||||
# !! -------------------------------------------------------------------
|
||||
# Integration of person search
|
||||
# TODO: remove title
|
||||
spacing_layout = QVBoxLayout()
|
||||
spacing_layout.addSpacing(15)
|
||||
form_layout.addRow(spacing_layout)
|
||||
|
||||
title = QLabel("--- Suche Nutzer ---")
|
||||
title.setStyleSheet("font-size: 14px; font-weight: bold;")
|
||||
main_layout.addWidget(title)
|
||||
# --- SEARCH ---
|
||||
self.person_search_input = QComboBox()
|
||||
self.person_search_input.setEditable(True)
|
||||
self.person_search_input.setInsertPolicy(QComboBox.InsertPolicy.NoInsert)
|
||||
line_edit = self.person_search_input.lineEdit()
|
||||
assert line_edit
|
||||
line_edit.setPlaceholderText("Suchen...")
|
||||
# --- FILLED FIELDS ---
|
||||
form_layout.addRow("Suche Ansprechpartner:", self.person_search_input)
|
||||
self.person_completer = self.person_search_input.completer()
|
||||
assert self.person_completer
|
||||
self.person_completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
|
||||
self.person_completer.setFilterMode(Qt.MatchFlag.MatchContains)
|
||||
self.person_completer.setCompletionMode(QCompleter.CompletionMode.PopupCompletion)
|
||||
# self.person_search_input.activated.connect(self._selected_person_on_completer)
|
||||
self.person_search_input.currentIndexChanged.connect(
|
||||
self._selected_person_on_completer
|
||||
)
|
||||
# salutation
|
||||
self.person_titel = QLineEdit()
|
||||
self.person_anrede = QLineEdit()
|
||||
hor_layout = QHBoxLayout()
|
||||
hor_layout.addWidget(self.person_anrede, stretch=1)
|
||||
hor_layout.addWidget(self.person_titel, stretch=1)
|
||||
form_layout.addRow("Anrede / Titel:", hor_layout)
|
||||
# names
|
||||
self.person_nachname = QLineEdit()
|
||||
self.person_vorname = QLineEdit()
|
||||
hor_layout = QHBoxLayout()
|
||||
hor_layout.addWidget(self.person_nachname, stretch=1)
|
||||
hor_layout.addWidget(self.person_vorname, stretch=1)
|
||||
form_layout.addRow("Nachname / Vorname:", hor_layout)
|
||||
# phones
|
||||
phone_layout = QHBoxLayout()
|
||||
phone_layout.setContentsMargins(0, 0, 0, 0)
|
||||
phone_layout.setSpacing(10)
|
||||
self.person_landline_number = QLineEdit()
|
||||
self.person_mobile_number = QLineEdit()
|
||||
phone_layout.addWidget(self.person_landline_number, stretch=1)
|
||||
phone_layout.addWidget(self.person_mobile_number, stretch=1)
|
||||
form_layout.addRow("Telefon Festnetz / Mobil:", phone_layout)
|
||||
# additional
|
||||
self.person_email = QLineEdit()
|
||||
form_layout.addRow("E-Mail:", self.person_email)
|
||||
self.person_funktion = QLineEdit()
|
||||
form_layout.addRow("Funktion:", self.person_funktion)
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
# add fom layout
|
||||
main_layout.addLayout(form_layout)
|
||||
main_layout.addSpacing(20)
|
||||
main_layout.addWidget(
|
||||
QLabel('>>>> Platzhalter "Wie sind Sie auf uns aufmerksam geworden?"')
|
||||
)
|
||||
|
||||
self.autofilled_fields: tuple[QLineEdit, ...] = (
|
||||
self.company_name,
|
||||
self.company_street,
|
||||
self.company_streetnumber,
|
||||
self.company_zip,
|
||||
self.company_city,
|
||||
self.person_titel,
|
||||
self.person_anrede,
|
||||
self.person_nachname,
|
||||
self.person_vorname,
|
||||
self.person_landline_number,
|
||||
self.person_mobile_number,
|
||||
self.person_email,
|
||||
self.person_funktion,
|
||||
)
|
||||
|
||||
for field in self.autofilled_fields:
|
||||
field.setReadOnly(True)
|
||||
field.setProperty("styleClass", "stempel")
|
||||
|
||||
self.update_company_data()
|
||||
# self.update_person_data(None)
|
||||
|
||||
def fill_out_company(self, comp_info: be_init_rec.CompanyInfo):
|
||||
self.company_name.setText(comp_info["ma_unternehmensname"])
|
||||
self.company_street.setText(comp_info["ma_strasse"])
|
||||
self.company_streetnumber.setText(comp_info["ma_hausnummer"])
|
||||
self.company_zip.setText(comp_info["ma_plz"])
|
||||
self.company_city.setText(comp_info["ma_ort"])
|
||||
|
||||
def fill_out(
|
||||
self,
|
||||
info: be_init_rec.ContactPersonInfo,
|
||||
) -> None:
|
||||
self.person_titel.setText(info["an_titel"])
|
||||
self.person_anrede.setText(info["an_anrede"])
|
||||
self.person_nachname.setText(info["an_nachname"])
|
||||
self.person_vorname.setText(info["an_vorname"])
|
||||
self.person_landline_number.setText(info["an_festnetz"])
|
||||
self.person_mobile_number.setText(info["an_mobil"])
|
||||
self.person_email.setText(info["an_mail"])
|
||||
self.person_funktion.setText(info["an_position"])
|
||||
|
||||
def clear_autofilled_fields(self) -> None:
|
||||
self.company_search_input.clear()
|
||||
self.person_search_input.clear()
|
||||
for field in self.autofilled_fields:
|
||||
field.clear()
|
||||
|
||||
def update_company_data(self) -> None:
|
||||
self.clear_autofilled_fields()
|
||||
search_items = QStandardItemModel()
|
||||
search_choices = be_init_rec.comp_search_choices()
|
||||
for item, db_index in search_choices:
|
||||
qitem = QStandardItem(item)
|
||||
qitem.setData(db_index, Qt.ItemDataRole.UserRole)
|
||||
search_items.appendRow(qitem)
|
||||
|
||||
self.company_search_completer.setModel(search_items)
|
||||
|
||||
def update_person_data(
|
||||
self,
|
||||
ma_id: int | None,
|
||||
) -> None:
|
||||
self.clear_autofilled_fields()
|
||||
search_choices = be_init_rec.contact_person_search_choices(ma_id, True)
|
||||
for item, db_index in search_choices:
|
||||
self.person_search_input.addItem(item, db_index)
|
||||
self.person_search_input.setCurrentIndex(0)
|
||||
|
||||
def _selected_company_on_completer(
|
||||
self,
|
||||
index: QModelIndex,
|
||||
) -> None:
|
||||
ma_id = index.data(Qt.ItemDataRole.UserRole)
|
||||
comp_info = be_init_rec.comp_search_get_info(
|
||||
ma_id=ma_id,
|
||||
)
|
||||
self.company_search_input.setProperty(self.PROPERTY_MA_ID, ma_id)
|
||||
self.fill_out_company(comp_info)
|
||||
# self.company_selected.emit(ma_id)
|
||||
self.update_person_data(ma_id)
|
||||
|
||||
def _selected_person_on_completer(
|
||||
self,
|
||||
index: int,
|
||||
):
|
||||
an_id = self.person_search_input.itemData(index)
|
||||
comp_info = be_init_rec.contact_person_search_get_info(
|
||||
an_id=an_id,
|
||||
)
|
||||
self.fill_out(comp_info)
|
||||
|
||||
def _search_company_change_manually(
|
||||
self,
|
||||
_: str,
|
||||
) -> None:
|
||||
self.company_search_input.setProperty(self.PROPERTY_MA_ID, -1)
|
||||
|
||||
def get_form_data(self) -> CompanyForm_Search_Data:
|
||||
ma_id = self.company_search_input.property(self.PROPERTY_MA_ID)
|
||||
self.export_data["ma_id"] = ma_id
|
||||
|
||||
return self.export_data
|
||||
|
||||
def set_form_data(
|
||||
self,
|
||||
ma_id: int,
|
||||
) -> None:
|
||||
comp_info = be_init_rec.comp_search_get_info(
|
||||
ma_id=ma_id,
|
||||
)
|
||||
self.company_search_input.setText(comp_info["ma_unternehmensname"])
|
||||
self.fill_out_company(comp_info)
|
||||
# self.company_selected.emit(ma_id)
|
||||
|
||||
|
||||
FORM_FIELDS_SEARCH_HEAD = [
|
||||
FormField(
|
||||
"Suche",
|
||||
FormFieldType.TEXT_SEARCH,
|
||||
required=False,
|
||||
key="kontaktliste_un_suche",
|
||||
),
|
||||
FormField(
|
||||
"Name Unternehmen/Netzwerkpartner",
|
||||
FormFieldType.TEXT,
|
||||
required=False,
|
||||
key="kontaktliste_un_name",
|
||||
readonly=True,
|
||||
info="ma_unternehmensname",
|
||||
),
|
||||
FormField(
|
||||
"Straße",
|
||||
FormFieldType.TEXT,
|
||||
required=False,
|
||||
key="kontaktliste_un_straße",
|
||||
readonly=True,
|
||||
info="ma_strasse",
|
||||
),
|
||||
FormField(
|
||||
"Hausnummer",
|
||||
FormFieldType.TEXT,
|
||||
required=False,
|
||||
key="kontaktliste_un_hausnummer",
|
||||
readonly=True,
|
||||
info="ma_hausnummer",
|
||||
),
|
||||
FormField(
|
||||
"PLZ",
|
||||
FormFieldType.TEXT,
|
||||
required=False,
|
||||
key="kontaktliste_un_PLZ",
|
||||
readonly=True,
|
||||
info="ma_plz",
|
||||
),
|
||||
FormField(
|
||||
"Ort",
|
||||
FormFieldType.TEXT,
|
||||
required=False,
|
||||
key="kontaktliste_un_ort",
|
||||
readonly=True,
|
||||
info="ma_ort",
|
||||
),
|
||||
FormField(
|
||||
"Suche Ansprechpartner",
|
||||
FormFieldType.EXTENDED_DROPDOWN,
|
||||
required=False,
|
||||
key="kontaktliste_person_suche",
|
||||
info="ma_ort",
|
||||
),
|
||||
FormField(
|
||||
"Titel",
|
||||
FormFieldType.TEXT,
|
||||
required=False,
|
||||
key="kontaktliste_person_titel",
|
||||
readonly=True,
|
||||
info="an_titel",
|
||||
),
|
||||
FormField(
|
||||
"Anrede",
|
||||
FormFieldType.TEXT,
|
||||
required=False,
|
||||
key="kontaktliste_person_anrede",
|
||||
readonly=True,
|
||||
info="an_anrede",
|
||||
),
|
||||
FormField(
|
||||
"Name",
|
||||
FormFieldType.TEXT,
|
||||
required=False,
|
||||
key="kontaktliste_person_name",
|
||||
readonly=True,
|
||||
info="an_nachname",
|
||||
),
|
||||
FormField(
|
||||
"Vorname",
|
||||
FormFieldType.TEXT,
|
||||
required=False,
|
||||
key="kontaktliste_person_vorname",
|
||||
readonly=True,
|
||||
info="an_vorname",
|
||||
),
|
||||
FormField(
|
||||
"Telefon",
|
||||
FormFieldType.TEXT,
|
||||
required=False,
|
||||
key="kontaktliste_person_telefon",
|
||||
readonly=True,
|
||||
info="an_festnetz",
|
||||
),
|
||||
FormField(
|
||||
"Mobil",
|
||||
FormFieldType.TEXT,
|
||||
required=False,
|
||||
key="kontaktliste_person_mobilfunk",
|
||||
readonly=True,
|
||||
info="an_mobil",
|
||||
),
|
||||
FormField(
|
||||
"E-Mail",
|
||||
FormFieldType.TEXT,
|
||||
required=False,
|
||||
key="kontaktliste_person_email",
|
||||
readonly=True,
|
||||
info="an_mail",
|
||||
),
|
||||
FormField(
|
||||
"Funktion im Unternehmen",
|
||||
FormFieldType.TEXT,
|
||||
required=False,
|
||||
key="kontaktliste_person_funktion",
|
||||
readonly=True,
|
||||
info="an_position",
|
||||
),
|
||||
FormField(
|
||||
"Wie sind Sie auf uns aufmerksam geworden?",
|
||||
FormFieldType.DROPDOWN,
|
||||
required=False,
|
||||
key="kontaktliste_kanal_aufmerksamkeit",
|
||||
options=[
|
||||
("Agentur für Arbeit", None),
|
||||
("Ausländerbehörde", None),
|
||||
("Jobcenter", None),
|
||||
("Freunde/Familie", None),
|
||||
("Anerkennungsstelle", None),
|
||||
("Beratungsstelle", None),
|
||||
("Internet", None),
|
||||
("Arbeitgeber", None),
|
||||
("Bildungsdienstleister", None),
|
||||
("Welcome-Mappe", None),
|
||||
("Newsletter WFE", None),
|
||||
("Newsletter RM", None),
|
||||
("Sonstiges", None),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
class Grunderfassung_Suche_new(QWidget):
|
||||
def __init__(
|
||||
self,
|
||||
form_fields: Sequence[FormField],
|
||||
label: str = "Suche",
|
||||
prefix: str = "",
|
||||
):
|
||||
super().__init__()
|
||||
self.form_fields = form_fields
|
||||
self.label = label
|
||||
self.prefix = prefix
|
||||
self.widget_registry: WidgetRegistry = {}
|
||||
self.export_data: CompanyForm_Search_Data = {"ma_id": -1}
|
||||
self.PROPERTY_MA_ID = "user_ma_id"
|
||||
|
||||
main_layout = QVBoxLayout(self)
|
||||
main_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.form_layout = QFormLayout()
|
||||
self.form_layout.setSpacing(10)
|
||||
main_layout.addLayout(self.form_layout)
|
||||
|
||||
_build_ui_recursively(
|
||||
self.form_fields,
|
||||
self.form_layout,
|
||||
self.widget_registry,
|
||||
self.prefix,
|
||||
)
|
||||
|
||||
lookup = search_widgets_by_key(self.widget_registry, "kontaktliste_un_suche")
|
||||
assert len(lookup) == 1
|
||||
self.company_search_input = cast(QLineEdit, lookup[0]["widget"])
|
||||
self.company_search_completer = self.company_search_input.completer()
|
||||
self.company_search_completer.activated[QModelIndex].connect( # type: ignore
|
||||
self._selected_company_on_completer
|
||||
)
|
||||
self.company_search_input.textChanged.connect(self._search_company_change_manually)
|
||||
|
||||
lookup = search_widgets_by_key(self.widget_registry, "kontaktliste_person_suche")
|
||||
assert len(lookup) == 1
|
||||
self.person_search_input = cast(QComboBox, lookup[0]["widget"])
|
||||
self.person_search_input.currentIndexChanged.connect(
|
||||
self._selected_person_on_completer
|
||||
)
|
||||
# self.company_search_completer = self.company_search_input.completer()
|
||||
|
||||
self.company_widgets: dict[str, QWidget] = {}
|
||||
self.person_widgets: dict[str, QWidget] = {}
|
||||
self.properties_company: tuple[str, ...] = (
|
||||
"ma_unternehmensname",
|
||||
"ma_strasse",
|
||||
"ma_hausnummer",
|
||||
"ma_plz",
|
||||
"ma_ort",
|
||||
)
|
||||
self.properties_person: tuple[str, ...] = (
|
||||
"an_titel",
|
||||
"an_anrede",
|
||||
"an_nachname",
|
||||
"an_vorname",
|
||||
"an_festnetz",
|
||||
"an_mobil",
|
||||
"an_mail",
|
||||
"an_position",
|
||||
)
|
||||
|
||||
for entry in self.widget_registry.values():
|
||||
field = entry["form_field"]
|
||||
widget = entry["widget"]
|
||||
|
||||
if field.info in self.properties_company:
|
||||
self.company_widgets[field.info] = widget
|
||||
elif field.info in self.properties_person:
|
||||
self.person_widgets[field.info] = widget
|
||||
|
||||
button = QPushButton("Print Registry")
|
||||
button.clicked.connect(self.print_registry)
|
||||
main_layout.addWidget(button)
|
||||
button = QPushButton("Reset form")
|
||||
button.clicked.connect(self.reset_form)
|
||||
main_layout.addWidget(button)
|
||||
|
||||
self.update_company_data()
|
||||
|
||||
def print_registry(self) -> None:
|
||||
pprint_registry(self.widget_registry)
|
||||
|
||||
def fill_out_company(
|
||||
self,
|
||||
data: be_init_rec.CompanyInfo,
|
||||
) -> None:
|
||||
for key, widget in self.company_widgets.items():
|
||||
if key not in data:
|
||||
raise KeyError(
|
||||
(
|
||||
f"Key: {key} not found in company info. Add the key "
|
||||
f"to the info property in the form field definition"
|
||||
)
|
||||
)
|
||||
set_widget_value(widget, data[key])
|
||||
|
||||
def fill_out_person(
|
||||
self,
|
||||
data: be_init_rec.ContactPersonInfo,
|
||||
) -> None:
|
||||
for key, widget in self.person_widgets.items():
|
||||
if key not in data:
|
||||
raise KeyError(
|
||||
(
|
||||
f"Key: {key} not found in company info. Add the key "
|
||||
f"to the info property in the form field definition"
|
||||
)
|
||||
)
|
||||
set_widget_value(widget, data[key])
|
||||
|
||||
def reset_form(self) -> None:
|
||||
reset_form(self.widget_registry)
|
||||
self._clear_company_fields()
|
||||
self._clear_person_fields()
|
||||
|
||||
def _clear_company_fields(self) -> None:
|
||||
for widget in self.company_widgets.values():
|
||||
widget = cast(QLineEdit, widget)
|
||||
widget.clear()
|
||||
|
||||
def _clear_person_fields(self) -> None:
|
||||
for widget in self.person_widgets.values():
|
||||
widget = cast(QLineEdit, widget)
|
||||
widget.clear()
|
||||
|
||||
def update_company_data(self) -> None:
|
||||
# self.reset_form()
|
||||
self.company_search_input.clear()
|
||||
self._clear_company_fields()
|
||||
search_items = QStandardItemModel()
|
||||
search_choices = be_init_rec.comp_search_choices()
|
||||
for item, db_index in search_choices:
|
||||
qitem = QStandardItem(item)
|
||||
qitem.setData(db_index, Qt.ItemDataRole.UserRole)
|
||||
search_items.appendRow(qitem)
|
||||
|
||||
self.company_search_completer.setModel(search_items)
|
||||
|
||||
def update_person_data(
|
||||
self,
|
||||
ma_id: int | None,
|
||||
) -> None:
|
||||
# self.reset_form()
|
||||
self.person_search_input.clear()
|
||||
self.person_search_input.addItem(DROPDOWN_DEFAULT, None)
|
||||
search_choices = be_init_rec.contact_person_search_choices(ma_id, True)
|
||||
for item, db_index in search_choices:
|
||||
self.person_search_input.addItem(item, db_index)
|
||||
self.person_search_input.setCurrentIndex(0)
|
||||
|
||||
def _selected_company_on_completer(
|
||||
self,
|
||||
index: QModelIndex,
|
||||
) -> None:
|
||||
ma_id = index.data(Qt.ItemDataRole.UserRole)
|
||||
data = be_init_rec.comp_search_get_info(
|
||||
ma_id=ma_id,
|
||||
)
|
||||
self.company_search_input.setProperty(self.PROPERTY_MA_ID, ma_id)
|
||||
self.fill_out_company(data)
|
||||
# self.company_selected.emit(ma_id)
|
||||
self.update_person_data(ma_id)
|
||||
|
||||
def _selected_person_on_completer(
|
||||
self,
|
||||
index: int,
|
||||
) -> None:
|
||||
an_id = self.person_search_input.itemData(index)
|
||||
if an_id is None:
|
||||
self._clear_person_fields()
|
||||
return
|
||||
|
||||
data = be_init_rec.contact_person_search_get_info(
|
||||
an_id=an_id,
|
||||
)
|
||||
self.fill_out_person(data)
|
||||
|
||||
def _search_company_change_manually(
|
||||
self,
|
||||
_: str,
|
||||
) -> None:
|
||||
self.company_search_input.setProperty(self.PROPERTY_MA_ID, -1)
|
||||
|
||||
def get_form_data(self) -> CompanyForm_Search_Data:
|
||||
# TODO decide if value is checked here or later in the Pydantic validation
|
||||
ma_id = self.company_search_input.property(self.PROPERTY_MA_ID)
|
||||
self.export_data["ma_id"] = ma_id
|
||||
|
||||
return self.export_data
|
||||
|
||||
# def set_form_data(
|
||||
# self,
|
||||
# ma_id: int,
|
||||
# ) -> None:
|
||||
# comp_info = be_init_rec.comp_search_get_info(
|
||||
# ma_id=ma_id,
|
||||
# )
|
||||
# self.company_search_input.setText(comp_info["ma_unternehmensname"])
|
||||
# self.fill_out_company(comp_info)
|
||||
|
||||
|
||||
class ContactPersonForm_Search(QWidget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@@ -961,7 +1665,10 @@ class ContactPersonForm_Search(QWidget):
|
||||
|
||||
self.update_search_data(None)
|
||||
|
||||
def fill_out(self, info: be_init_rec.ContactPersonInfo):
|
||||
def fill_out(
|
||||
self,
|
||||
info: be_init_rec.ContactPersonInfo,
|
||||
) -> None:
|
||||
self.gui_titel.setText(info["an_titel"])
|
||||
self.gui_anrede.setText(info["an_anrede"])
|
||||
self.gui_nachname.setText(info["an_nachname"])
|
||||
@@ -996,90 +1703,6 @@ class ContactPersonForm_Search(QWidget):
|
||||
self.search_input.addItem(item, db_index)
|
||||
|
||||
|
||||
class FormFieldType(enum.StrEnum):
|
||||
GROUP = enum.auto()
|
||||
TEXT = enum.auto()
|
||||
LONGTEXT = enum.auto()
|
||||
DATE = enum.auto()
|
||||
DATETIME = enum.auto()
|
||||
DROPDOWN = enum.auto()
|
||||
EXTENDED_DROPDOWN = enum.auto()
|
||||
DYNAMIC_LIST = enum.auto()
|
||||
DYNAMIC_DROPDOWN = enum.auto()
|
||||
|
||||
|
||||
@dc.dataclass(slots=True)
|
||||
class DropdownOption:
|
||||
label: str
|
||||
_data: dc.InitVar[Any | None] = None
|
||||
data: Any = dc.field(init=False)
|
||||
|
||||
def __post_init__(
|
||||
self,
|
||||
_data: Any | None,
|
||||
) -> None:
|
||||
if _data is None:
|
||||
self.data = self.label
|
||||
else:
|
||||
self.data = _data
|
||||
|
||||
|
||||
@dc.dataclass(slots=True)
|
||||
class FormField:
|
||||
label: str
|
||||
type: FormFieldType
|
||||
children: Sequence[FormField] = dc.field(default_factory=list)
|
||||
parent: FormField | None = None
|
||||
required: bool = False
|
||||
placeholder: str = ""
|
||||
fill_value: str = ""
|
||||
readonly: bool = False
|
||||
options: dc.InitVar[Sequence[tuple[str, Any]]] = tuple()
|
||||
dropdown_options: Sequence[DropdownOption] = dc.field(default=tuple(), init=False)
|
||||
key: str = ""
|
||||
tooltip: str = ""
|
||||
init_label: str = dc.field(init=False)
|
||||
|
||||
def __post_init__(
|
||||
self,
|
||||
options: Sequence[tuple[str, Any]],
|
||||
) -> None:
|
||||
if not self.key:
|
||||
self.key = str(uuid.uuid4())
|
||||
|
||||
self.label = self.label.strip()
|
||||
self.init_label = self.label.replace("*", "").replace(":", "")
|
||||
if not self.label.endswith(":") and self.type is not FormFieldType.GROUP:
|
||||
self.label += ":"
|
||||
if self.required:
|
||||
self.label += "*"
|
||||
|
||||
if (
|
||||
self.type in (FormFieldType.DROPDOWN, FormFieldType.EXTENDED_DROPDOWN)
|
||||
and not options
|
||||
):
|
||||
raise ValueError("Invalid field definition: Dropdown requires options")
|
||||
elif self.type in (FormFieldType.DROPDOWN, FormFieldType.EXTENDED_DROPDOWN):
|
||||
self.dropdown_options = tuple(DropdownOption(op[0], op[1]) for op in options)
|
||||
|
||||
if self.children:
|
||||
self.required = any((child.required for child in self.children))
|
||||
for child in self.children:
|
||||
child.parent = self
|
||||
|
||||
def enhanced_label(
|
||||
self,
|
||||
add_text: str,
|
||||
) -> str:
|
||||
enhanced_label = self.init_label + f" {add_text}"
|
||||
if not enhanced_label.endswith(":") and self.type is not FormFieldType.GROUP:
|
||||
enhanced_label += ":"
|
||||
if self.required:
|
||||
enhanced_label += "*"
|
||||
|
||||
return enhanced_label
|
||||
|
||||
|
||||
def enhanced_label(
|
||||
base_label: str,
|
||||
add_text: str,
|
||||
@@ -2560,41 +3183,42 @@ class SearchFormPage(QWidget):
|
||||
container_layout.addSpacing(10)
|
||||
|
||||
# --- SUCHE MIT NAMEN ---
|
||||
self.company_search = CompanyForm_Search()
|
||||
# self.company_search = Grunderfassung_Suche()
|
||||
self.company_search = Grunderfassung_Suche_new(FORM_FIELDS_SEARCH_HEAD)
|
||||
container_layout.addWidget(self.company_search)
|
||||
self.contact_person_search = ContactPersonForm_Search()
|
||||
container_layout.addWidget(self.contact_person_search)
|
||||
hor_layout = QHBoxLayout()
|
||||
label = QLabel("Wie sind Sie auf uns aufmerksam geworden?")
|
||||
combo = QComboBox()
|
||||
combo.addItems(
|
||||
[
|
||||
"--- Bitte wählen ---",
|
||||
"Agentur für Arbeit",
|
||||
"Ausländerbehörde",
|
||||
"Jobcenter",
|
||||
"Freunde/Familie",
|
||||
"Anerkennungsstelle",
|
||||
"Beratungsstelle",
|
||||
"Internet",
|
||||
"Arbeitgeber",
|
||||
"Bildungsdienstleister",
|
||||
"Welcome-Mappe",
|
||||
"Newsletter WFE",
|
||||
"Newsletter RM",
|
||||
"Sonstiges",
|
||||
]
|
||||
)
|
||||
combo.setPlaceholderText("Bitte auswählen")
|
||||
combo.model().item(0).setEnabled(False) # type: ignore
|
||||
hor_layout.addWidget(label)
|
||||
hor_layout.addWidget(combo, stretch=1)
|
||||
container_layout.addLayout(hor_layout)
|
||||
# self.contact_person_search = ContactPersonForm_Search()
|
||||
# container_layout.addWidget(self.contact_person_search)
|
||||
# hor_layout = QHBoxLayout()
|
||||
# label = QLabel("Wie sind Sie auf uns aufmerksam geworden?")
|
||||
# combo = QComboBox()
|
||||
# combo.addItems(
|
||||
# [
|
||||
# "--- Bitte wählen ---",
|
||||
# "Agentur für Arbeit",
|
||||
# "Ausländerbehörde",
|
||||
# "Jobcenter",
|
||||
# "Freunde/Familie",
|
||||
# "Anerkennungsstelle",
|
||||
# "Beratungsstelle",
|
||||
# "Internet",
|
||||
# "Arbeitgeber",
|
||||
# "Bildungsdienstleister",
|
||||
# "Welcome-Mappe",
|
||||
# "Newsletter WFE",
|
||||
# "Newsletter RM",
|
||||
# "Sonstiges",
|
||||
# ]
|
||||
# )
|
||||
# combo.setPlaceholderText("Bitte auswählen")
|
||||
# combo.model().item(0).setEnabled(False) # type: ignore
|
||||
# hor_layout.addWidget(label)
|
||||
# hor_layout.addWidget(combo, stretch=1)
|
||||
# container_layout.addLayout(hor_layout)
|
||||
|
||||
container_layout.addWidget(
|
||||
QLabel('Platzhalter "Wie sind Sie auf uns aufmerksam geworden?"')
|
||||
)
|
||||
self.company_search.company_selected.connect(self.update_contact_persons)
|
||||
# container_layout.addWidget(
|
||||
# QLabel('Platzhalter "Wie sind Sie auf uns aufmerksam geworden?"')
|
||||
# )
|
||||
# self.company_search.company_selected.connect(self.update_contact_persons)
|
||||
|
||||
container_layout.addSpacing(10)
|
||||
|
||||
@@ -2608,11 +3232,11 @@ class SearchFormPage(QWidget):
|
||||
|
||||
container_layout.addSpacing(30)
|
||||
|
||||
def update_contact_persons(
|
||||
self,
|
||||
company_id: int,
|
||||
) -> None:
|
||||
self.contact_person_search.update_search_data(company_id)
|
||||
# def update_contact_persons(
|
||||
# self,
|
||||
# company_id: int,
|
||||
# ) -> None:
|
||||
# self.contact_person_search.update_search_data(company_id)
|
||||
|
||||
|
||||
# 2. Das Hauptfenster mit dem Grid-Layout
|
||||
|
||||
Reference in New Issue
Block a user