added Browser tracking and TextQuestion type
This commit is contained in:
parent
13246538fc
commit
a44e61b83e
12 changed files with 270 additions and 124 deletions
|
@ -1,6 +1,7 @@
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from PyQt6.QtCore import Qt, pyqtSignal
|
from PyQt6.QtCore import Qt, pyqtSignal
|
||||||
|
from PyQt6.QtGui import QFont
|
||||||
from PyQt6.QtWidgets import QFrame, QVBoxLayout, QLabel, QRadioButton, QButtonGroup
|
from PyQt6.QtWidgets import QFrame, QVBoxLayout, QLabel, QRadioButton, QButtonGroup
|
||||||
|
|
||||||
from source.survey.base import BaseSurvey
|
from source.survey.base import BaseSurvey
|
||||||
|
@ -20,6 +21,11 @@ class ChoiceQuestion(BaseSurvey):
|
||||||
self.label_question.setText(title)
|
self.label_question.setText(title)
|
||||||
self.label_question.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
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
|
# responses
|
||||||
self.frame_responses = QFrame()
|
self.frame_responses = QFrame()
|
||||||
self._layout.addWidget(self.frame_responses)
|
self._layout.addWidget(self.frame_responses)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from PyQt6.QtCore import pyqtSignal
|
from PyQt6.QtCore import pyqtSignal
|
||||||
from survey.base import BaseSurvey
|
from source.survey.base import BaseSurvey
|
||||||
|
|
||||||
|
|
||||||
class Empty(BaseSurvey):
|
class Empty(BaseSurvey):
|
||||||
|
|
|
@ -4,7 +4,7 @@ from PyQt6.QtCore import Qt, pyqtSignal
|
||||||
from PyQt6.QtGui import QFont
|
from PyQt6.QtGui import QFont
|
||||||
from PyQt6.QtWidgets import QVBoxLayout, QLabel
|
from PyQt6.QtWidgets import QVBoxLayout, QLabel
|
||||||
|
|
||||||
from survey.base import BaseSurvey
|
from source.survey.base import BaseSurvey
|
||||||
|
|
||||||
|
|
||||||
class Text(BaseSurvey):
|
class Text(BaseSurvey):
|
||||||
|
|
54
source/survey/TextQuestion.py
Normal file
54
source/survey/TextQuestion.py
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from PyQt6.QtCore import Qt, pyqtSignal
|
||||||
|
from PyQt6.QtGui import QFont
|
||||||
|
from PyQt6.QtWidgets import QFrame, QVBoxLayout, QLabel, QRadioButton, QButtonGroup, QTextEdit
|
||||||
|
|
||||||
|
from source.survey.base import BaseSurvey
|
||||||
|
|
||||||
|
|
||||||
|
class TextQuestion(BaseSurvey):
|
||||||
|
def __init__(self, title: str, signals: dict[str, pyqtSignal]):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.signals = signals
|
||||||
|
|
||||||
|
# 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 = QTextEdit()
|
||||||
|
self._layout.addWidget(self.entry_response)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, data: dict[str, Any], signals: dict[str, pyqtSignal]) -> "TextQuestion":
|
||||||
|
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 {
|
||||||
|
"choice": self.entry_response.toPlainText()
|
||||||
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
import time
|
import time
|
||||||
from typing import Optional, Any
|
from typing import Optional, Any
|
||||||
|
|
||||||
from PyQt6.QtCore import Qt, QTimer, pyqtSignal, QUrl
|
from PyQt6.QtCore import Qt, QTimer, pyqtSignal, QUrl, QEvent, QObject
|
||||||
from PyQt6.QtGui import QFont
|
from PyQt6.QtGui import QFont, QMouseEvent, QResizeEvent
|
||||||
from PyQt6.QtWidgets import QLabel, QVBoxLayout, QSizePolicy
|
from PyQt6.QtWidgets import QLabel, QVBoxLayout, QSizePolicy
|
||||||
|
|
||||||
from survey.base import BaseSurvey
|
from source.survey.base import BaseSurvey
|
||||||
from source.widget import DecoratedWebEngineView
|
from source.widget import Browser
|
||||||
|
|
||||||
|
|
||||||
class WebMission(BaseSurvey):
|
class WebMission(BaseSurvey):
|
||||||
|
@ -15,15 +15,15 @@ class WebMission(BaseSurvey):
|
||||||
|
|
||||||
self.check_condition = check_condition
|
self.check_condition = check_condition
|
||||||
self.default_url = url
|
self.default_url = url
|
||||||
self.signals = signals # TODO: default None ?
|
self.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)
|
||||||
|
|
||||||
# data collection
|
# data collection
|
||||||
self.initial_time = time.time()
|
self.start_time = time.time()
|
||||||
self.collect_urls: list[tuple[float, str]] = [] # list of urls that the user went by
|
self._collected_events: list[dict[str, Any]] = []
|
||||||
|
|
||||||
# mission title
|
# mission title
|
||||||
self.label_title = QLabel()
|
self.label_title = QLabel()
|
||||||
|
@ -37,11 +37,12 @@ class WebMission(BaseSurvey):
|
||||||
self.label_title.setFont(font_title)
|
self.label_title.setFont(font_title)
|
||||||
|
|
||||||
# web page
|
# web page
|
||||||
self.web_view = DecoratedWebEngineView()
|
self.browser = Browser()
|
||||||
self._layout.addWidget(self.web_view)
|
self._layout.addWidget(self.browser)
|
||||||
self.web_view.urlChanged.connect(self._on_url_changed) # NOQA: connect exist
|
self.browser.web.focusProxy().installEventFilter(self) # capture the event in eventFilter
|
||||||
|
self.browser.web.urlChanged.connect(self._on_url_changed) # NOQA: connect exist
|
||||||
|
|
||||||
self.web_view.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
self.browser.web.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
||||||
|
|
||||||
# setup the timer for the check
|
# setup the timer for the check
|
||||||
if self.check_condition is not None:
|
if self.check_condition is not None:
|
||||||
|
@ -59,31 +60,92 @@ class WebMission(BaseSurvey):
|
||||||
signals=signals
|
signals=signals
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# events
|
||||||
|
|
||||||
|
def eventFilter(self, obj: QObject, event: QEvent) -> bool:
|
||||||
|
if obj is self.browser.web.focusProxy():
|
||||||
|
# if the object is the content of the web engine widget
|
||||||
|
match event.type():
|
||||||
|
case QEvent.Type.MouseMove:
|
||||||
|
# if this is a mouse movement
|
||||||
|
event: QMouseEvent
|
||||||
|
position = event.position()
|
||||||
|
|
||||||
|
self._save_event(
|
||||||
|
type="mouse_move",
|
||||||
|
position=(position.x(), position.y())
|
||||||
|
)
|
||||||
|
|
||||||
|
case QEvent.Type.MouseButtonPress:
|
||||||
|
# if this is a mouse click press
|
||||||
|
event: QMouseEvent
|
||||||
|
position = event.position()
|
||||||
|
|
||||||
|
self._save_event(
|
||||||
|
type="mouse_press",
|
||||||
|
position=(position.x(), position.y()),
|
||||||
|
button=event.button(),
|
||||||
|
)
|
||||||
|
|
||||||
|
case QEvent.Type.MouseButtonRelease:
|
||||||
|
# if this is a mouse click release
|
||||||
|
event: QMouseEvent
|
||||||
|
position = event.position()
|
||||||
|
|
||||||
|
self._save_event(
|
||||||
|
type="mouse_release",
|
||||||
|
position=(position.x(), position.y()),
|
||||||
|
button=event.button(),
|
||||||
|
)
|
||||||
|
|
||||||
|
case QEvent.Type.MouseButtonDblClick:
|
||||||
|
# if this is a mouse double click
|
||||||
|
event: QMouseEvent
|
||||||
|
position = event.position()
|
||||||
|
|
||||||
|
self._save_event(
|
||||||
|
type="mouse_double_click",
|
||||||
|
position=(position.x(), position.y()),
|
||||||
|
)
|
||||||
|
|
||||||
|
case QEvent.Type.Resize:
|
||||||
|
# if the window got resized
|
||||||
|
event: QResizeEvent
|
||||||
|
size = event.size()
|
||||||
|
|
||||||
|
self._save_event(
|
||||||
|
type="resize",
|
||||||
|
size=(size.width(), size.height()),
|
||||||
|
)
|
||||||
|
|
||||||
|
return super().eventFilter(obj, event)
|
||||||
|
|
||||||
def on_show(self) -> None:
|
def on_show(self) -> None:
|
||||||
self.web_view.setUrl(QUrl(self.default_url))
|
# initialize the start time
|
||||||
|
self.start_time = time.time()
|
||||||
|
|
||||||
|
# set the web view to the default url
|
||||||
|
self.browser.web.setUrl(QUrl(self.default_url))
|
||||||
|
|
||||||
if self.check_condition is not None:
|
if self.check_condition is not None:
|
||||||
# enable the timer
|
# enable the timer
|
||||||
self.timer_check.start()
|
self.timer_check.start()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# call directly the success signal
|
self._success() # call directly the success method
|
||||||
if "success" in self.signals:
|
|
||||||
self.signals["success"].emit() # NOQA: emit exist
|
|
||||||
|
|
||||||
def on_hide(self) -> None:
|
def on_hide(self) -> None:
|
||||||
self.timer_check.stop()
|
self.timer_check.stop()
|
||||||
|
|
||||||
# data collection
|
def _success(self):
|
||||||
|
# TODO: animation or notification to clearly mark mission as succeeded
|
||||||
|
|
||||||
def get_collected_data(self) -> dict:
|
# mark the success in the events
|
||||||
# TODO: more data to collect
|
self._save_event(type="check")
|
||||||
return {
|
|
||||||
"collect_urls": self.collect_urls
|
|
||||||
}
|
|
||||||
|
|
||||||
def _on_url_changed(self):
|
# emit on the success signal
|
||||||
self.collect_urls.append((time.time() - self.initial_time, self.web_view.url()))
|
if "success" in self.signals:
|
||||||
|
self.signals["success"].emit() # NOQA: emit exist
|
||||||
|
|
||||||
# condition
|
# condition
|
||||||
|
|
||||||
|
@ -93,8 +155,27 @@ class WebMission(BaseSurvey):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def check_callback(result: bool):
|
def check_callback(result: bool):
|
||||||
if result and "success" in self.signals:
|
if result:
|
||||||
self.signals["success"].emit() # NOQA: emit exist
|
self._success()
|
||||||
|
|
||||||
page = self.web_view.page()
|
page = self.browser.web.page()
|
||||||
page.runJavaScript(self.check_condition, resultCallback=check_callback)
|
page.runJavaScript(self.check_condition, resultCallback=check_callback)
|
||||||
|
|
||||||
|
# data collection
|
||||||
|
|
||||||
|
def _save_event(self, **data) -> None:
|
||||||
|
# save the data of the event and add the current time
|
||||||
|
data["time"] = round(time.time() - self.start_time, 3)
|
||||||
|
self._collected_events.append(data)
|
||||||
|
|
||||||
|
def get_collected_data(self) -> dict:
|
||||||
|
return {
|
||||||
|
"event": self._collected_events,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _on_url_changed(self):
|
||||||
|
# log the new url
|
||||||
|
self._save_event(
|
||||||
|
type="url",
|
||||||
|
url=self.browser.web.url().toString()
|
||||||
|
)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from .Empty import Empty
|
from .Empty import Empty
|
||||||
from .Text import Text
|
from .Text import Text
|
||||||
from .ChoiceQuestion import ChoiceQuestion
|
from .ChoiceQuestion import ChoiceQuestion
|
||||||
|
from .TextQuestion import TextQuestion
|
||||||
from .WebMission import WebMission
|
from .WebMission import WebMission
|
||||||
|
|
||||||
from .get import survey_get
|
from .get import survey_get
|
||||||
|
|
|
@ -2,14 +2,18 @@ from typing import Type
|
||||||
|
|
||||||
from PyQt6.QtCore import pyqtSignal
|
from PyQt6.QtCore import pyqtSignal
|
||||||
|
|
||||||
from . import Text, ChoiceQuestion, WebMission, Empty
|
from . import Text, ChoiceQuestion, WebMission, Empty, TextQuestion
|
||||||
from .base import BaseSurvey
|
from .base import BaseSurvey
|
||||||
|
|
||||||
|
|
||||||
all_survey: dict[str, Type[BaseSurvey]] = {
|
all_survey: dict[str, Type[BaseSurvey]] = {
|
||||||
|
# base
|
||||||
"empty": Empty,
|
"empty": Empty,
|
||||||
"text": Text,
|
"text": Text,
|
||||||
|
# questions
|
||||||
"question-choice": ChoiceQuestion,
|
"question-choice": ChoiceQuestion,
|
||||||
|
"question-text": TextQuestion,
|
||||||
|
# missions
|
||||||
"mission-web": WebMission,
|
"mission-web": WebMission,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
88
source/widget/Browser.py
Normal file
88
source/widget/Browser.py
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from PyQt6.QtCore import QUrl, QObject, QEvent
|
||||||
|
from PyQt6.QtGui import QMouseEvent
|
||||||
|
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
||||||
|
from PyQt6.QtWidgets import QVBoxLayout, QWidget, QProgressBar, QStyle, QToolBar
|
||||||
|
|
||||||
|
|
||||||
|
class Browser(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.navigation = QToolBar()
|
||||||
|
self._layout.addWidget(self.navigation, 0)
|
||||||
|
|
||||||
|
style = self.style()
|
||||||
|
|
||||||
|
self._action_back = self.navigation.addAction(
|
||||||
|
style.standardIcon(QStyle.StandardPixmap.SP_ArrowBack),
|
||||||
|
"Back"
|
||||||
|
)
|
||||||
|
self._action_reload = self.navigation.addAction(
|
||||||
|
style.standardIcon(QStyle.StandardPixmap.SP_BrowserReload),
|
||||||
|
"Reload"
|
||||||
|
)
|
||||||
|
self._action_forward = self.navigation.addAction(
|
||||||
|
style.standardIcon(QStyle.StandardPixmap.SP_ArrowForward),
|
||||||
|
"Forward"
|
||||||
|
)
|
||||||
|
|
||||||
|
# web widget
|
||||||
|
self.web = QWebEngineView()
|
||||||
|
self._layout.addWidget(self.web, 1)
|
||||||
|
|
||||||
|
if url is not None:
|
||||||
|
self.web.load(QUrl(url))
|
||||||
|
|
||||||
|
# loading bar
|
||||||
|
self.progress = QProgressBar()
|
||||||
|
self._layout.addWidget(self.progress, 0)
|
||||||
|
self.progress.setFixedHeight(6)
|
||||||
|
self.progress.setTextVisible(False)
|
||||||
|
self.progress.setMaximum(100)
|
||||||
|
self.progress.hide()
|
||||||
|
|
||||||
|
# connect the signals
|
||||||
|
self.web.loadStarted.connect(self._load_started) # NOQA: connect exist
|
||||||
|
self.web.loadProgress.connect(self._load_progress) # NOQA: connect exist
|
||||||
|
self.web.loadFinished.connect(self._load_finished) # NOQA: connect exist
|
||||||
|
|
||||||
|
self._action_back.triggered.connect(self.web.back) # NOQA: connect exist
|
||||||
|
self._action_reload.triggered.connect(self.web.reload) # NOQA: connect exist
|
||||||
|
self._action_forward.triggered.connect(self.web.forward) # NOQA: connect exist
|
||||||
|
|
||||||
|
# finalize the initialisation
|
||||||
|
self.refresh_navigation_actions()
|
||||||
|
|
||||||
|
# graphical methods
|
||||||
|
|
||||||
|
def _load_started(self):
|
||||||
|
# update the progress bar
|
||||||
|
self.progress.setValue(0)
|
||||||
|
self.progress.show()
|
||||||
|
|
||||||
|
def _load_progress(self, value: int):
|
||||||
|
# update the progress bar
|
||||||
|
self.progress.setValue(value)
|
||||||
|
|
||||||
|
def _load_finished(self):
|
||||||
|
# update the progress bar
|
||||||
|
self.progress.hide()
|
||||||
|
# refresh the navigation buttons
|
||||||
|
self.refresh_navigation_actions()
|
||||||
|
|
||||||
|
def refresh_navigation_actions(self):
|
||||||
|
history = self.web.history()
|
||||||
|
# enable the navigation button depending on the history
|
||||||
|
self._action_back.setEnabled(history.canGoBack())
|
||||||
|
self._action_forward.setEnabled(history.canGoForward())
|
|
@ -1,93 +0,0 @@
|
||||||
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())
|
|
|
@ -58,7 +58,7 @@ class FrameSurvey(QFrame):
|
||||||
|
|
||||||
def load_file(self, survey_path: Path | str):
|
def load_file(self, survey_path: Path | str):
|
||||||
# load the surveys screens
|
# load the surveys screens
|
||||||
with open(survey_path) as file:
|
with open(survey_path, encoding="utf-8") as file:
|
||||||
surveys_data = json.load(file)
|
surveys_data = json.load(file)
|
||||||
|
|
||||||
self.survey_screens = [
|
self.survey_screens = [
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
from .DecoratedWebEngineView import DecoratedWebEngineView
|
from .Browser import Browser
|
||||||
from .FrameSurvey import FrameSurvey
|
from .FrameSurvey import FrameSurvey
|
||||||
from .MyMainWindow import MyMainWindow
|
from .MyMainWindow import MyMainWindow
|
||||||
|
|
|
@ -29,5 +29,10 @@
|
||||||
"title": "Rendez-vous sur la boutique des points.",
|
"title": "Rendez-vous sur la boutique des points.",
|
||||||
"url": "https://steampowered.com/",
|
"url": "https://steampowered.com/",
|
||||||
"check": "true"
|
"check": "true"
|
||||||
|
},
|
||||||
|
|
||||||
|
"question-experience": {
|
||||||
|
"type": "question-text",
|
||||||
|
"title": "Qu'avez vous pensé de l'interface de Steam ?"
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue