File indexing completed on 2024-04-14 03:49:10
0001 /* 0002 SPDX-FileCopyrightText: 2009 Daniel Laidig <d.laidig@gmx.de> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "guifrontend.h" 0007 0008 #include <QTimer> 0009 0010 #include <KColorScheme> 0011 #include <KLocalizedString> 0012 #include <QDebug> 0013 0014 #include "ui_practice_mainwindow.h" 0015 0016 #include "comparisonmodewidget.h" 0017 #include "conjugationmodewidget.h" 0018 #include "flashcardmodewidget.h" 0019 #include "mixedlettersmodewidget.h" 0020 #include "multiplechoicemodewidget.h" 0021 #include "settings/kgametheme/kgametheme.h" 0022 #include "themedbackgroundrenderer.h" 0023 #include "writtenpracticewidget.h" 0024 0025 using namespace Practice; 0026 0027 GuiFrontend::GuiFrontend(QWidget *parent) 0028 : AbstractFrontend(parent) 0029 , m_widget(new ImageWidget()) 0030 , m_ui(new Ui::PracticeMainWindow()) 0031 , m_resultState(AbstractFrontend::AnswerWrong) 0032 , m_feedbackState(AbstractFrontend::AnswerWrong) 0033 , m_themedBackgroundRenderer(new ThemedBackgroundRenderer(this, QStringLiteral("practicethemecache.bin"))) 0034 { 0035 m_widget->setScalingEnabled(false, false); 0036 m_widget->setKeepAspectRatio(Qt::IgnoreAspectRatio); 0037 m_widget->setFadingEnabled(false); 0038 0039 m_ui->setupUi(m_widget); 0040 m_ui->centralPracticeWidget->setLayout(new QHBoxLayout()); 0041 0042 connect(Prefs::self(), &Prefs::configChanged, this, &GuiFrontend::setTheme); 0043 setTheme(); 0044 0045 connect(m_themedBackgroundRenderer, &ThemedBackgroundRenderer::backgroundChanged, this, &GuiFrontend::backgroundChanged); 0046 connect(m_widget, &ImageWidget::sizeChanged, this, &GuiFrontend::updateBackground); 0047 0048 connect(m_ui->continueButton, &QPushButton::clicked, this, &GuiFrontend::continueAction); 0049 connect(m_ui->answerLaterButton, &QPushButton::clicked, this, &GuiFrontend::skipAction); 0050 connect(m_ui->hintButton, &QPushButton::clicked, this, &GuiFrontend::hintAction); 0051 connect(m_ui->statusToggle, &Practice::StatusToggle::toggle, this, &GuiFrontend::toggleResultState); 0052 connect(m_ui->countAsCorrectButton, &QPushButton::clicked, this, &GuiFrontend::countAsCorrectButtonClicked); 0053 connect(m_ui->countAsWrongButton, &QPushButton::clicked, this, &GuiFrontend::countAsWrongButtonClicked); 0054 0055 m_ui->centralPracticeWidget->installEventFilter(this); 0056 m_ui->imageWidget->installEventFilter(this); 0057 m_ui->rightContainer->installEventFilter(this); 0058 0059 QTimer::singleShot(0, this, &GuiFrontend::updateBackground); 0060 } 0061 0062 GuiFrontend::~GuiFrontend() 0063 { 0064 delete m_widget; 0065 delete m_ui; 0066 } 0067 0068 QVariant GuiFrontend::userInput() 0069 { 0070 return m_modeWidget->userInput(); 0071 } 0072 0073 QWidget *GuiFrontend::widget() 0074 { 0075 return m_widget; 0076 } 0077 0078 void GuiFrontend::setMode(Mode mode) 0079 { 0080 qDebug() << "setCentralWidget" << mode; 0081 AbstractModeWidget *newWidget = nullptr; 0082 switch (mode) { 0083 case Written: 0084 if (/*m_modeWidget->metaObject()->className() == QLatin1String("WrittenPracticeWidget")*/ false) { 0085 qDebug() << "Written practice widget is already the central widget"; 0086 break; 0087 } 0088 newWidget = new WrittenPracticeWidget(this, m_widget); 0089 break; 0090 case MultipleChoice: 0091 newWidget = new MultiplechoiceModeWidget(this, m_widget); 0092 break; 0093 case FlashCard: 0094 newWidget = new FlashCardModeWidget(this, m_widget); 0095 break; 0096 case MixedLetters: 0097 newWidget = new MixedLettersModeWidget(this, m_widget); 0098 break; 0099 case Conjugation: 0100 newWidget = new ConjugationModeWidget(this, m_widget); 0101 break; 0102 case Comparison: 0103 newWidget = new ComparisonModeWidget(this, m_widget); 0104 break; 0105 case ExampleSentence: 0106 newWidget = new WrittenPracticeWidget(this, m_widget, true); 0107 break; 0108 default: 0109 Q_ASSERT("Practice Mode Invalid" == nullptr); 0110 } 0111 if (newWidget) { 0112 m_ui->centralPracticeWidget->layout()->addWidget(newWidget); 0113 delete m_modeWidget; 0114 m_modeWidget = newWidget; 0115 connect(m_modeWidget, SIGNAL(continueAction()), m_ui->continueButton, SLOT(animateClick())); 0116 } 0117 m_ui->buttonStack->setCurrentIndex(0); 0118 updateFontColors(); 0119 } 0120 0121 void GuiFrontend::setLessonName(const QString &lessonName) 0122 { 0123 m_ui->lessonLabel->setText(i18nc("Display of the current unit during practice", "Unit: %1", lessonName)); 0124 } 0125 0126 void GuiFrontend::showGrade(int preGrade, int grade) 0127 { 0128 if (preGrade == 0 && grade == 0) { 0129 m_ui->gradeLabel->setText(i18n("New word")); 0130 } else { 0131 m_ui->gradeLabel->setText(i18nc("Display of the current confidence level during practice, 1st param is either initial or long term", 0132 "%1, confidence %2", 0133 grade == 0 ? i18n("initial") : i18n("long term"), 0134 QString::number(grade == 0 ? preGrade : grade))); 0135 } 0136 } 0137 0138 void GuiFrontend::showQuestion() 0139 { 0140 m_ui->answerLaterButton->setEnabled(true); 0141 m_ui->hintButton->setEnabled(Prefs::showHints()); 0142 QTimer::singleShot(0, m_ui->continueButton, SLOT(setFocus())); 0143 m_modeWidget->showQuestion(); 0144 setImage(m_questionImage); 0145 } 0146 0147 void GuiFrontend::showSolution() 0148 { 0149 m_ui->continueButton->setFocus(); 0150 m_modeWidget->showSolution(); 0151 m_ui->answerLaterButton->setEnabled(false); 0152 m_ui->hintButton->setEnabled(false); 0153 setImage(m_solutionImage); 0154 } 0155 void GuiFrontend::setSynonym(const QString &entry) 0156 { 0157 m_modeWidget->setSynonym(entry); 0158 } 0159 0160 void GuiFrontend::showSynonym() 0161 { 0162 m_modeWidget->showSynonym(); 0163 } 0164 0165 void GuiFrontend::setBoxes(grade_t currentBox, grade_t newBoxIfCorrect, grade_t newBoxIfWrong) 0166 { 0167 m_ui->boxesWidget->setBoxes(currentBox, 0); 0168 m_currentBox = currentBox; 0169 m_newBoxIfCorrect = newBoxIfCorrect; 0170 m_newBoxIfWrong = newBoxIfWrong; 0171 } 0172 0173 void GuiFrontend::backgroundChanged(const QPixmap &pixmap) 0174 { 0175 m_widget->setPixmap(pixmap); 0176 } 0177 0178 void GuiFrontend::showSetResultButtons(bool show) 0179 { 0180 m_ui->buttonStack->setCurrentIndex(int(show)); 0181 if (show) { 0182 m_ui->countAsCorrectButton->setFocus(); 0183 } 0184 } 0185 0186 bool GuiFrontend::eventFilter(QObject *object, QEvent *event) 0187 { 0188 if (event->type() == QEvent::Resize) 0189 updateBackground(); 0190 return AbstractFrontend::eventFilter(object, event); 0191 } 0192 0193 void GuiFrontend::setFinishedWordsTotalWords(int finished, int total) 0194 { 0195 int finishedPercentage = 1.0 * finished / total * 100; 0196 // update progress bar 0197 m_ui->totalProgress->setMaximum(total); 0198 m_ui->totalProgress->setValue(finished); 0199 m_ui->totalProgress->setToolTip(i18np("You answered correctly %2 of a total of %1 word.\nYou are %3% done.", 0200 "You answered correctly %2 of a total of %1 words.\nYou are %3% done.", 0201 total, 0202 finished, 0203 finishedPercentage)); 0204 } 0205 0206 QFont GuiFrontend::knownLangFont() const 0207 { 0208 return m_knownLangFont; 0209 } 0210 0211 QFont GuiFrontend::learningLangFont() const 0212 { 0213 return m_learningLangFont; 0214 } 0215 0216 void GuiFrontend::setKnownLangFont(const QFont &font) 0217 { 0218 m_knownLangFont = font; 0219 } 0220 0221 void GuiFrontend::setLearningLangFont(const QFont &font) 0222 { 0223 m_learningLangFont = font; 0224 } 0225 0226 void GuiFrontend::setHint(const QVariant &hint) 0227 { 0228 m_modeWidget->setHint(hint); 0229 } 0230 0231 void GuiFrontend::setQuestion(const QVariant &question) 0232 { 0233 m_modeWidget->setQuestion(question); 0234 } 0235 0236 void GuiFrontend::setQuestionPronunciation(const QString &pronunciationText) 0237 { 0238 m_modeWidget->setQuestionPronunciation(pronunciationText); 0239 } 0240 0241 void GuiFrontend::setQuestionSound(const QUrl &soundUrl) 0242 { 0243 m_modeWidget->setQuestionSound(soundUrl); 0244 } 0245 0246 void GuiFrontend::setSolution(const QVariant &solution) 0247 { 0248 m_modeWidget->setSolution(solution); 0249 } 0250 0251 void GuiFrontend::setQuestionImage(const QUrl &image) 0252 { 0253 m_questionImage = image; 0254 } 0255 0256 void GuiFrontend::setSolutionImage(const QUrl &image) 0257 { 0258 m_solutionImage = image; 0259 } 0260 0261 void GuiFrontend::setQuestionFont(const QFont &font) 0262 { 0263 m_modeWidget->setQuestionFont(font); 0264 } 0265 0266 void GuiFrontend::setSolutionFont(const QFont &font) 0267 { 0268 m_modeWidget->setSolutionFont(font); 0269 } 0270 0271 void GuiFrontend::setImage(const QUrl &image) 0272 { 0273 if (m_lastImage == image) { 0274 return; 0275 } 0276 QPixmap pixmap(image.path()); 0277 if (pixmap.isNull()) { 0278 m_ui->imageWidget->setPixmap(m_themedBackgroundRenderer->getPixmapForId(QStringLiteral("image-placeholder"), QSize(150, 150))); 0279 } else { 0280 m_ui->imageWidget->setPixmap(pixmap); 0281 } 0282 m_lastImage = image; 0283 } 0284 0285 void GuiFrontend::setSolutionPronunciation(const QString &pronunciationText) 0286 { 0287 m_modeWidget->setSolutionPronunciation(pronunciationText); 0288 } 0289 0290 void GuiFrontend::setSolutionSound(const QUrl &soundUrl) 0291 { 0292 m_modeWidget->setSolutionSound(soundUrl); 0293 } 0294 0295 void GuiFrontend::setFeedback(const QVariant &feedback) 0296 { 0297 m_modeWidget->setFeedback(feedback); 0298 } 0299 0300 void GuiFrontend::setFeedbackState(ResultState feedbackState) 0301 { 0302 m_feedbackState = feedbackState; 0303 m_modeWidget->setFeedbackState(feedbackState); 0304 } 0305 0306 void GuiFrontend::setResultState(ResultState resultState) 0307 { 0308 // TODO: temporary text labels instead of graphics 0309 // m_ui->statusImageLabel->setFont(QFont("", 80, QFont::Bold)); 0310 m_ui->statusToggle->setResultState(resultState); 0311 switch (resultState) { 0312 case AbstractFrontend::QuestionState: 0313 case AbstractFrontend::AnswerSynonym: 0314 // m_ui->statusImageLabel->setText("?"); 0315 // m_ui->toggleButton->setEnabled(false); 0316 // m_ui->toggleButton->setText(QString(0x2717)+QChar(0x2192)+QChar(0x2713)); 0317 m_ui->boxesWidget->setBoxes(m_currentBox); 0318 break; 0319 case AbstractFrontend::AnswerCorrect: 0320 // m_ui->statusImageLabel->setText(QChar(0x2713)); 0321 // m_ui->toggleButton->setEnabled(true); 0322 // m_ui->toggleButton->setText(QString(0x2713)+QChar(0x2192)+QChar(0x2717)); 0323 m_ui->boxesWidget->setBoxes(m_newBoxIfCorrect, m_currentBox); 0324 break; 0325 0326 // m_ui->statusImageLabel->setText("?"); 0327 // m_ui->toggleButton->setEnabled(true); 0328 // m_ui->toggleButton->setText(QString(0x2713)+QChar(0x2192)+QChar(0x2717)); 0329 // m_ui->boxesWidget->setBoxes(m_currentBox); 0330 // break; 0331 case AbstractFrontend::AnswerWrong: 0332 // m_ui->statusImageLabel->setText(QChar(0x2717)); 0333 // m_ui->toggleButton->setEnabled(true); 0334 // m_ui->toggleButton->setText(QString(0x2717)+QChar(0x2192)+QChar(0x2713)); 0335 m_ui->boxesWidget->setBoxes(m_newBoxIfWrong, m_currentBox); 0336 break; 0337 } 0338 0339 m_resultState = resultState; 0340 m_modeWidget->setResultState(resultState); 0341 } 0342 0343 AbstractFrontend::ResultState GuiFrontend::resultState() 0344 { 0345 return m_resultState; 0346 } 0347 0348 void GuiFrontend::countAsCorrectButtonClicked() 0349 { 0350 m_resultState = AnswerCorrect; 0351 Q_EMIT continueAction(); 0352 } 0353 0354 void GuiFrontend::countAsWrongButtonClicked() 0355 { 0356 m_resultState = AnswerWrong; 0357 Q_EMIT continueAction(); 0358 } 0359 0360 void GuiFrontend::toggleResultState() 0361 { 0362 if (resultState() == AnswerWrong) { 0363 setResultState(AnswerCorrect); 0364 } else { 0365 setResultState(AnswerWrong); 0366 } 0367 } 0368 0369 void GuiFrontend::updateBackground() 0370 { 0371 m_themedBackgroundRenderer->clearRects(); 0372 m_themedBackgroundRenderer->addRect(QStringLiteral("background"), QRect(QPoint(), m_widget->size())); 0373 m_themedBackgroundRenderer->addRect(QStringLiteral("image"), m_ui->imageWidget->frameGeometry()); 0374 m_themedBackgroundRenderer->addRect(QStringLiteral("central"), m_ui->centralPracticeWidget->frameGeometry()); 0375 m_themedBackgroundRenderer->addRect(QStringLiteral("buttons"), m_ui->rightContainer->frameGeometry()); 0376 QPixmap pixmap = m_themedBackgroundRenderer->getScaledBackground(); 0377 if (!pixmap.isNull()) { 0378 m_widget->setPixmap(pixmap); 0379 } 0380 m_themedBackgroundRenderer->updateBackground(); 0381 } 0382 0383 void GuiFrontend::updateFontColors() 0384 { 0385 QPalette p(QApplication::palette()); 0386 QColor c = m_themedBackgroundRenderer->fontColor(QStringLiteral("Outer"), p.color(QPalette::Active, QPalette::WindowText)); 0387 p.setColor(QPalette::WindowText, c); 0388 m_ui->lessonLabel->setPalette(p); 0389 m_ui->gradeLabel->setPalette(p); 0390 0391 if (m_modeWidget) { 0392 p = QApplication::palette(); 0393 c = m_themedBackgroundRenderer->fontColor(QStringLiteral("Central"), p.color(QPalette::Active, QPalette::WindowText)); 0394 p.setColor(QPalette::Active, QPalette::WindowText, c); 0395 p.setColor(QPalette::Inactive, QPalette::WindowText, c); 0396 m_modeWidget->setPalette(p); 0397 0398 KColorScheme scheme(QPalette::Active); 0399 QPalette correctPalette = QApplication::palette(); 0400 c = m_themedBackgroundRenderer->fontColor(QStringLiteral("Correct"), scheme.foreground(KColorScheme::PositiveText).color()); 0401 correctPalette.setColor(QPalette::WindowText, c); 0402 correctPalette.setColor(QPalette::Text, scheme.foreground(KColorScheme::PositiveText).color()); 0403 QPalette wrongPalette = QApplication::palette(); 0404 c = m_themedBackgroundRenderer->fontColor(QStringLiteral("Wrong"), scheme.foreground(KColorScheme::NegativeText).color()); 0405 wrongPalette.setColor(QPalette::WindowText, c); 0406 wrongPalette.setColor(QPalette::Text, scheme.foreground(KColorScheme::NegativeText).color()); 0407 0408 m_modeWidget->setResultPalettes(correctPalette, wrongPalette); 0409 } 0410 } 0411 0412 void GuiFrontend::setTheme() 0413 { 0414 m_themedBackgroundRenderer->setTheme(Prefs::theme()); 0415 updateFontColors(); 0416 updateBackground(); 0417 m_widget->setContentsMargins(m_themedBackgroundRenderer->contentMargins()); 0418 m_ui->boxesWidget->setRenderer(m_themedBackgroundRenderer); 0419 m_ui->statusToggle->setRenderer(m_themedBackgroundRenderer); 0420 } 0421 0422 #include "moc_guifrontend.cpp"