File indexing completed on 2024-04-21 03:41:48
0001 /* 0002 SPDX-FileCopyrightText: 2008 Tiago Porangaba <tiago.porangaba@ltia.fc.unesp.br> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "ExercisePercentage.h" 0008 0009 /* these includes are needed for KDE support */ 0010 #include <KLocalizedString> 0011 0012 /* these includes are needed for Qt support */ 0013 #include <QApplication> 0014 #include <QGridLayout> 0015 #include <QIntValidator> 0016 #include <QLineEdit> 0017 #include <QPushButton> 0018 #include <QRandomGenerator> 0019 0020 #ifdef DEBUG 0021 #include <QDebug> 0022 #endif 0023 0024 /* standard C++ library includes */ 0025 #include <cstdlib> 0026 0027 #include "RationalWidget.h" 0028 #include "ResultWidget.h" 0029 #include "settingsclass.h" 0030 0031 /* ----- public member functions ----- */ 0032 0033 /* constructor */ 0034 ExercisePercentage::ExercisePercentage(QWidget * parent) : 0035 ExerciseBase(parent) 0036 { 0037 #ifdef DEBUG 0038 qDebug() << QStringLiteral("constructor ExercisePercentage()"); 0039 #endif 0040 0041 /* create a new task */ 0042 QApplication::setOverrideCursor(Qt::WaitCursor); /* show the sand clock */ 0043 createTask(); 0044 QApplication::restoreOverrideCursor(); /* show the normal cursor */ 0045 0046 // to validate, that the input is an int 0047 QIntValidator *valnum = new QIntValidator(this); 0048 0049 QFont defaultFont = SettingsClass::taskFont(); 0050 defaultFont.setBold(true); 0051 defaultFont.setPointSize(10); 0052 0053 // the next thing to do on a button click would be to check the entered 0054 // result 0055 m_currentState = _CHECK_TASK; 0056 0057 taskWidget = new QWidget(this); 0058 taskWidget->setObjectName(QStringLiteral("taskWidget")); 0059 checkWidget = new QWidget(this); 0060 checkWidget->setObjectName(QStringLiteral("checkWidget")); 0061 0062 baseGrid = new QGridLayout(this); 0063 baseGrid->setObjectName(QStringLiteral("baseGrid")); 0064 baseGrid->setColumnStretch(0, 1); 0065 0066 baseGrid->addWidget(taskWidget, 0, 0); 0067 baseGrid->addWidget(checkWidget, 0, 1); 0068 0069 taskLayout = new QGridLayout(taskWidget); 0070 taskLayout->setObjectName(QStringLiteral("taskLayout")); 0071 taskLayout->setRowStretch(0, 1); 0072 taskLayout->setRowStretch(4, 1); 0073 taskLayout->setColumnStretch(0, 1); 0074 taskLayout->setColumnStretch(3, 1); 0075 0076 checkLayout = new QGridLayout(checkWidget); 0077 checkLayout->setObjectName(QStringLiteral("checkLayout")); 0078 0079 /* Task: percentage question */ 0080 defaultFont.setPointSize(16); 0081 m_taskLabel = new QLabel(this); 0082 m_taskLabel->setObjectName(QStringLiteral("m_taskLabel")); 0083 m_taskLabel->setFont(defaultFont); 0084 m_taskLabel->setText(i18nc("%1 percentage of %2", "%1% of %2 = ", m_numberPercentage , m_numberPercentageOf)); 0085 taskLayout->addWidget(m_taskLabel, 1, 1, 2, 1); 0086 0087 /* Input question: result of question */ 0088 answer_edit = new QLineEdit(taskWidget); 0089 answer_edit->setObjectName(QStringLiteral("answer_edit")); 0090 answer_edit->setValidator(valnum); // use the int validator 0091 answer_edit->setToolTip(i18n("Enter the result of percentage question")); 0092 answer_edit->setFixedSize(85, 42); 0093 answer_edit->setAlignment(Qt::AlignHCenter); 0094 answer_edit->setFont(defaultFont); 0095 QObject::connect(answer_edit, &QLineEdit::returnPressed, this, &ExercisePercentage::answerReturnPressed); 0096 taskLayout->addWidget(answer_edit, 1, 2, 2, 1); 0097 0098 // next is the result widget 0099 m_resultWidget = new ResultWidget(checkWidget, m_result); 0100 m_resultWidget->setObjectName(QStringLiteral("m_resultWidget")); 0101 checkLayout->addWidget(m_resultWidget, 0, 0, 1, 2); 0102 0103 // the right aligned button 0104 defaultFont.setPointSize(10); 0105 m_checkButton = new QPushButton(checkWidget); 0106 m_checkButton->setObjectName(QStringLiteral("m_checkButton")); 0107 m_checkButton->setText(i18n("&Check")); 0108 m_checkButton->setDefault(true); // is the default button of the dialog 0109 m_checkButton->setToolTip(i18n("Click on this button to check your result. The button will not work if you have not entered a result yet.")); 0110 m_checkButton->setFont(defaultFont); 0111 QObject::connect(m_checkButton, &QPushButton::clicked, this, &ExercisePercentage::slotCheckButtonClicked); 0112 checkLayout->addWidget(m_checkButton, 2, 0); 0113 0114 // the right aligned button 0115 m_skipButton = new QPushButton(checkWidget); 0116 m_skipButton->setObjectName(QStringLiteral("m_skipButton")); 0117 m_skipButton->setText(i18n("&Skip")); 0118 m_skipButton->setToolTip(i18n("Click on this button to skip this question.")); 0119 m_skipButton->setFont(defaultFont); 0120 QObject::connect(m_skipButton, &QPushButton::clicked, this, &ExercisePercentage::slotSkipButtonClicked); 0121 checkLayout->addWidget(m_skipButton, 2, 1); 0122 0123 // that the user can start typing without moving the focus 0124 //numer_edit->setFocus(); 0125 answer_edit->setFocus(); 0126 0127 setLayout(baseGrid); 0128 taskWidget->setLayout(taskLayout); 0129 checkWidget->setLayout(checkLayout); 0130 0131 // add tooltip and qwhatsthis help to the widget 0132 setToolTip(i18n("In this exercise you have to work with percentage questions.")); 0133 setWhatsThis(i18n("In this exercise you have to enter the fraction of the given number.")); 0134 0135 } 0136 0137 /* destructor */ 0138 ExercisePercentage::~ExercisePercentage() 0139 { 0140 #ifdef DEBUG 0141 qDebug() << QStringLiteral("destructor ExercisePercentage()"); 0142 #endif 0143 0144 /* no need to delete any child widgets, Qt does it by itself */ 0145 } 0146 0147 /** resets the current state, creates a new task and count the last task as 0148 * wrong, if it wasn't solved (in _NEXT_TASK state) yet 0149 * mainly used after changing the task parameters */ 0150 void ExercisePercentage::forceNewTask() 0151 { 0152 #ifdef DEBUG 0153 qDebug() << QStringLiteral("forceNewTask ExercisePercentage()"); 0154 #endif 0155 0156 if (m_currentState == _CHECK_TASK) { 0157 // emit the signal for skipped 0158 Q_EMIT signalExerciseSkipped(); 0159 } 0160 m_currentState = _CHECK_TASK; 0161 m_checkButton->setText(i18n("&Check")); 0162 0163 // generate next task 0164 (void) nextTask(); 0165 } 0166 0167 0168 /* ------ public slots ------ */ 0169 0170 void ExercisePercentage::update() 0171 { 0172 // call update of components 0173 //m_rationalWidget->updateAndRepaint(); 0174 m_resultWidget->updateAndRepaint(); 0175 0176 // update for itself 0177 ((QWidget *) this)->update(); 0178 } 0179 0180 0181 /* ------ private member functions ------ */ 0182 0183 void ExercisePercentage::createTask() 0184 { 0185 // the tasks are hardcoded here; there are some algorithms to convert 0186 // rational numbers to fractions, but it is not worth the effort here 0187 switch (QRandomGenerator::global()->bounded(19)) { 0188 case 0 : 0189 //m_number = QLocale().toString(0.5, 'f', 1); 0190 m_numberPercentage = QStringLiteral("75"); 0191 m_numberPercentageOf = QStringLiteral("1900"); 0192 m_resultPercentage = QStringLiteral("1425"); 0193 break; 0194 case 1 : 0195 //m_number = QLocale().toString(0.3, 'f', 1); 0196 m_numberPercentage = QStringLiteral("50"); 0197 m_numberPercentageOf = QStringLiteral("1800"); 0198 m_resultPercentage = QStringLiteral("900"); 0199 break; 0200 case 2 : 0201 //m_number = QLocale().toString(0.6, 'f', 1); 0202 m_numberPercentage = QStringLiteral("1"); 0203 m_numberPercentageOf = QStringLiteral("1200"); 0204 m_resultPercentage = QStringLiteral("12"); 0205 break; 0206 case 3 : 0207 //m_number = QLocale().toString(0.25, 'f', 2); 0208 m_numberPercentage = QStringLiteral("10"); 0209 m_numberPercentageOf = QStringLiteral("900"); 0210 m_resultPercentage = QStringLiteral("90"); 0211 break; 0212 case 4 : 0213 //m_number = QLocale().toString(0.75, 'f', 2); 0214 m_numberPercentage = QStringLiteral("100"); 0215 m_numberPercentageOf = QStringLiteral("800"); 0216 m_resultPercentage = QStringLiteral("800"); 0217 break; 0218 case 5 : 0219 //m_number = QLocale().toString(0.2, 'f', 1); 0220 m_numberPercentage = QStringLiteral("75"); 0221 m_numberPercentageOf = QStringLiteral("300"); 0222 m_resultPercentage = QStringLiteral("225"); 0223 break; 0224 case 6 : 0225 //m_number = QLocale().toString(0.4, 'f', 1); 0226 m_numberPercentage = QStringLiteral("10"); 0227 m_numberPercentageOf = QStringLiteral("1500"); 0228 m_resultPercentage = QStringLiteral("150"); 0229 break; 0230 case 7 : 0231 //m_number = QLocale().toString(0.6, 'f', 1); 0232 m_numberPercentage = QStringLiteral("10"); 0233 m_numberPercentageOf = QStringLiteral("100"); 0234 m_resultPercentage = QStringLiteral("10"); 0235 break; 0236 case 8 : 0237 //m_number = QLocale().toString(0.8, 'f', 1); 0238 m_numberPercentage = QStringLiteral("25"); 0239 m_numberPercentageOf = QStringLiteral("400"); 0240 m_resultPercentage = QStringLiteral("100"); 0241 break; 0242 case 9 : 0243 //m_number = QLocale().toString(0.16, 'f', 2); 0244 m_numberPercentage = QStringLiteral("50"); 0245 m_numberPercentageOf = QStringLiteral("800"); 0246 m_resultPercentage = QStringLiteral("400"); 0247 break; 0248 case 10 : 0249 //m_number = QLocale().toString(0.142857, 'f', 6); 0250 m_numberPercentage = QStringLiteral("1"); 0251 m_numberPercentageOf = QStringLiteral("400"); 0252 m_resultPercentage = QStringLiteral("4"); 0253 break; 0254 case 11 : 0255 //m_number = QLocale().toString(0.125, 'f', 3); 0256 m_numberPercentage = QStringLiteral("50"); 0257 m_numberPercentageOf = QStringLiteral("600"); 0258 m_resultPercentage = QStringLiteral("300"); 0259 break; 0260 case 12 : 0261 //m_number = QLocale().toString(0.375, 'f', 3); 0262 m_numberPercentage = QStringLiteral("100"); 0263 m_numberPercentageOf = QStringLiteral("1300"); 0264 m_resultPercentage = QStringLiteral("1300"); 0265 break; 0266 case 13 : 0267 //m_number = QLocale().toString(0.1, 'f', 1); 0268 m_numberPercentage = QStringLiteral("100"); 0269 m_numberPercentageOf = QStringLiteral("800"); 0270 m_resultPercentage = QStringLiteral("800"); 0271 break; 0272 case 14 : 0273 //m_number = QLocale().toString(0.1, 'f', 1); 0274 m_numberPercentage = QStringLiteral("25"); 0275 m_numberPercentageOf = QStringLiteral("1400"); 0276 m_resultPercentage = QStringLiteral("350"); 0277 break; 0278 case 15 : 0279 //m_number = QLocale().toString(0.05, 'f', 2); 0280 m_numberPercentage = QStringLiteral("10"); 0281 m_numberPercentageOf = QStringLiteral("1400"); 0282 m_resultPercentage = QStringLiteral("140"); 0283 break; 0284 case 16 : 0285 //m_number = QLocale().toString(0.01, 'f', 2); 0286 m_numberPercentage = QStringLiteral("1"); 0287 m_numberPercentageOf = QStringLiteral("2000"); 0288 m_resultPercentage = QStringLiteral("20"); 0289 break; 0290 case 17 : 0291 //m_number = QLocale().toString(0.83, 'f', 2); 0292 m_numberPercentage = QStringLiteral("75"); 0293 m_numberPercentageOf = QStringLiteral("1000"); 0294 m_resultPercentage = QStringLiteral("750"); 0295 break; 0296 default : 0297 case 18 : 0298 //m_number = QLocale().toString(0.001, 'f', 3); 0299 m_numberPercentage = QStringLiteral("75"); 0300 m_numberPercentageOf = QStringLiteral("1100"); 0301 m_resultPercentage = QStringLiteral("825"); 0302 break; 0303 } 0304 0305 return; 0306 } 0307 0308 /** - checks, if the user solved the task correctly 0309 - emits signals if task was solved correctly or wrong */ 0310 void ExercisePercentage::showResult() 0311 { 0312 int tmp_result; 0313 Ratio entered_result; 0314 Ratio correct_result; 0315 0316 // change the tooltip of the check button 0317 m_checkButton->setToolTip(i18n("Click on this button to get to the next question.")); 0318 0319 answer_edit->setEnabled(false); 0320 m_skipButton->setEnabled(false); 0321 0322 //an empty answer field will be interpreted as 0 0323 if (answer_edit->text().isEmpty() == true) 0324 answer_edit->setText(QStringLiteral("0")); 0325 0326 0327 tmp_result = answer_edit->text().toInt(); 0328 entered_result.setNumerator(tmp_result, false); 0329 entered_result.setDenominator(1, false); 0330 correct_result.setNumerator(m_resultPercentage.toInt()); 0331 correct_result.setDenominator(1, false); 0332 if (tmp_result == m_resultPercentage.toInt()) { 0333 // emit the signal for correct 0334 Q_EMIT signalExerciseSolvedCorrect(); 0335 /* yes, the user entered the correct result */ 0336 m_resultWidget->setResult(entered_result, 1); 0337 } else { 0338 // emit the signal for incorrect 0339 Q_EMIT signalExerciseSolvedWrong(); 0340 /* no, the user entered the wrong result */ 0341 m_resultWidget->setResult(correct_result, 0); 0342 } 0343 0344 return; 0345 } 0346 0347 /** generate the next task and show it to the user */ 0348 void ExercisePercentage::nextTask() 0349 { 0350 // change the tooltip of the check button 0351 m_checkButton->setToolTip(i18n("Click on this button to check your result. The button will not work if you have not entered a result yet.")); 0352 0353 answer_edit->setEnabled(true); 0354 m_skipButton->setEnabled(true); 0355 0356 m_resultWidget->setResult(m_result, -1); 0357 0358 /* clear user input */ 0359 answer_edit->clear(); 0360 answer_edit->setFocus(); 0361 0362 /* create a new task */ 0363 QApplication::setOverrideCursor(Qt::WaitCursor); /* show the sand clock */ 0364 createTask(); 0365 QApplication::restoreOverrideCursor(); /* show the normal cursor */ 0366 0367 // update the task widget 0368 QString tempTask = i18nc("%1 percentage of %2", "%1% of %2 = ", m_numberPercentage, m_numberPercentageOf); 0369 m_taskLabel->setText(tempTask); 0370 0371 return; 0372 } 0373 0374 /* ------ private slots ------ */ 0375 0376 void ExercisePercentage::slotCheckButtonClicked() 0377 { 0378 if (m_currentState == _CHECK_TASK) { 0379 // if nothing has been entered by the user, we don't check the result yet 0380 if (answer_edit->text().isEmpty() == true) 0381 return; 0382 m_currentState = _NEXT_TASK; 0383 m_checkButton->setText(i18n("N&ext")); 0384 (void) showResult(); 0385 } else { 0386 m_currentState = _CHECK_TASK; 0387 m_checkButton->setText(i18n("&Check")); 0388 (void) nextTask(); 0389 } 0390 0391 return; 0392 } 0393 0394 void ExercisePercentage::slotSkipButtonClicked() 0395 { 0396 forceNewTask(); 0397 } 0398 0399 void ExercisePercentage::answerReturnPressed() 0400 { 0401 slotCheckButtonClicked(); 0402 } 0403 0404 #include "moc_ExercisePercentage.cpp"