# This file is part of Octopus Sensing <https://octopus-sensing.nastaran-saffar.me/>
# Copyright © Nastaran Saffaryazdi 2020
#
# Octopus Sensing is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.
#
# Octopus Sensing is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with Octopus Sensing.
# If not, see <https://www.gnu.org/licenses/>.
import gi
gi.require_version('Gtk', '3.0') # nopep8
from gi.repository import Gtk # nopep8
from typing import List, Union, Any
from octopus_sensing.questionnaire.question import Question
FONT_STYLE = "<span font_desc='Tahoma 16'>{}</span>"
[docs]class Option():
'''
The class for creating opinions
Attributes
----------
Parameters
----------
id: int
A unique ID for the opinion
label: str
The text of opinion
value: Any
The value of opinion
'''
def __init__(self, id: int, label: str=None, value: Any=None):
self.id = id
self.label = label
if self.label is None:
self.label = str(id)
self.value = value
if self.value is None:
self.value = id
[docs]class OpinionQuestion(Question):
'''
The class for creating opinion questions using Gtk 3.0
Attributes
----------
Parameters
----------
id: str
A unique ID for the question
text: str
The text of question
options: Union[dict, int]
image_path: str, default: None
The path to an image which will be showed with the question.
default_answer: Union[int, str], default: 0
The default checked option
'''
def __init__(self, id: str, text: str, options: Union[dict, int],
image_path: str = None, default_answer: int = 0):
super().__init__(id, text)
self._options = []
if isinstance(options, int):
for i in range(options):
option = Option(i, label=str(i), value=i)
self._options.append(option)
else:
i = 0
for key, value in options.items():
option = Option(i, label=key, value=value)
self._options.append(option)
i += 1
self._image_path = image_path
self.answer = default_answer
[docs] def render(self, grid: Gtk.Grid, grid_row: int):
'''
renders a question for adding to a questionnaire
Parameters
----------
grid: Gtk.Grid
a Gtk grid object that this question will be added to it
grid_row: int
The row number of grid that the question will be added to it
Returns
-------
row_counter: int
The grid's row for adding the next object after adding this question
Examples
--------
Creating an opinion question and adding it to the questionnaire
>>> emotions = {"Happiness": 4, "Sadness": 6, "Neutral": 5, "Fear": 3, "Anger": 1}
>>> question_1 = OpinionQuestion("q1",
... "1- What emotion did you feel the most?",
... options=emotions,
... default_answer=5)
>>> questionnaire = Questionnaire("after_stimuli",
... "study01_p10",
... "stimuli00",
... "After Stimulus Questionnaire")
>>> questionnaire.add_questions([question_1])
See Also
-----------
:class:`octopus_sensing.questionnaire.questionnaire`
'''
row_counter = grid_row
# Question box
question_label_box = Gtk.Box(spacing=120)
question_label = Gtk.Label()
question_label.set_markup(FONT_STYLE.format(self._text))
question_label_box.pack_start(question_label, False, False, 0)
grid.attach(question_label_box, 0, row_counter, 1, 1)
row_counter += 1
# Image box
image_box = None
if self._image_path is not None:
image_box = Gtk.Box(spacing=120)
image = Gtk.Image.new_from_file(self._image_path)
image_box.pack_start(image, False, False, 0)
grid.attach(image_box, 0, row_counter, 1, 1)
row_counter += 1
# Options box
options_box = Gtk.Box(spacing=120)
option_buttons: List[Gtk.RadioButton] = []
for i, option in enumerate(self._options):
if i == 0:
option_button = \
Gtk.RadioButton.new_with_label_from_widget(None, str(option.id))
else:
option_button = \
Gtk.RadioButton.new_with_label_from_widget(option_buttons[0],
str(option.id))
option_button.connect("toggled",
self.__on_option_button_toggled,
option.value)
option_button.get_child().set_markup(FONT_STYLE.format(option.label))
option_buttons.append(option_button)
options_box.pack_start(option_button, False, False, 0)
if option.value == self.answer:
option_button.set_active(True)
grid.attach(options_box, 0, row_counter, 1, 1)
row_counter += 1
return row_counter
def __on_option_button_toggled(self, button, name):
if button.get_active():
self.answer = name
[docs] def get_answer(self) -> int:
'''
Gets selected answer
Returns
-------
answer: int
answer
'''
return self.answer