diff --git a/source/survey/IntegerQuestion.py b/source/survey/IntegerQuestion.py new file mode 100644 index 0000000..2fff1b2 --- /dev/null +++ b/source/survey/IntegerQuestion.py @@ -0,0 +1,57 @@ +from typing import Any + +from PyQt6.QtCore import Qt, pyqtSignal +from PyQt6.QtGui import QFont, QIntValidator +from PyQt6.QtWidgets import QVBoxLayout, QLabel, QDoubleSpinBox, QSpinBox + +from source.survey.base import BaseSurvey + + +class IntegerQuestion(BaseSurvey): + def __init__(self, title: str, signals: dict[str, pyqtSignal] = None): + super().__init__() + + 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(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) + + # response + self.entry_response = QSpinBox() + self.entry_response.setMinimum(13) + self.entry_response.setMaximum(200) + self.entry_response.setValue(30) + self._layout.addWidget(self.entry_response) + + @classmethod + def from_dict(cls, data: dict[str, Any], signals: dict[str, pyqtSignal]) -> "IntegerQuestion": + return cls( + title=data["title"], + signals=signals, + ) + + # events + + def on_show(self) -> None: + # immediately mark the survey as successful + if "success" in self.signals: + self.signals["success"].emit() # NOQA: emit exist + + # data collection + + def get_collected_data(self) -> dict: + return { + "value": self.entry_response.value() + } diff --git a/source/survey/MultipleChoiceQuestion.py b/source/survey/MultipleChoiceQuestion.py new file mode 100644 index 0000000..7574ffa --- /dev/null +++ b/source/survey/MultipleChoiceQuestion.py @@ -0,0 +1,94 @@ +from typing import Any + +from PyQt6.QtCore import Qt, pyqtSignal +from PyQt6.QtGui import QFont +from PyQt6.QtWidgets import QFrame, QVBoxLayout, QLabel, QCheckBox, QLineEdit + +from source.survey.base import BaseSurvey + + +class MultipleChoiceQuestion(BaseSurvey): + def __init__( + self, + title: str, + choices: dict[Any, str], + other_choice: bool = None, + signals: dict[str, pyqtSignal] = None + ): + super().__init__() + + self.other_choice = other_choice if other_choice 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(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(choice_text) + + # add the button to the frame + self._layout_responses.addWidget(button) + + # save the button + self.button_responses[choice_id] = button + + if self.other_choice: + self.button_response_other = QCheckBox() + self._layout_responses.addWidget(self.button_response_other) + self.button_response_other.setText("Autre") + self.button_response_other.clicked.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"], + other_choice=data.get("other_choice"), + + 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: + return { + "choice": {choice_id: button.isChecked() for choice_id, button in self.button_responses.items()}, + "other": ( + self.entry_response_other.text() if self.other_choice and self.button_response_other.isChecked() + else None + ) + } diff --git a/source/survey/ChoiceQuestion.py b/source/survey/SingleChoiceQuestion.py similarity index 96% rename from source/survey/ChoiceQuestion.py rename to source/survey/SingleChoiceQuestion.py index 2a6252f..3ce0cec 100644 --- a/source/survey/ChoiceQuestion.py +++ b/source/survey/SingleChoiceQuestion.py @@ -7,7 +7,7 @@ from PyQt6.QtWidgets import QFrame, QVBoxLayout, QLabel, QRadioButton, QButtonGr from source.survey.base import BaseSurvey -class ChoiceQuestion(BaseSurvey): +class SingleChoiceQuestion(BaseSurvey): def __init__(self, title: str, choices: dict[Any, str], signals: dict[str, pyqtSignal]): super().__init__() @@ -51,7 +51,7 @@ class ChoiceQuestion(BaseSurvey): self.group_responses.addButton(button, int(choice_id)) @classmethod - def from_dict(cls, data: dict[str, Any], signals: dict[str, pyqtSignal]) -> "ChoiceQuestion": + def from_dict(cls, data: dict[str, Any], signals: dict[str, pyqtSignal]) -> "SingleChoiceQuestion": return cls( title=data["title"], choices=data["choices"], diff --git a/source/survey/__init__.py b/source/survey/__init__.py index 101a815..04a77b3 100644 --- a/source/survey/__init__.py +++ b/source/survey/__init__.py @@ -1,7 +1,9 @@ from .Empty import Empty from .Text import Text -from .ChoiceQuestion import ChoiceQuestion +from .SingleChoiceQuestion import SingleChoiceQuestion +from .MultipleChoiceQuestion import MultipleChoiceQuestion from .TextQuestion import TextQuestion +from .IntegerQuestion import IntegerQuestion from .WebMission import WebMission from .get import survey_get diff --git a/source/survey/get.py b/source/survey/get.py index 3590da6..9a60f66 100644 --- a/source/survey/get.py +++ b/source/survey/get.py @@ -2,7 +2,7 @@ from typing import Type from PyQt6.QtCore import pyqtSignal -from . import Text, ChoiceQuestion, WebMission, Empty, TextQuestion +from . import Text, SingleChoiceQuestion, MultipleChoiceQuestion, WebMission, Empty, TextQuestion, IntegerQuestion from .base import BaseSurvey @@ -11,8 +11,10 @@ all_survey: dict[str, Type[BaseSurvey]] = { "empty": Empty, "text": Text, # questions - "question-choice": ChoiceQuestion, + "question-single-choice": SingleChoiceQuestion, + "question-multiple-choice": MultipleChoiceQuestion, "question-text": TextQuestion, + "question-integer": IntegerQuestion, # missions "mission-web": WebMission, } diff --git a/source/widget/FrameSurvey.py b/source/widget/FrameSurvey.py index 62a325d..fcc0222 100644 --- a/source/widget/FrameSurvey.py +++ b/source/widget/FrameSurvey.py @@ -29,8 +29,6 @@ class FrameSurvey(QFrame): self.signal_success.connect(self._on_signal_success) # NOQA: connect exist # prepare the survey collected data - self.survey_name = None - self.collected_data_url = None self.collected_datas: dict[str, dict] = {"time": time.time(), "surveys": {}} self.survey_screens: list[tuple[str, BaseSurvey]] = [] self.current_survey_index = 0 @@ -91,9 +89,6 @@ class FrameSurvey(QFrame): with open(survey_path, encoding="utf-8") as file: surveys_data = json.load(file) - self.survey_name = surveys_data.get("name") - self.collected_data_url = surveys_data.get("collected_data_url") - self.survey_screens = [ ( survey_id, diff --git a/source/widget/MyMainWindow.py b/source/widget/MyMainWindow.py index 36a9e84..47fccc7 100644 --- a/source/widget/MyMainWindow.py +++ b/source/widget/MyMainWindow.py @@ -12,6 +12,6 @@ class MyMainWindow(QMainWindow): super().__init__() self.setWindowIcon(QIcon(str(icon_path.resolve()))) - self.setWindowTitle("Sondage - Steam") + self.setWindowTitle("Sondage") self.setCentralWidget(widget.FrameSurvey("./surveys.json")) diff --git a/surveys.json b/surveys.json index a7167d3..a14d2cd 100644 --- a/surveys.json +++ b/surveys.json @@ -1,7 +1,4 @@ { - "name": "steam-navigation", - "collected_data_url": "http://127.0.0.1:8000/rest/university/recherche/survey/", - "surveys": { "text-welcome": { "type": "text", @@ -11,7 +8,7 @@ }, "question-usage": { - "type": "question-choice", + "type": "question-single-choice", "title": "A quel point ĂȘtes-vous familier avec Steam ?", "choices": { "0": "Ne connait pas",