made ChoiceQuestions a bit more flexible
This commit is contained in:
parent
f9953a3cbb
commit
025ee52946
3 changed files with 147 additions and 35 deletions
|
@ -12,12 +12,16 @@ class MultipleChoiceQuestion(BaseSurvey):
|
||||||
self,
|
self,
|
||||||
title: str,
|
title: str,
|
||||||
choices: dict[Any, str],
|
choices: dict[Any, str],
|
||||||
other_choice: bool = None,
|
details_choice_enabled: bool = None,
|
||||||
|
details_choice_id: str = None,
|
||||||
|
details_choice_text: str = None,
|
||||||
signals: dict[str, pyqtSignal] = None
|
signals: dict[str, pyqtSignal] = None
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.other_choice = other_choice if other_choice is not None else None
|
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 {}
|
self.signals = signals if signals is not None else {}
|
||||||
|
|
||||||
# set layout
|
# set layout
|
||||||
|
@ -55,11 +59,11 @@ class MultipleChoiceQuestion(BaseSurvey):
|
||||||
# save the button
|
# save the button
|
||||||
self.button_responses[choice_id] = button
|
self.button_responses[choice_id] = button
|
||||||
|
|
||||||
if self.other_choice:
|
if self.details_choice_enabled:
|
||||||
self.button_response_other = QCheckBox()
|
self.button_response_other = QCheckBox()
|
||||||
self._layout_responses.addWidget(self.button_response_other)
|
self._layout_responses.addWidget(self.button_response_other)
|
||||||
self.button_response_other.setText("Autre")
|
self.button_response_other.setText(self.details_choice_text)
|
||||||
self.button_response_other.clicked.connect(self._on_response_other_check) # NOQA: connect exist
|
self.button_response_other.toggled.connect(self._on_response_other_check) # NOQA: connect exist
|
||||||
|
|
||||||
self.entry_response_other = QLineEdit()
|
self.entry_response_other = QLineEdit()
|
||||||
self._layout_responses.addWidget(self.entry_response_other)
|
self._layout_responses.addWidget(self.entry_response_other)
|
||||||
|
@ -70,7 +74,9 @@ class MultipleChoiceQuestion(BaseSurvey):
|
||||||
return cls(
|
return cls(
|
||||||
title=data["title"],
|
title=data["title"],
|
||||||
choices=data["choices"],
|
choices=data["choices"],
|
||||||
other_choice=data.get("other_choice"),
|
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,
|
signals=signals,
|
||||||
)
|
)
|
||||||
|
@ -85,10 +91,16 @@ class MultipleChoiceQuestion(BaseSurvey):
|
||||||
self.entry_response_other.setEnabled(self.button_response_other.isChecked())
|
self.entry_response_other.setEnabled(self.button_response_other.isChecked())
|
||||||
|
|
||||||
def get_collected_data(self) -> dict:
|
def get_collected_data(self) -> dict:
|
||||||
return {
|
collected_data = {
|
||||||
"choice": {choice_id: button.isChecked() for choice_id, button in self.button_responses.items()},
|
"choice": [
|
||||||
"other": (
|
choice_id
|
||||||
self.entry_response_other.text() if self.other_choice and self.button_response_other.isChecked()
|
for choice_id, button in self.button_responses.items()
|
||||||
else None
|
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
|
||||||
|
|
|
@ -2,15 +2,30 @@ from typing import Any
|
||||||
|
|
||||||
from PyQt6.QtCore import Qt, pyqtSignal
|
from PyQt6.QtCore import Qt, pyqtSignal
|
||||||
from PyQt6.QtGui import QFont
|
from PyQt6.QtGui import QFont
|
||||||
from PyQt6.QtWidgets import QFrame, QVBoxLayout, QLabel, QRadioButton, QButtonGroup
|
from PyQt6.QtWidgets import QFrame, QVBoxLayout, QLabel, QRadioButton, QButtonGroup, QLineEdit, QAbstractButton
|
||||||
|
|
||||||
from source.survey.base import BaseSurvey
|
from source.survey.base import BaseSurvey
|
||||||
|
|
||||||
|
|
||||||
class SingleChoiceQuestion(BaseSurvey):
|
class SingleChoiceQuestion(BaseSurvey):
|
||||||
def __init__(self, title: str, choices: dict[Any, str], signals: dict[str, pyqtSignal]):
|
def __init__(
|
||||||
|
self,
|
||||||
|
title: str,
|
||||||
|
details_choice_enabled: bool = None,
|
||||||
|
details_choice_id: str = None,
|
||||||
|
details_choice_text: str = None,
|
||||||
|
choices: dict[Any, str] = None,
|
||||||
|
signals: dict[str, pyqtSignal] = None
|
||||||
|
):
|
||||||
super().__init__()
|
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
|
||||||
|
|
||||||
|
choices = choices if choices is not None else {}
|
||||||
|
signals = signals if signals is not None else {}
|
||||||
|
|
||||||
# set layout
|
# set layout
|
||||||
self._layout = QVBoxLayout()
|
self._layout = QVBoxLayout()
|
||||||
self.setLayout(self._layout)
|
self.setLayout(self._layout)
|
||||||
|
@ -39,7 +54,7 @@ class SingleChoiceQuestion(BaseSurvey):
|
||||||
# checking any button allow the user to go to the next step
|
# checking any button allow the user to go to the next step
|
||||||
self.group_responses.buttonClicked.connect(signals["success"].emit) # NOQA: connect and emit exists
|
self.group_responses.buttonClicked.connect(signals["success"].emit) # NOQA: connect and emit exists
|
||||||
|
|
||||||
self.button_responses_id: dict[QRadioButton, str] = {}
|
self.button_responses_id: dict[QAbstractButton, str] = {}
|
||||||
|
|
||||||
for choice_id, choice_text in choices.items():
|
for choice_id, choice_text in choices.items():
|
||||||
# create a radio button for that choice
|
# create a radio button for that choice
|
||||||
|
@ -53,16 +68,43 @@ class SingleChoiceQuestion(BaseSurvey):
|
||||||
self.group_responses.addButton(button)
|
self.group_responses.addButton(button)
|
||||||
self.button_responses_id[button] = choice_id
|
self.button_responses_id[button] = choice_id
|
||||||
|
|
||||||
|
if self.details_choice_enabled:
|
||||||
|
self.button_response_other = QRadioButton()
|
||||||
|
self._layout_responses.addWidget(self.button_response_other)
|
||||||
|
self.button_responses_id[self.button_response_other] = self.details_choice_id
|
||||||
|
|
||||||
|
self.button_response_other.setText(self.details_choice_text)
|
||||||
|
self.group_responses.addButton(self.button_response_other)
|
||||||
|
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
|
@classmethod
|
||||||
def from_dict(cls, data: dict[str, Any], signals: dict[str, pyqtSignal]) -> "SingleChoiceQuestion":
|
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"],
|
||||||
|
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,
|
signals=signals,
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_collected_data(self) -> dict:
|
def get_collected_data(self) -> dict:
|
||||||
return {
|
checked_button = self.group_responses.checkedButton()
|
||||||
"choice": self.button_responses_id[self.group_responses.checkedButton()]
|
|
||||||
|
collected_data = {
|
||||||
|
"choice": self.button_responses_id[checked_button] if checked_button is not None else None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.details_choice_enabled:
|
||||||
|
collected_data["other"] = self.entry_response_other.text()
|
||||||
|
|
||||||
|
return collected_data
|
||||||
|
|
||||||
|
def _on_response_other_check(self):
|
||||||
|
# refresh the other entry response status
|
||||||
|
self.entry_response_other.setEnabled(self.button_response_other.isChecked())
|
||||||
|
|
94
surveys.json
94
surveys.json
|
@ -1,25 +1,66 @@
|
||||||
{
|
{
|
||||||
"surveys": {
|
"surveys": {
|
||||||
"text-welcome": {
|
|
||||||
|
"welcome": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"title": "Bienvenue !",
|
"title": "Bienvenue !",
|
||||||
"description": "Nous réalisons une étude sur le logiciel Steam afin de déterminer son ergonomie.\nVous serez invité à naviguer sur la plateforme Steam d'une page à l'autre.",
|
"description": "Salut ...",
|
||||||
"abandonable": true
|
"abandonable": true
|
||||||
},
|
},
|
||||||
|
|
||||||
"question-usage": {
|
"age": {
|
||||||
|
"type": "question-integer",
|
||||||
|
"title": "Quel est votre âge ?",
|
||||||
|
"default": 30,
|
||||||
|
"minimum": 13,
|
||||||
|
"maximum": 150
|
||||||
|
},
|
||||||
|
|
||||||
|
"usage-steam": {
|
||||||
"type": "question-single-choice",
|
"type": "question-single-choice",
|
||||||
"title": "A quel point êtes-vous familier avec Steam ?",
|
"title": "Utilisez-vous Steam ?",
|
||||||
"choices": {
|
"choices": {
|
||||||
"0": "Ne connait pas",
|
"always": "Tout le temps",
|
||||||
"1": "Connait de nom",
|
"often": "Souvent",
|
||||||
"2": "Utilisation rare",
|
"sometime": "De temps en temps",
|
||||||
"3": "Utilisation moyenne",
|
"rarely": "Rarement",
|
||||||
"4": "Utilisation fréquente"
|
"never": "Jamais"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"web-language": {
|
"usage-concurrent": {
|
||||||
|
"type": "question-multiple-choice",
|
||||||
|
"title": "Quel autre plateforme de jeu en ligne utilisez-vous ?",
|
||||||
|
"choices": {
|
||||||
|
"epic": "Epic Games Store",
|
||||||
|
"gog": "GOG",
|
||||||
|
"origin": "Origin",
|
||||||
|
"uplay": "Uplay",
|
||||||
|
"battle": "Battle.net"
|
||||||
|
},
|
||||||
|
"details_choice_enabled": true,
|
||||||
|
"details_choice_id": "other",
|
||||||
|
"details_choice_text": "Autre"
|
||||||
|
},
|
||||||
|
|
||||||
|
"difficulty-before": {
|
||||||
|
"type": "question-single-choice",
|
||||||
|
"title": "Avez-vous déjà rencontré des difficultés particulières lors de votre utilisation de Steam ?",
|
||||||
|
"choices": {
|
||||||
|
"no": "Non"
|
||||||
|
},
|
||||||
|
"details_choice_enabled": true,
|
||||||
|
"details_choice_id": "yes",
|
||||||
|
"details_choice_text": "Oui"
|
||||||
|
},
|
||||||
|
|
||||||
|
"mission-explanation": {
|
||||||
|
"type": "text",
|
||||||
|
"title": "Explication de l'Evaluation",
|
||||||
|
"description": "Vous allez devoir naviguer dans steam ..."
|
||||||
|
},
|
||||||
|
|
||||||
|
"mission-language": {
|
||||||
"type": "mission-web",
|
"type": "mission-web",
|
||||||
"title": "Changer la langue en français.",
|
"title": "Changer la langue en français.",
|
||||||
"url": "https://steampowered.com/",
|
"url": "https://steampowered.com/",
|
||||||
|
@ -27,18 +68,35 @@
|
||||||
"skip_time": 60
|
"skip_time": 60
|
||||||
},
|
},
|
||||||
|
|
||||||
"web-point-shop": {
|
|
||||||
"type": "mission-web",
|
|
||||||
"title": "Rendez-vous sur la boutique des points.",
|
|
||||||
"url": "https://steampowered.com/",
|
|
||||||
"check": "true",
|
|
||||||
"skip_time": 90
|
|
||||||
},
|
|
||||||
|
|
||||||
"question-experience": {
|
"question-experience": {
|
||||||
"type": "question-text",
|
"type": "question-text",
|
||||||
"title": "Qu'avez vous pensé de l'interface de Steam ?"
|
"title": "Qu'avez vous pensé de l'interface de Steam ?"
|
||||||
|
},
|
||||||
|
|
||||||
|
"difficulty-after": {
|
||||||
|
"type": "question-single-choice",
|
||||||
|
"title": "Avez-vous rencontré des difficultés particulières lors de ce test ?",
|
||||||
|
"choices": {
|
||||||
|
"no": "Non"
|
||||||
|
},
|
||||||
|
"details_choice_enabled": true,
|
||||||
|
"details_choice_id": "yes",
|
||||||
|
"details_choice_text": "Oui"
|
||||||
|
},
|
||||||
|
|
||||||
|
"hardest-mission": {
|
||||||
|
"type": "question-single-choice",
|
||||||
|
"title": "Parmi les tâches, laquelle avez-vous trouvée la plus difficile ?",
|
||||||
|
"choices": {
|
||||||
|
"mission-language": "Changer la langue"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"comment": {
|
||||||
|
"type": "question-text",
|
||||||
|
"title": "Vous pouvez laisser un commentaire sur votre ressenti général (optionnel)"
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue