Source code for betty.gui.model

"""
Provide entity management widgets for the Graphical User Interface.
"""
from __future__ import annotations

from typing import Callable, cast, Iterator

from PyQt6.QtWidgets import QFormLayout, QLabel, QComboBox, QLineEdit, QWidget, QPushButton, QVBoxLayout, QHBoxLayout

from betty.app import App
from betty.gui.locale import LocalizedObject
from betty.locale import Localizable
from betty.model import UserFacingEntity, Entity
from betty.project import EntityReference, EntityReferenceSequence


[docs] class EntityReferenceCollector(LocalizedObject, QWidget): def __init__( self, app: App, entity_reference: EntityReference[UserFacingEntity & Entity], label_builder: Callable[[], str] | None = None, caption_builder: Callable[[], str] | None = None, ): super().__init__(app) self._entity_reference = entity_reference self._label_builder = label_builder self._caption_builder = caption_builder self._layout = QFormLayout() self.setLayout(self._layout) if self._entity_reference.entity_type_is_constrained: self._entity_type_label = QLabel() else: def _update_entity_type() -> None: self._entity_reference.entity_type = self._entity_type.currentData() self._entity_type = QComboBox() self._entity_type.currentIndexChanged.connect(_update_entity_type) entity_types = enumerate(sorted(cast(Iterator[type['UserFacingEntity & Entity']], filter( lambda entity_type: issubclass(entity_type, UserFacingEntity), self._app.entity_types, )), key=lambda entity_type: entity_type.entity_type_label().localize(self._app.localizer))) for i, entity_type in entity_types: self._entity_type.addItem(entity_type.entity_type_label().localize(self._app.localizer), entity_type) if entity_type == self._entity_reference.entity_type: self._entity_type.setCurrentIndex(i) self._entity_type_label = QLabel() self._layout.addRow(self._entity_type_label, self._entity_type) def _update_entity_id() -> None: self._entity_reference.entity_id = self._entity_id.text() self._entity_id = QLineEdit() self._entity_id.textChanged.connect(_update_entity_id) self._entity_id_label = QLabel() self._layout.addRow(self._entity_id_label, self._entity_id) self._set_translatables() def _set_translatables(self) -> None: super()._set_translatables() if self._entity_reference.entity_type: self._entity_id_label.setText(self._app.localizer._('{entity_type_label} ID').format( entity_type_label=self._entity_reference.entity_type.entity_type_label().localize(self._app.localizer), )) else: self._entity_id_label.setText(self._app.localizer._('Entity ID'))
[docs] class EntityReferenceSequenceCollector(LocalizedObject, QWidget): def __init__( self, app: App, entity_references: EntityReferenceSequence[UserFacingEntity & Entity], label_text: Localizable | None = None, caption_text: Localizable | None = None, ): super().__init__(app) self._entity_references = entity_references self._label_text = label_text self._caption_text = caption_text self._entity_reference_collectors: list[EntityReferenceCollector] = [ EntityReferenceCollector(self._app, entity_reference) for entity_reference in entity_references ] self._layout = QVBoxLayout() self.setLayout(self._layout) if label_text: self._label = QLabel() self._layout.addWidget(self._label) self._entity_reference_collectors_widget = QWidget() self._entity_reference_collectors_layout = QVBoxLayout() self._entity_reference_collectors_widget.setLayout(self._entity_reference_collectors_layout) self._layout.addWidget(self._entity_reference_collectors_widget) self._entity_reference_collection_widgets: list[QWidget] = [] self._entity_reference_remove_buttons: list[QPushButton] = [] if caption_text: self._caption = QLabel() self._layout.addWidget(self._caption) self._add_entity_reference_button = QPushButton() self._add_entity_reference_button.released.connect(self._add_entity_reference) self._layout.addWidget(self._add_entity_reference_button) self._build_entity_references_collection() self._set_translatables() def _add_entity_reference(self) -> None: entity_reference = EntityReference['UserFacingEntity & Entity']() self._entity_references.append(entity_reference) self._build_entity_reference_collection(len(self._entity_references) - 1, entity_reference) self._set_translatables() def _remove_entity_reference(self, i: int) -> None: del self._entity_references[i] del self._entity_reference_collectors[i] del self._entity_reference_remove_buttons[i] self._entity_reference_collectors_layout.removeWidget(self._entity_reference_collection_widgets[i]) del self._entity_reference_collection_widgets[i] def _build_entity_references_collection(self) -> None: for i, entity_reference in enumerate(self._entity_references): self._build_entity_reference_collection(i, entity_reference) def _build_entity_reference_collection( self, i: int, entity_reference: EntityReference[UserFacingEntity & Entity], ) -> None: widget = QWidget() layout = QHBoxLayout() widget.setLayout(layout) self._entity_reference_collection_widgets.insert(i, widget) self._entity_reference_collectors_layout.insertWidget(i, widget) entity_reference_collector = EntityReferenceCollector(self._app, entity_reference) self._entity_reference_collectors.append(entity_reference_collector) layout.addWidget(entity_reference_collector) entity_reference_remove_button = QPushButton() self._entity_reference_remove_buttons.insert(i, entity_reference_remove_button) entity_reference_remove_button.released.connect(lambda: self._remove_entity_reference(i)) layout.addWidget(entity_reference_remove_button) def _set_translatables(self) -> None: super()._set_translatables() if self._label_text: self._label.setText(self._label_text.localize(self._app.localizer)) if self._caption_text: self._caption.setText(self._caption_text.localize(self._app.localizer)) self._add_entity_reference_button.setText(self._app.localizer._('Add an entity')) for entity_reference_remove_button in self._entity_reference_remove_buttons: entity_reference_remove_button.setText(self._app.localizer._('Remove'))