M1-Survey-Engine/source/survey/MultipleChoiceQuestion.py

107 lines
4 KiB
Python

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