added MultipleChoiceQuestion and IntegerQuestion
This commit is contained in:
parent
445be46cd9
commit
660669ea89
8 changed files with 162 additions and 15 deletions
57
source/survey/IntegerQuestion.py
Normal file
57
source/survey/IntegerQuestion.py
Normal file
|
@ -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()
|
||||||
|
}
|
94
source/survey/MultipleChoiceQuestion.py
Normal file
94
source/survey/MultipleChoiceQuestion.py
Normal file
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ from PyQt6.QtWidgets import QFrame, QVBoxLayout, QLabel, QRadioButton, QButtonGr
|
||||||
from source.survey.base import BaseSurvey
|
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]):
|
def __init__(self, title: str, choices: dict[Any, str], signals: dict[str, pyqtSignal]):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ class ChoiceQuestion(BaseSurvey):
|
||||||
self.group_responses.addButton(button, int(choice_id))
|
self.group_responses.addButton(button, int(choice_id))
|
||||||
|
|
||||||
@classmethod
|
@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(
|
return cls(
|
||||||
title=data["title"],
|
title=data["title"],
|
||||||
choices=data["choices"],
|
choices=data["choices"],
|
|
@ -1,7 +1,9 @@
|
||||||
from .Empty import Empty
|
from .Empty import Empty
|
||||||
from .Text import Text
|
from .Text import Text
|
||||||
from .ChoiceQuestion import ChoiceQuestion
|
from .SingleChoiceQuestion import SingleChoiceQuestion
|
||||||
|
from .MultipleChoiceQuestion import MultipleChoiceQuestion
|
||||||
from .TextQuestion import TextQuestion
|
from .TextQuestion import TextQuestion
|
||||||
|
from .IntegerQuestion import IntegerQuestion
|
||||||
from .WebMission import WebMission
|
from .WebMission import WebMission
|
||||||
|
|
||||||
from .get import survey_get
|
from .get import survey_get
|
||||||
|
|
|
@ -2,7 +2,7 @@ from typing import Type
|
||||||
|
|
||||||
from PyQt6.QtCore import pyqtSignal
|
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
|
from .base import BaseSurvey
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,8 +11,10 @@ all_survey: dict[str, Type[BaseSurvey]] = {
|
||||||
"empty": Empty,
|
"empty": Empty,
|
||||||
"text": Text,
|
"text": Text,
|
||||||
# questions
|
# questions
|
||||||
"question-choice": ChoiceQuestion,
|
"question-single-choice": SingleChoiceQuestion,
|
||||||
|
"question-multiple-choice": MultipleChoiceQuestion,
|
||||||
"question-text": TextQuestion,
|
"question-text": TextQuestion,
|
||||||
|
"question-integer": IntegerQuestion,
|
||||||
# missions
|
# missions
|
||||||
"mission-web": WebMission,
|
"mission-web": WebMission,
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,6 @@ class FrameSurvey(QFrame):
|
||||||
self.signal_success.connect(self._on_signal_success) # NOQA: connect exist
|
self.signal_success.connect(self._on_signal_success) # NOQA: connect exist
|
||||||
|
|
||||||
# prepare the survey collected data
|
# 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.collected_datas: dict[str, dict] = {"time": time.time(), "surveys": {}}
|
||||||
self.survey_screens: list[tuple[str, BaseSurvey]] = []
|
self.survey_screens: list[tuple[str, BaseSurvey]] = []
|
||||||
self.current_survey_index = 0
|
self.current_survey_index = 0
|
||||||
|
@ -91,9 +89,6 @@ class FrameSurvey(QFrame):
|
||||||
with open(survey_path, encoding="utf-8") as file:
|
with open(survey_path, encoding="utf-8") as file:
|
||||||
surveys_data = json.load(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 = [
|
self.survey_screens = [
|
||||||
(
|
(
|
||||||
survey_id,
|
survey_id,
|
||||||
|
|
|
@ -12,6 +12,6 @@ class MyMainWindow(QMainWindow):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.setWindowIcon(QIcon(str(icon_path.resolve())))
|
self.setWindowIcon(QIcon(str(icon_path.resolve())))
|
||||||
self.setWindowTitle("Sondage - Steam")
|
self.setWindowTitle("Sondage")
|
||||||
|
|
||||||
self.setCentralWidget(widget.FrameSurvey("./surveys.json"))
|
self.setCentralWidget(widget.FrameSurvey("./surveys.json"))
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
{
|
{
|
||||||
"name": "steam-navigation",
|
|
||||||
"collected_data_url": "http://127.0.0.1:8000/rest/university/recherche/survey/",
|
|
||||||
|
|
||||||
"surveys": {
|
"surveys": {
|
||||||
"text-welcome": {
|
"text-welcome": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
@ -11,7 +8,7 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
"question-usage": {
|
"question-usage": {
|
||||||
"type": "question-choice",
|
"type": "question-single-choice",
|
||||||
"title": "A quel point êtes-vous familier avec Steam ?",
|
"title": "A quel point êtes-vous familier avec Steam ?",
|
||||||
"choices": {
|
"choices": {
|
||||||
"0": "Ne connait pas",
|
"0": "Ne connait pas",
|
||||||
|
|
Loading…
Reference in a new issue