Initial commit
This commit is contained in:
commit
b4dff9a2e7
16 changed files with 563 additions and 0 deletions
13
main.py
Normal file
13
main.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import sys
|
||||||
|
from PyQt6.QtWidgets import QApplication
|
||||||
|
|
||||||
|
from source.widget import MyMainWindow
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
application = QApplication(sys.argv)
|
||||||
|
|
||||||
|
window = MyMainWindow()
|
||||||
|
window.show()
|
||||||
|
|
||||||
|
application.exec()
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
PyQt6
|
||||||
|
PyQt6-WebEngine
|
0
source/__init__.py
Normal file
0
source/__init__.py
Normal file
59
source/survey/ChoiceQuestion.py
Normal file
59
source/survey/ChoiceQuestion.py
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from PyQt6.QtCore import Qt, pyqtSignal
|
||||||
|
from PyQt6.QtWidgets import QFrame, QVBoxLayout, QLabel, QRadioButton, QButtonGroup
|
||||||
|
|
||||||
|
from source.survey.base import BaseSurvey
|
||||||
|
|
||||||
|
|
||||||
|
class ChoiceQuestion(BaseSurvey):
|
||||||
|
def __init__(self, title: str, choices: dict[Any, str], signals: dict[str, pyqtSignal]):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# responses
|
||||||
|
self.frame_responses = QFrame()
|
||||||
|
self._layout.addWidget(self.frame_responses)
|
||||||
|
|
||||||
|
self._layout_responses = QVBoxLayout()
|
||||||
|
self.frame_responses.setLayout(self._layout_responses)
|
||||||
|
|
||||||
|
self.group_responses = QButtonGroup()
|
||||||
|
|
||||||
|
if "success" in signals:
|
||||||
|
# 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
|
||||||
|
|
||||||
|
for choice_id, choice_text in choices.items():
|
||||||
|
# create a radio button for that choice
|
||||||
|
button = QRadioButton()
|
||||||
|
button.setText(choice_text)
|
||||||
|
|
||||||
|
# add the button to the frame
|
||||||
|
self._layout_responses.addWidget(button)
|
||||||
|
|
||||||
|
# add the button to the group
|
||||||
|
self.group_responses.addButton(button, int(choice_id))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, data: dict[str, Any], signals: dict[str, pyqtSignal]) -> "ChoiceQuestion":
|
||||||
|
return cls(
|
||||||
|
title=data["title"],
|
||||||
|
choices=data["choices"],
|
||||||
|
|
||||||
|
signals=signals,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_collected_data(self) -> dict:
|
||||||
|
return {
|
||||||
|
"choice": self.group_responses.checkedId()
|
||||||
|
}
|
10
source/survey/Empty.py
Normal file
10
source/survey/Empty.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from PyQt6.QtCore import pyqtSignal
|
||||||
|
from survey.base import BaseSurvey
|
||||||
|
|
||||||
|
|
||||||
|
class Empty(BaseSurvey):
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, data: dict[str, Any], signals: dict[str, pyqtSignal]) -> "BaseSurvey":
|
||||||
|
return Empty()
|
52
source/survey/Text.py
Normal file
52
source/survey/Text.py
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
from typing import Optional, Any
|
||||||
|
|
||||||
|
from PyQt6.QtCore import Qt, pyqtSignal
|
||||||
|
from PyQt6.QtGui import QFont
|
||||||
|
from PyQt6.QtWidgets import QVBoxLayout, QLabel
|
||||||
|
|
||||||
|
from survey.base import BaseSurvey
|
||||||
|
|
||||||
|
|
||||||
|
class Text(BaseSurvey):
|
||||||
|
def __init__(self, title: str, description: Optional[str], signals: dict[str, pyqtSignal]):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.signals = signals
|
||||||
|
|
||||||
|
# set the layout
|
||||||
|
self._layout = QVBoxLayout()
|
||||||
|
self.setLayout(self._layout)
|
||||||
|
|
||||||
|
# prepare the title
|
||||||
|
self.label_title = QLabel()
|
||||||
|
self._layout.addWidget(self.label_title)
|
||||||
|
self.label_title.setText(title)
|
||||||
|
self.label_title.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
|
|
||||||
|
font_title = self.label_title.font()
|
||||||
|
font_title.setPointSize(32)
|
||||||
|
font_title.setWeight(QFont.Weight.Bold)
|
||||||
|
self.label_title.setFont(font_title)
|
||||||
|
|
||||||
|
if description is not None:
|
||||||
|
# prepare the description
|
||||||
|
self.label_description = QLabel()
|
||||||
|
self._layout.addWidget(self.label_description)
|
||||||
|
self.label_description.setText(description)
|
||||||
|
self.label_description.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, data: dict[str, Any], signals: dict[str, pyqtSignal]) -> "Text":
|
||||||
|
return cls(
|
||||||
|
title=data["title"],
|
||||||
|
description=data.get("description"),
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
100
source/survey/WebMission.py
Normal file
100
source/survey/WebMission.py
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
import time
|
||||||
|
from typing import Optional, Any
|
||||||
|
|
||||||
|
from PyQt6.QtCore import Qt, QTimer, pyqtSignal, QUrl
|
||||||
|
from PyQt6.QtGui import QFont
|
||||||
|
from PyQt6.QtWidgets import QLabel, QVBoxLayout, QSizePolicy
|
||||||
|
|
||||||
|
from survey.base import BaseSurvey
|
||||||
|
from source.widget import DecoratedWebEngineView
|
||||||
|
|
||||||
|
|
||||||
|
class WebMission(BaseSurvey):
|
||||||
|
def __init__(self, title: str, url: str, signals: dict[str, pyqtSignal], check_condition: Optional[str] = None):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.check_condition = check_condition
|
||||||
|
self.default_url = url
|
||||||
|
self.signals = signals # TODO: default None ?
|
||||||
|
|
||||||
|
# set layout
|
||||||
|
self._layout = QVBoxLayout()
|
||||||
|
self.setLayout(self._layout)
|
||||||
|
|
||||||
|
# data collection
|
||||||
|
self.initial_time = time.time()
|
||||||
|
self.collect_urls: list[tuple[float, str]] = [] # list of urls that the user went by
|
||||||
|
|
||||||
|
# mission title
|
||||||
|
self.label_title = QLabel()
|
||||||
|
self._layout.addWidget(self.label_title)
|
||||||
|
self.label_title.setText(title)
|
||||||
|
self.label_title.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
|
|
||||||
|
font_title = self.label_title.font()
|
||||||
|
font_title.setPointSize(24)
|
||||||
|
font_title.setWeight(QFont.Weight.Bold)
|
||||||
|
self.label_title.setFont(font_title)
|
||||||
|
|
||||||
|
# web page
|
||||||
|
self.web_view = DecoratedWebEngineView()
|
||||||
|
self._layout.addWidget(self.web_view)
|
||||||
|
self.web_view.urlChanged.connect(self._on_url_changed) # NOQA: connect exist
|
||||||
|
|
||||||
|
self.web_view.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
||||||
|
|
||||||
|
# setup the timer for the check
|
||||||
|
if self.check_condition is not None:
|
||||||
|
self.timer_check = QTimer()
|
||||||
|
self.timer_check.setInterval(1000)
|
||||||
|
self.timer_check.timeout.connect(self.check) # NOQA: connect exist
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, data: dict[str, Any], signals: dict[str, pyqtSignal]) -> "WebMission":
|
||||||
|
return cls(
|
||||||
|
title=data["title"],
|
||||||
|
url=data.get("url"),
|
||||||
|
check_condition=data.get("check"),
|
||||||
|
|
||||||
|
signals=signals
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_show(self) -> None:
|
||||||
|
self.web_view.setUrl(QUrl(self.default_url))
|
||||||
|
|
||||||
|
if self.check_condition is not None:
|
||||||
|
# enable the timer
|
||||||
|
self.timer_check.start()
|
||||||
|
|
||||||
|
else:
|
||||||
|
# call directly the success signal
|
||||||
|
if "success" in self.signals:
|
||||||
|
self.signals["success"].emit() # NOQA: emit exist
|
||||||
|
|
||||||
|
def on_hide(self) -> None:
|
||||||
|
self.timer_check.stop()
|
||||||
|
|
||||||
|
# data collection
|
||||||
|
|
||||||
|
def get_collected_data(self) -> dict:
|
||||||
|
# TODO: more data to collect
|
||||||
|
return {
|
||||||
|
"collect_urls": self.collect_urls
|
||||||
|
}
|
||||||
|
|
||||||
|
def _on_url_changed(self):
|
||||||
|
self.collect_urls.append((time.time() - self.initial_time, self.web_view.url()))
|
||||||
|
|
||||||
|
# condition
|
||||||
|
|
||||||
|
def check(self) -> None:
|
||||||
|
"""
|
||||||
|
Check if the checking condition have been completed
|
||||||
|
"""
|
||||||
|
|
||||||
|
def check_callback(result: bool):
|
||||||
|
if result and "success" in self.signals:
|
||||||
|
self.signals["success"].emit() # NOQA: emit exist
|
||||||
|
|
||||||
|
page = self.web_view.page()
|
||||||
|
page.runJavaScript(self.check_condition, resultCallback=check_callback)
|
6
source/survey/__init__.py
Normal file
6
source/survey/__init__.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
from .Empty import Empty
|
||||||
|
from .Text import Text
|
||||||
|
from .ChoiceQuestion import ChoiceQuestion
|
||||||
|
from .WebMission import WebMission
|
||||||
|
|
||||||
|
from .get import survey_get
|
38
source/survey/base/BaseSurvey.py
Normal file
38
source/survey/base/BaseSurvey.py
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
from abc import abstractmethod
|
||||||
|
from typing import Optional, Any
|
||||||
|
|
||||||
|
from PyQt6.QtCore import pyqtSignal
|
||||||
|
from PyQt6.QtWidgets import QFrame
|
||||||
|
|
||||||
|
|
||||||
|
class BaseSurvey(QFrame):
|
||||||
|
"""
|
||||||
|
A type of survey survey that can be in the user interface
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def from_dict(cls, data: dict[str, Any], signals: dict[str, pyqtSignal]) -> "BaseSurvey":
|
||||||
|
"""
|
||||||
|
Create an instance from a configuration dictionary
|
||||||
|
:return: the instance
|
||||||
|
"""
|
||||||
|
|
||||||
|
def on_show(self) -> None:
|
||||||
|
"""
|
||||||
|
Called when the survey is shown
|
||||||
|
"""
|
||||||
|
|
||||||
|
def on_hide(self) -> None:
|
||||||
|
"""
|
||||||
|
Called when the survey is hidden
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_collected_data(self) -> Optional[dict]:
|
||||||
|
"""
|
||||||
|
Return the data collected for the survey
|
||||||
|
:return: the data collected for the survey
|
||||||
|
"""
|
||||||
|
|
||||||
|
return None
|
1
source/survey/base/__init__.py
Normal file
1
source/survey/base/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from .BaseSurvey import BaseSurvey
|
26
source/survey/get.py
Normal file
26
source/survey/get.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
from typing import Type
|
||||||
|
|
||||||
|
from PyQt6.QtCore import pyqtSignal
|
||||||
|
|
||||||
|
from . import Text, ChoiceQuestion, WebMission, Empty
|
||||||
|
from .base import BaseSurvey
|
||||||
|
|
||||||
|
|
||||||
|
all_survey: dict[str, Type[BaseSurvey]] = {
|
||||||
|
"empty": Empty,
|
||||||
|
"text": Text,
|
||||||
|
"question-choice": ChoiceQuestion,
|
||||||
|
"mission-web": WebMission,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def survey_get(data: dict[str, ...], signals: dict[str, pyqtSignal]) -> BaseSurvey:
|
||||||
|
"""
|
||||||
|
Return a Survey object from the data
|
||||||
|
:param data: the data of the survey
|
||||||
|
:param signals: signal that the survey survey can react to
|
||||||
|
:return: a Survey object
|
||||||
|
"""
|
||||||
|
|
||||||
|
survey_class = all_survey[data["type"]]
|
||||||
|
return survey_class.from_dict(data, signals=signals)
|
93
source/widget/DecoratedWebEngineView.py
Normal file
93
source/widget/DecoratedWebEngineView.py
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from PyQt6.QtCore import QUrl
|
||||||
|
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
||||||
|
from PyQt6.QtWidgets import QVBoxLayout, QWidget, QProgressBar, QFrame, QHBoxLayout, QPushButton, QStyle
|
||||||
|
|
||||||
|
|
||||||
|
class DecoratedWebEngineView(QWidget):
|
||||||
|
"""
|
||||||
|
A version of the QWebEngineView class with integrated progress bar and navigations bar.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, url: Optional[QUrl] = None):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
# layout
|
||||||
|
self._layout = QVBoxLayout()
|
||||||
|
self.setLayout(self._layout)
|
||||||
|
|
||||||
|
# navigation bar
|
||||||
|
self.frame_navigation = QFrame()
|
||||||
|
self._layout.addWidget(self.frame_navigation, 0)
|
||||||
|
self._layout_navigation = QHBoxLayout()
|
||||||
|
self.frame_navigation.setLayout(self._layout_navigation)
|
||||||
|
|
||||||
|
self.button_back = QPushButton()
|
||||||
|
self._layout_navigation.addWidget(self.button_back)
|
||||||
|
self.button_back.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_ArrowBack))
|
||||||
|
|
||||||
|
self.button_reload = QPushButton()
|
||||||
|
self._layout_navigation.addWidget(self.button_reload)
|
||||||
|
self.button_reload.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_BrowserReload))
|
||||||
|
|
||||||
|
self.button_forward = QPushButton()
|
||||||
|
self._layout_navigation.addWidget(self.button_forward)
|
||||||
|
self.button_forward.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_ArrowForward))
|
||||||
|
|
||||||
|
# force the navigation buttons to be on the left by adding a stretching element
|
||||||
|
self._layout_navigation.addStretch(0)
|
||||||
|
|
||||||
|
# web widget
|
||||||
|
self.web_view = QWebEngineView()
|
||||||
|
self._layout.addWidget(self.web_view, 1)
|
||||||
|
|
||||||
|
if url is not None:
|
||||||
|
self.web_view.load(QUrl(url))
|
||||||
|
|
||||||
|
# loading bar
|
||||||
|
self.progress_bar = QProgressBar()
|
||||||
|
self._layout.addWidget(self.progress_bar, 0)
|
||||||
|
self.progress_bar.setFixedHeight(6)
|
||||||
|
self.progress_bar.setTextVisible(False)
|
||||||
|
self.progress_bar.setMaximum(100)
|
||||||
|
self.progress_bar.hide()
|
||||||
|
|
||||||
|
# connect the signals
|
||||||
|
self.web_view.loadStarted.connect(self._load_started) # NOQA: connect exist
|
||||||
|
self.web_view.loadProgress.connect(self._load_progress) # NOQA: connect exist
|
||||||
|
self.web_view.loadFinished.connect(self._load_finished) # NOQA: connect exist
|
||||||
|
|
||||||
|
self.button_back.clicked.connect(self.back) # NOQA: connect exist
|
||||||
|
self.button_reload.clicked.connect(self.reload) # NOQA: connect exist
|
||||||
|
self.button_forward.clicked.connect(self.forward) # NOQA: connect exist
|
||||||
|
|
||||||
|
# finalize the initialisation
|
||||||
|
self.refresh_navigation_actions()
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
# if the member is not found in the class, look in the web view directly
|
||||||
|
return getattr(self.web_view, name)
|
||||||
|
|
||||||
|
# graphical methods
|
||||||
|
|
||||||
|
def _load_started(self):
|
||||||
|
# update the progress bar
|
||||||
|
self.progress_bar.setValue(0)
|
||||||
|
self.progress_bar.show()
|
||||||
|
|
||||||
|
def _load_progress(self, value: int):
|
||||||
|
# update the progress bar
|
||||||
|
self.progress_bar.setValue(value)
|
||||||
|
|
||||||
|
def _load_finished(self):
|
||||||
|
# update the progress bar
|
||||||
|
self.progress_bar.hide()
|
||||||
|
# refresh the navigation buttons
|
||||||
|
self.refresh_navigation_actions()
|
||||||
|
|
||||||
|
def refresh_navigation_actions(self):
|
||||||
|
history = self.web_view.history()
|
||||||
|
# enable the navigation button depending on the history
|
||||||
|
self.button_back.setEnabled(history.canGoBack())
|
||||||
|
self.button_forward.setEnabled(history.canGoForward())
|
117
source/widget/FrameSurvey.py
Normal file
117
source/widget/FrameSurvey.py
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from PyQt6.QtCore import pyqtSignal
|
||||||
|
from PyQt6.QtWidgets import QFrame, QVBoxLayout, QHBoxLayout, QPushButton
|
||||||
|
|
||||||
|
from source.survey.base import BaseSurvey
|
||||||
|
from source.survey import Empty, survey_get
|
||||||
|
|
||||||
|
|
||||||
|
class FrameSurvey(QFrame):
|
||||||
|
signal_success = pyqtSignal()
|
||||||
|
|
||||||
|
def __init__(self, survey_path: Path | str):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
# signals
|
||||||
|
self.signal_success.connect(self._on_signal_success) # NOQA: connect exist
|
||||||
|
|
||||||
|
# prepare the survey screen data
|
||||||
|
self.survey_screens: list[tuple[str, BaseSurvey]] = []
|
||||||
|
self.current_survey_index = 0
|
||||||
|
|
||||||
|
# prepare the survey collected data
|
||||||
|
self.collected_datas: dict[str, dict] = {}
|
||||||
|
|
||||||
|
# set the layout
|
||||||
|
self._layout = QVBoxLayout()
|
||||||
|
self.setLayout(self._layout)
|
||||||
|
|
||||||
|
# prepare the frame for the survey elements
|
||||||
|
self.frame_survey: BaseSurvey = Empty()
|
||||||
|
self._layout.addWidget(self.frame_survey)
|
||||||
|
|
||||||
|
# navigations actions
|
||||||
|
self.frame_navigation = QFrame()
|
||||||
|
self._layout.addWidget(self.frame_navigation)
|
||||||
|
|
||||||
|
self._layout_navigation = QHBoxLayout()
|
||||||
|
self.frame_navigation.setLayout(self._layout_navigation)
|
||||||
|
|
||||||
|
self._layout_navigation.addStretch(0)
|
||||||
|
|
||||||
|
self.button_forward = QPushButton()
|
||||||
|
self._layout_navigation.addWidget(self.button_forward)
|
||||||
|
self.button_forward.setText("Suivant")
|
||||||
|
self.button_forward.clicked.connect(self.next_survey) # NOQA: connect exist
|
||||||
|
|
||||||
|
# load the survey configuration file
|
||||||
|
self.load_file(survey_path)
|
||||||
|
|
||||||
|
# finalize the initialisation
|
||||||
|
self.update_survey()
|
||||||
|
|
||||||
|
def _on_signal_success(self):
|
||||||
|
# on success, show the button to go forward
|
||||||
|
self.button_forward.show()
|
||||||
|
|
||||||
|
def load_file(self, survey_path: Path | str):
|
||||||
|
# load the surveys screens
|
||||||
|
with open(survey_path) as file:
|
||||||
|
surveys_data = json.load(file)
|
||||||
|
|
||||||
|
self.survey_screens = [
|
||||||
|
(
|
||||||
|
survey_id,
|
||||||
|
survey_get(
|
||||||
|
survey_data,
|
||||||
|
signals={"success": self.signal_success}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for survey_id, survey_data in surveys_data.items()
|
||||||
|
]
|
||||||
|
self.current_survey_index = 0
|
||||||
|
|
||||||
|
def next_survey(self):
|
||||||
|
# get the collected data from the survey
|
||||||
|
collected_data = self.frame_survey.get_collected_data()
|
||||||
|
if collected_data is not None:
|
||||||
|
# if there is data, get the current survey id
|
||||||
|
survey_id, survey = self.survey_screens[self.current_survey_index]
|
||||||
|
# save the response in the data
|
||||||
|
self.collected_datas[survey_id] = collected_data
|
||||||
|
|
||||||
|
print(collected_data)
|
||||||
|
|
||||||
|
self.current_survey_index += 1
|
||||||
|
|
||||||
|
if self.current_survey_index < len(self.survey_screens):
|
||||||
|
self.update_survey()
|
||||||
|
else:
|
||||||
|
self.finish_survey()
|
||||||
|
|
||||||
|
def update_survey(self):
|
||||||
|
# disable the forward button
|
||||||
|
self.button_forward.hide()
|
||||||
|
|
||||||
|
# mark the actual survey as the old one
|
||||||
|
old_frame_survey = self.frame_survey
|
||||||
|
# call the old survey event
|
||||||
|
old_frame_survey.on_hide()
|
||||||
|
# get the currently selected survey
|
||||||
|
survey_id, survey = self.survey_screens[self.current_survey_index]
|
||||||
|
# update it to the new one
|
||||||
|
self.frame_survey = survey
|
||||||
|
# change the widget on the layout
|
||||||
|
self._layout.replaceWidget(old_frame_survey, self.frame_survey)
|
||||||
|
# call the new survey event
|
||||||
|
survey.on_show()
|
||||||
|
# delete the old frame
|
||||||
|
old_frame_survey.deleteLater()
|
||||||
|
|
||||||
|
def finish_survey(self):
|
||||||
|
# TODO: send the collected data as a file somewhere
|
||||||
|
print(self.collected_datas)
|
||||||
|
|
||||||
|
self.window().close()
|
10
source/widget/MyMainWindow.py
Normal file
10
source/widget/MyMainWindow.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from PyQt6.QtWidgets import QMainWindow
|
||||||
|
|
||||||
|
from source import widget
|
||||||
|
|
||||||
|
|
||||||
|
class MyMainWindow(QMainWindow):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.setCentralWidget(widget.FrameSurvey("./surveys.json"))
|
3
source/widget/__init__.py
Normal file
3
source/widget/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from .DecoratedWebEngineView import DecoratedWebEngineView
|
||||||
|
from .FrameSurvey import FrameSurvey
|
||||||
|
from .MyMainWindow import MyMainWindow
|
33
surveys.json
Normal file
33
surveys.json
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"text-welcome": {
|
||||||
|
"type": "text",
|
||||||
|
"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."
|
||||||
|
},
|
||||||
|
|
||||||
|
"question-usage": {
|
||||||
|
"type": "question-choice",
|
||||||
|
"title": "A quel point êtes-vous familier avec Steam ?",
|
||||||
|
"choices": {
|
||||||
|
"0": "Ne connait pas",
|
||||||
|
"1": "Connait de nom",
|
||||||
|
"2": "Utilisation rare",
|
||||||
|
"3": "Utilisation moyenne",
|
||||||
|
"4": "Utilisation fréquente"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"web-language": {
|
||||||
|
"type": "mission-web",
|
||||||
|
"title": "Changer la langue en français.",
|
||||||
|
"url": "https://steampowered.com/",
|
||||||
|
"check": "document.getElementsByTagName('html')[0].lang == 'fr'"
|
||||||
|
},
|
||||||
|
|
||||||
|
"web-point-shop": {
|
||||||
|
"type": "mission-web",
|
||||||
|
"title": "Rendez-vous sur la boutique des points.",
|
||||||
|
"url": "https://steampowered.com/",
|
||||||
|
"check": "true"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue