Warning, file /education/parley/src/practice/multiplechoicemodewidget.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2009 Frederik Gladhorn <gladhorn@kde.org> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "multiplechoicemodewidget.h" 0007 #include "guifrontend.h" 0008 #include "latexrenderer.h" 0009 #include "multiplechoicedata.h" 0010 0011 #include "ui_practice_widget_multiplechoice.h" 0012 0013 #include <KColorScheme> 0014 #include <QAction> 0015 #include <QDebug> 0016 #include <QKeyEvent> 0017 #include <QPushButton> 0018 #include <QTimer> 0019 #include <QVBoxLayout> 0020 0021 using namespace Practice; 0022 0023 MultiplechoiceModeWidget::MultiplechoiceModeWidget(GuiFrontend *frontend, QWidget *parent) 0024 : AbstractModeWidget(frontend, parent) 0025 , m_latexRenderer(0) 0026 { 0027 m_ui = new Ui::MultiplechoicePracticeWidget(); 0028 m_ui->setupUi(this); 0029 0030 for (int i = 0; i < 5; i++) { 0031 QAction *action = new QAction(this); 0032 action->setShortcut(Qt::Key_1 + i); 0033 addAction(action); 0034 m_actions.append(action); 0035 } 0036 connect(frontend, &AbstractFrontend::continueAction, this, &AbstractModeWidget::stopAudio); 0037 connect(frontend, &AbstractFrontend::skipAction, this, &AbstractModeWidget::stopAudio); 0038 } 0039 0040 void MultiplechoiceModeWidget::setQuestionFont(const QFont &font) 0041 { 0042 m_ui->questionLabel->setFont(font); 0043 } 0044 0045 void MultiplechoiceModeWidget::setSolutionFont(const QFont &font) 0046 { 0047 m_solutionFont = font; 0048 resetButtonStyleSheet(); 0049 } 0050 0051 void MultiplechoiceModeWidget::setQuestion(const QVariant &question) 0052 { 0053 if (!question.canConvert<MultipleChoiceData>()) { 0054 qWarning() << "expected MultipleChoiceData"; 0055 return; 0056 } 0057 MultipleChoiceData data = question.value<MultipleChoiceData>(); 0058 0059 m_ui->questionLabel->setMinimumSize(QSize(0, 0)); 0060 if (LatexRenderer::isLatex(data.question)) { 0061 if (!m_latexRenderer) { 0062 m_latexRenderer = new LatexRenderer(this); 0063 m_latexRenderer->setResultLabel(m_ui->questionLabel); 0064 } 0065 m_latexRenderer->renderLatex(data.question); 0066 } else { 0067 m_ui->questionLabel->setText(data.question); 0068 } 0069 0070 if (m_choiceButtons.size() != data.choices.size()) { 0071 qDeleteAll(m_choiceButtons); 0072 m_choiceButtons.clear(); 0073 setNumberOfPushButtons(data.choices.size()); 0074 } 0075 0076 int j = 0; 0077 for (QPushButton *pushButton : qAsConst(m_choiceButtons)) { 0078 pushButton->setText(data.choices[j]); 0079 pushButton->setToolTip(data.choices[j]); 0080 pushButton->setFont(m_solutionFont); 0081 j++; 0082 } 0083 } 0084 0085 void MultiplechoiceModeWidget::showQuestion() 0086 { 0087 m_ui->questionPronunciationLabel->setVisible(m_ui->questionPronunciationLabel->isEnabled()); 0088 m_ui->questionSoundButton->setVisible(m_ui->questionSoundButton->isEnabled()); 0089 m_ui->solutionPronunciationLabel->setVisible(false); 0090 m_ui->solutionSoundButton->setVisible(false); 0091 m_ui->feedbackLabel->clear(); 0092 0093 resetButtonStyleSheet(); 0094 0095 if (!m_choiceButtons.isEmpty()) { 0096 for (QPushButton *pushButton : qAsConst(m_choiceButtons)) { 0097 pushButton->setChecked(false); 0098 pushButton->setEnabled(true); 0099 } 0100 0101 QTimer::singleShot(0, m_choiceButtons[0], SLOT(setFocus())); 0102 } 0103 } 0104 0105 void MultiplechoiceModeWidget::setNumberOfPushButtons(const int numberOfChoices) 0106 { 0107 QVBoxLayout *verticalLayout = new QVBoxLayout(); 0108 m_ui->gridLayout->addLayout(verticalLayout, 2, 0); 0109 0110 for (int i = 0; i < numberOfChoices; i++) { 0111 QHBoxLayout *horizontalLayout = new QHBoxLayout(); 0112 verticalLayout->addLayout(horizontalLayout); 0113 0114 // Display number of entry 0115 QLabel *label = new QLabel(QString::number(i + 1) + QStringLiteral(":"), this); 0116 horizontalLayout->addWidget(label); 0117 0118 // Button displaying choice 0119 QPushButton *pushButton = new QPushButton(this); 0120 pushButton->setCheckable(true); 0121 pushButton->setFlat(true); 0122 pushButton->sizePolicy().setHorizontalPolicy(QSizePolicy::Maximum); 0123 m_choiceButtons.append(pushButton); 0124 if (i < 5) { 0125 connect(m_actions.at(i), &QAction::triggered, pushButton, &QAbstractButton::click); 0126 } 0127 connect(pushButton, &QPushButton::clicked, this, &MultiplechoiceModeWidget::continueAction); 0128 pushButton->installEventFilter(this); 0129 horizontalLayout->addWidget(pushButton); 0130 0131 // Spacer to align button to the left 0132 horizontalLayout->addStretch(1); 0133 } 0134 } 0135 0136 void MultiplechoiceModeWidget::setSynonym(const QString & /*entry*/) 0137 { 0138 // TODO Do something here to show synonyms 0139 } 0140 0141 void MultiplechoiceModeWidget::showSynonym() 0142 { 0143 // TODO Do something here to show synonyms 0144 } 0145 0146 bool MultiplechoiceModeWidget::eventFilter(QObject *obj, QEvent *event) 0147 { 0148 // make it possible to use the enter key to select multiple choice options 0149 if (event->type() == QEvent::KeyPress) { 0150 QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); 0151 if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) { 0152 QPushButton *pushButton = qobject_cast<QPushButton *>(obj); 0153 if (pushButton) { 0154 pushButton->click(); 0155 return true; 0156 } 0157 } 0158 } 0159 0160 return QObject::eventFilter(obj, event); 0161 } 0162 0163 void MultiplechoiceModeWidget::setSolution(const QVariant &solution) 0164 { 0165 m_solution = solution.toInt(); 0166 } 0167 0168 void MultiplechoiceModeWidget::setHint(const QVariant &hint) 0169 { 0170 m_choiceButtons.at(hint.toInt())->setEnabled(false); 0171 } 0172 0173 void MultiplechoiceModeWidget::setFeedback(const QVariant &feedback) 0174 { 0175 m_ui->feedbackLabel->setText(feedback.toString()); 0176 } 0177 0178 void MultiplechoiceModeWidget::showSolution() 0179 { 0180 int input = -1; 0181 if (userInput().isValid()) { 0182 input = userInput().toInt(); 0183 } 0184 0185 const QColor textColor = palette().color(QPalette::WindowText); 0186 // Set border to text color with light transparency 0187 const QString borderColor = QStringLiteral("#90") + palette().color(QPalette::WindowText).name().remove(0, 1); 0188 // Set background to correct color, but with transparency 0189 const QString correctBackground = QStringLiteral("#7D") + m_correctPalette.color(QPalette::Text).name().remove(0, 1); 0190 0191 m_choiceButtons[m_solution]->setStyleSheet( 0192 m_choiceButtons[m_solution]->styleSheet() + 0193 " QPushButton:checked { " 0194 "color: " + textColor.name() + "; " 0195 "border-color: " + borderColor + "; " 0196 "background-color: " + correctBackground + 0197 " }" 0198 ); 0199 // Always check correct button to highlight correct answer 0200 m_choiceButtons[m_solution]->setChecked(true); 0201 0202 if (input != -1 && input != m_solution) { 0203 const QString wrongBackground = QStringLiteral("#7D") + m_wrongPalette.color(QPalette::Text).name().remove(0, 1); 0204 0205 m_choiceButtons[input]->setStyleSheet( 0206 m_choiceButtons[input]->styleSheet() + 0207 " QPushButton:checked { " 0208 "color: " + textColor.name() + "; " 0209 "border-color: " + borderColor + "; " 0210 "background-color: " + wrongBackground + 0211 " }" 0212 ); 0213 } 0214 for (QPushButton *pushButton : qAsConst(m_choiceButtons)) { 0215 pushButton->setEnabled(false); 0216 } 0217 m_ui->solutionPronunciationLabel->setVisible(m_ui->solutionPronunciationLabel->isEnabled()); 0218 m_ui->solutionSoundButton->setVisible(m_ui->solutionSoundButton->isEnabled()); 0219 } 0220 0221 QVariant MultiplechoiceModeWidget::userInput() 0222 { 0223 int i = 0; 0224 for (QPushButton *pushButton : qAsConst(m_choiceButtons)) { 0225 if (pushButton->isChecked()) 0226 return i; 0227 i++; 0228 } 0229 0230 return QVariant(); 0231 } 0232 0233 void MultiplechoiceModeWidget::setQuestionSound(const QUrl &soundUrl) 0234 { 0235 m_ui->questionSoundButton->setSoundFile(soundUrl); 0236 } 0237 0238 void MultiplechoiceModeWidget::setSolutionSound(const QUrl &soundUrl) 0239 { 0240 m_ui->solutionSoundButton->setSoundFile(soundUrl); 0241 } 0242 0243 void MultiplechoiceModeWidget::setSolutionPronunciation(const QString &pronunciationText) 0244 { 0245 m_ui->solutionPronunciationLabel->setText('[' + pronunciationText + ']'); 0246 m_ui->solutionPronunciationLabel->setEnabled(!pronunciationText.isNull()); 0247 } 0248 0249 void MultiplechoiceModeWidget::setQuestionPronunciation(const QString &pronunciationText) 0250 { 0251 m_ui->questionPronunciationLabel->setText('[' + pronunciationText + ']'); 0252 m_ui->questionPronunciationLabel->setEnabled(!pronunciationText.isNull()); 0253 } 0254 0255 void MultiplechoiceModeWidget::resetButtonStyleSheet() 0256 { 0257 // Define default QPushButton StyleSheet 0258 const QColor textColor = palette().color(QPalette::WindowText); 0259 // Set border to text color with light transparency 0260 const QString borderColor = QStringLiteral("#90") + palette().color(QPalette::WindowText).name().remove(0, 1); 0261 const QString defaultStyleSheet = 0262 "QPushButton { text-align: left; " 0263 "color: " + textColor.name() + "; " 0264 "padding: 5px; " 0265 "border-color: #00FFFFFF; " // Make border transparent 0266 "border-style: solid; " 0267 "border-width: 1px; " 0268 "border-radius: 4px; " 0269 "font-style: " + 0270 m_solutionFont.styleName() + "; " + 0271 "font-weight: " + 0272 QString::number(m_solutionFont.weight()) + "; " + 0273 "font-size: " + 0274 QString::number(m_solutionFont.pointSize()) + "pt } "+ 0275 "QPushButton:hover { " 0276 "border-color: " + borderColor + " } " 0277 "QPushButton:focus { " 0278 "color: " + textColor.name() + " } " 0279 "QPushButton:focus:!hover { " 0280 "border-style: dashed; " 0281 "border-color: " + borderColor + " }"; 0282 0283 if (!m_choiceButtons.isEmpty()) { 0284 for (QPushButton *pushButton : qAsConst(m_choiceButtons)) { 0285 pushButton->setStyleSheet(defaultStyleSheet); 0286 } 0287 } 0288 }