from typing import Any from PyQt6.QtCore import Qt, pyqtSignal from PyQt6.QtGui import QFont from PyQt6.QtWidgets import QFrame, QVBoxLayout, QLabel, QCheckBox, QLineEdit import translate from source.survey.base import BaseSurvey class MultipleChoiceQuestion(BaseSurvey): def __init__( self, title: translate.Translatable, choices: dict[Any, translate.Translatable], details_choice_enabled: bool = None, details_choice_id: str = None, details_choice_text: translate.Translatable = None, signals: dict[str, pyqtSignal] = None ): super().__init__() self.details_choice_enabled = details_choice_enabled if details_choice_enabled is not None else None self.details_choice_id = details_choice_id if details_choice_id is not None else None self.details_choice_text = details_choice_text if details_choice_text is not None else None self.signals = signals if signals is not None else {} # set layout self._layout = QVBoxLayout() self.setLayout(self._layout) # question title self.label_question = QLabel() self._layout.addWidget(self.label_question) self.label_question.setText(translate.translate(title)) self.label_question.setAlignment(Qt.AlignmentFlag.AlignCenter) font_title = self.label_question.font() font_title.setPointSize(24) font_title.setWeight(QFont.Weight.Bold) self.label_question.setFont(font_title) # responses self.frame_responses = QFrame() self._layout.addWidget(self.frame_responses) self._layout_responses = QVBoxLayout() self.frame_responses.setLayout(self._layout_responses) self.button_responses: dict[str, QCheckBox] = {} for choice_id, choice_text in choices.items(): # create a radio button for that choice button = QCheckBox() button.setText(translate.translate(choice_text)) # add the button to the frame self._layout_responses.addWidget(button) # save the button self.button_responses[choice_id] = button if self.details_choice_enabled: self.button_response_other = QCheckBox() self._layout_responses.addWidget(self.button_response_other) self.button_response_other.setText(translate.translate(self.details_choice_text)) self.button_response_other.toggled.connect(self._on_response_other_check) # NOQA: connect exist self.entry_response_other = QLineEdit() self._layout_responses.addWidget(self.entry_response_other) self.entry_response_other.setEnabled(False) @classmethod def from_dict(cls, data: dict[str, Any], signals: dict[str, pyqtSignal]) -> "MultipleChoiceQuestion": return cls( title=data["title"], choices=data["choices"], details_choice_enabled=data.get("details_choice_enabled"), details_choice_id=data.get("details_choice_id"), details_choice_text=data.get("details_choice_text"), signals=signals, ) def on_show(self) -> None: if "success" in self.signals: # the user can skip a text whenever he wants to, directly signal a success self.signals["success"].emit() # NOQA: emit exist def _on_response_other_check(self): # refresh the other entry response status self.entry_response_other.setEnabled(self.button_response_other.isChecked()) def get_collected_data(self) -> dict: collected_data = { "choice": [ choice_id for choice_id, button in self.button_responses.items() if button.isChecked() ] } if self.details_choice_enabled: collected_data["choice"].append(self.details_choice_id) collected_data["other"] = self.entry_response_other.text() return collected_data