File indexing completed on 2023-05-30 10:45:28

0001 /*
0002     SPDX-FileCopyrightText: 2003-2010 Peter Hedlund <peter.hedlund@kdemail.net>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "qaview.h"
0008 
0009 #include <QDBusInterface>
0010 #include <QUrl>
0011 
0012 #include <KLocalizedString>
0013 #include <KNotification>
0014 
0015 #include "prefs.h"
0016 #include "kwqquizmodel.h"
0017 #include "kwqscorewidget.h"
0018 
0019 QString highlightError(const QString & c, const QString & e)
0020 {
0021   if (c == e)
0022     return c;
0023 
0024   QString s = c;
0025   if (s.left(4) == QLatin1String("<qt>") && e.left(4) != QLatin1String("<qt>"))
0026       s = s.mid(4, s.length() - 9);
0027 
0028   if (s == e)
0029     return s;
0030 
0031   QString result = QStringLiteral("<qt>");
0032   int i = 0;
0033   while (i < e.length() && s[i] == e[i])
0034     result.append(e[i++]);
0035   result.append("<b>");
0036   QString result2 = QStringLiteral("</qt>");
0037   int j = s.length() - 1;
0038   int k = e.length() - 1;
0039   while (j >= 0 && k >= 0 && s[j] == e[k])
0040   {
0041     result2.prepend(e[k]);
0042     j--;
0043     k--;
0044   }
0045   result2.prepend("</b>");
0046 
0047   for (int m = i; m <= k; m++)
0048     result.append(e[m]);
0049 
0050   result.append(result2);
0051   return result;
0052 }
0053 
0054 QAView::QAView(QWidget *parent, KActionCollection * actionCollection) : KWQQuizView(parent, actionCollection)
0055 {
0056   setupUi(this);
0057 
0058   connect(txtAnswer, SIGNAL(returnPressed()), this, SLOT(slotCheck()));
0059 }
0060 
0061 void QAView::init()
0062 {
0063   score->clear();
0064   score->setQuestionCount(m_quiz->questionCount());
0065   score->setAsPercent(Prefs::percent());
0066 
0067   m_hintUsed = false;
0068 
0069   QFont f = Prefs::editorFont();
0070   f.setWeight(QFont::Normal);
0071   lblQuestion->setFont(f);
0072   lblAnswerBlank->setFont(f);
0073   txtAnswer->setFont(f);
0074   lblPreviousQuestion->setFont(f);
0075   lblYourAnswer->setFont(f);
0076   lblCorrect->setFont(f);
0077 
0078   lblPreviousQuestionHeader->clear();
0079   lblPreviousQuestion->clear();
0080   lblYourAnswerHeader->clear();
0081   lblYourAnswer->clear();
0082   lblCorrectHeader->clear();
0083   lblCorrect->clear();
0084 
0085   picPrevious->clear();
0086   picYourAnswer->clear();
0087   picCorrectAnswer->clear();
0088 
0089   m_actionCollection->action(QStringLiteral("quiz_check"))->setEnabled(true);
0090   m_actionCollection->action(QStringLiteral("qa_mark_last_correct"))->setEnabled(false);
0091   m_actionCollection->action(QStringLiteral("qa_hint"))->setEnabled(true);
0092   m_actionCollection->action(QStringLiteral("quiz_repeat_errors"))->setEnabled(false);
0093   m_actionCollection->action(QStringLiteral("quiz_export_errors"))->setEnabled(false);
0094   m_actionCollection->action(QStringLiteral("quiz_audio_play"))->setEnabled(false);
0095 
0096   // reset last file
0097   audioPlayFile(QUrl(), true);
0098 
0099   showQuestion();
0100   txtAnswer->show();
0101   txtAnswer->setFocus();
0102 }
0103 
0104 void QAView::slotCheck()
0105 {
0106   if (m_actionCollection->action(QStringLiteral("quiz_check"))->isEnabled())
0107   {
0108     bool fIsCorrect;
0109 
0110     if (m_hintUsed && Prefs::hintError())
0111     {
0112       //Force an Error
0113       fIsCorrect = m_quiz->checkAnswer(QLatin1String(""));
0114     }
0115     else
0116     {
0117       //Really check the answer
0118       fIsCorrect = m_quiz->checkAnswer(txtAnswer->text());
0119     }
0120     //Reset for next question
0121     m_hintUsed = false;
0122 
0123     if (fIsCorrect)
0124     {
0125       picYourAnswer->setPixmap(QIcon::fromTheme(QStringLiteral("answer-correct")).pixmap(32));
0126       lblYourAnswer->setText(m_quiz->yourAnswer(txtAnswer->text()));
0127       lblCorrectHeader->clear();
0128       picCorrectAnswer->clear();
0129       lblCorrect->clear();
0130       score->countIncrement(KWQScoreWidget::cdCorrect);
0131       KNotification::event(QStringLiteral("QuizCorrect"), i18n("Your answer was correct!"));
0132       m_actionCollection->action(QStringLiteral("qa_mark_last_correct"))->setEnabled(false);
0133     }
0134     else
0135     {
0136       picYourAnswer->setPixmap(QIcon::fromTheme(QStringLiteral("error")).pixmap(32));
0137       lblYourAnswer->setText(highlightError(m_quiz->answer(), m_quiz->yourAnswer(txtAnswer->text())));
0138       lblCorrect->setText(m_quiz->answer());
0139       picCorrectAnswer->setPixmap(QIcon::fromTheme(QStringLiteral("answer-correct")).pixmap(32));
0140       lblCorrectHeader->setText(i18n("Correct Answer"));
0141       score->countIncrement(KWQScoreWidget::cdError);
0142       KNotification::event(QStringLiteral("QuizError"), i18n("Your answer was incorrect."));
0143       m_actionCollection->action(QStringLiteral("qa_mark_last_correct"))->setEnabled(true);
0144     }
0145 
0146     audioPlayAnswer();
0147 
0148     lblPreviousQuestionHeader->setText(i18n("Previous Question"));
0149     lblPreviousQuestion->setText(m_quiz->question());
0150     //lblPreviousQuestion->setFont(m_quiz->fontQuestion(m_question));
0151     picPrevious->setPixmap(QIcon::fromTheme(QStringLiteral("question")).pixmap(32));
0152 
0153     lblYourAnswerHeader->setText(i18n("Your Answer"));
0154 
0155     m_quiz->toNext();
0156     if (!m_quiz->atEnd())
0157     {
0158       showQuestion();
0159     }
0160     else
0161     {
0162       m_quiz->finish();
0163       m_actionCollection->action(QStringLiteral("quiz_check"))->setEnabled(false);
0164       m_actionCollection->action(QStringLiteral("qa_hint"))->setEnabled(false);
0165       m_actionCollection->action(QStringLiteral("quiz_repeat_errors"))->setEnabled(m_quiz->hasErrors());
0166       m_actionCollection->action(QStringLiteral("quiz_export_errors"))->setEnabled(m_quiz->hasErrors());
0167       m_actionCollection->action(QStringLiteral("qa_mark_last_correct"))->setEnabled(false);
0168 
0169       lblQuestionLanguage->setText(i18n("Summary"));
0170       lblQuestion->clear();
0171       lblAnswerLanguage->clear();
0172       lblAnswerBlank->hide();
0173       txtAnswer->hide();
0174       picQuestion->setPixmap(QIcon::fromTheme(QStringLiteral("kwordquiz")).pixmap(32));
0175       picAnswer->clear();
0176     }
0177   }
0178 }
0179 
0180 void QAView::slotHint()
0181 {
0182   QString answer = txtAnswer->text();
0183   QString correctAnswer = m_quiz->hint();
0184   if (correctAnswer.left(4) == QLatin1String("<qt>"))
0185   {
0186     correctAnswer = correctAnswer.remove(QStringLiteral("<qt>"));
0187     correctAnswer = correctAnswer.remove(QStringLiteral("</qt>"));
0188   }
0189   int minLength = qMin(answer.length(), correctAnswer.length());
0190 
0191   int correctCharCount = 1;
0192 
0193   if (answer.length() > 0)
0194   {
0195     for(int i = 0; i < minLength; i++)
0196     {
0197     if (answer.at(i) == correctAnswer.at(i))
0198       correctCharCount++;
0199     }
0200   }
0201 
0202   txtAnswer->setText(correctAnswer.left(correctCharCount));
0203   txtAnswer->setFocus();
0204   txtAnswer->setCursorPosition(txtAnswer->text().length());
0205 
0206   m_hintUsed = true;
0207 }
0208 
0209 /*!
0210     \fn QAView::showQuestion(int i)
0211  */
0212 void QAView::showQuestion()
0213 {
0214   lblQuestionLanguage->setText(m_quiz ->langQuestion());
0215   lblQuestion->setText(m_quiz ->question());
0216   //audioPlayQuestion();
0217 
0218   picQuestion->setPixmap(QIcon::fromTheme(m_quiz->quizIcon(KWQQuizModel::IconLeftCol)).pixmap(32));
0219 
0220   lblAnswerLanguage->setText(m_quiz ->langAnswer());
0221 
0222   if (!QString(m_quiz->blankAnswer()).isEmpty())
0223   {
0224     lblAnswerBlank->show();
0225     lblAnswerBlank->setText(m_quiz->blankAnswer());
0226   }
0227   else
0228     lblAnswerBlank->hide();
0229 
0230   txtAnswer->setText(QLatin1String(""));
0231 
0232   picAnswer->setPixmap(QIcon::fromTheme(m_quiz->quizIcon(KWQQuizModel::IconRightCol)).pixmap(32));
0233 
0234   QString layout = m_quiz->kbAnswer();
0235   if (!layout.isEmpty()) {
0236     QDBusInterface kxkb(QStringLiteral("org.kde.keyboard"), QStringLiteral("/Layouts"), QStringLiteral("org.kde.KeyboardLayouts"));
0237     if (kxkb.isValid())
0238       kxkb.call(QStringLiteral("setLayout"), layout);
0239   }
0240 }
0241 
0242 void QAView::slotApplySettings( )
0243 {
0244   score->setAsPercent(Prefs::percent());
0245 }
0246 
0247 void QAView::slotSpecChar( const QChar & c)
0248 {
0249   if (txtAnswer->hasFocus())
0250   {
0251     if (txtAnswer->hasSelectedText())
0252     {
0253       QString ls = txtAnswer->text();
0254       QString s = txtAnswer->selectedText();
0255       int len = s.length();
0256       int ss = txtAnswer->selectionStart();
0257       ls = ls.replace(ss, len, c);
0258       txtAnswer->setText(ls);
0259       txtAnswer->setSelection(ss, 1);
0260     }
0261     else
0262     {
0263       QString s = txtAnswer->text();
0264       int i = txtAnswer->cursorPosition();
0265       s.insert(i, c);
0266       txtAnswer->setText(s);
0267       txtAnswer->setCursorPosition(i + 1);
0268     }
0269   }
0270 }
0271 
0272 void QAView::slotMarkLastCorrect( )
0273 {
0274   m_quiz->removeLastError();
0275   score->swapCount();
0276   m_actionCollection->action(QStringLiteral("qa_mark_last_correct"))->setEnabled(false);
0277 }