diff options
Diffstat (limited to 'kbruch/src/exercisefactorize.cpp')
-rw-r--r-- | kbruch/src/exercisefactorize.cpp | 652 |
1 files changed, 652 insertions, 0 deletions
diff --git a/kbruch/src/exercisefactorize.cpp b/kbruch/src/exercisefactorize.cpp new file mode 100644 index 00000000..b411e032 --- /dev/null +++ b/kbruch/src/exercisefactorize.cpp @@ -0,0 +1,652 @@ +/*************************************************************************** + exerciseconvert.h + ------------------- + begin : 2004/06/04 + copyright : (C) 2004 by Sebastian Stein + email : seb.kde@hpfsc.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program 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 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "exercisefactorize.h" +#include "exercisefactorize.moc" + +/* these includes are needed for KDE support */ +#include <kapplication.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <knumvalidator.h> + +/* these includes are needed for Qt support */ +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qpushbutton.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +/* standard C++ library includes */ +#include <stdlib.h> + +#include "factorizedwidget.h" +#include "primenumber.h" +#include "rationalwidget.h" +#include "resultwidget.h" +#include "settingsclass.h" + +/* ----- public member functions ----- */ + +/* constructor */ +ExerciseFactorize::ExerciseFactorize(QWidget * parent, const char * name): + ExerciseBase(parent, name) +{ + QPalette pal; + QColorGroup cg; +#ifdef DEBUG + kdDebug() << "constructor ExerciseFactorize()" << endl; +#endif + + /* create a new task */ + QApplication::setOverrideCursor(waitCursor); /* show the sand clock */ + createTask(); + QApplication::restoreOverrideCursor(); /* show the normal cursor */ + + // the next thing to do on a button click would be to check the entered + // result + m_currentState = _CHECK_TASK; + + Form1Layout = new QVBoxLayout( this, 11, 6, "Form1Layout"); + + layout9 = new QVBoxLayout( 0, 0, 6, "layout9"); + + // The following method fix the problem in + // bug #116831, reverse order in RTL desktops. + // Amit Ramon amit.ramon@kdemail.net + layout4 = createFactorsLayout(); + layout9->addLayout(layout4); + + spacer2 = new QSpacerItem( 20, 21, QSizePolicy::Minimum, QSizePolicy::Expanding ); + layout9->addItem( spacer2 ); + + layout2 = new QVBoxLayout( 0, 0, 6, "layout2"); + + // The following method fix the problem in + // bug #116831, reverse order in RTL desktops. + // Amit Ramon amit.ramon@kdemail.net + layout1 = createButtonsLayout(); + layout2->addLayout(layout1); + + m_removeLastFactorButton = new QPushButton( this, "m_removeLastFactorButton" ); + layout2->addWidget( m_removeLastFactorButton ); + layout9->addLayout( layout2 ); + + spacer4 = new QSpacerItem( 20, 21, QSizePolicy::Minimum, QSizePolicy::Expanding ); + layout9->addItem( spacer4 ); + + layout7 = new QHBoxLayout( 0, 0, 6, "layout7"); + spacer3 = new QSpacerItem( 361, 20, QSizePolicy::Expanding, QSizePolicy::Minimum ); + layout7->addItem( spacer3 ); + + m_checkButton = new QPushButton( this, "m_checkButton" ); + layout7->addWidget( m_checkButton ); + layout9->addLayout( layout7 ); + Form1Layout->addLayout( layout9 ); + + // the current task + QString tmp_str; + tmp_str.setNum(m_taskNumber); + m_taskLabel->setText(tmp_str); + + // now set the color for the task label + m_taskLabel->setPaletteForegroundColor(SettingsClass::numberColor()); + + // the equal sign + m_equalSignLabel->setText("="); + + // now set the color for the equal sign + m_equalSignLabel->setPaletteForegroundColor(SettingsClass::operationColor()); + + // the wrong/correct label, we hide it + result_label->setText(i18n("WRONG")); + result_label->hide(); + + // the prime factor buttons + m_factor2Button->setText( i18n( "2" ) ); + m_factor3Button->setText( i18n( "3" ) ); + m_factor5Button->setText( i18n( "5" ) ); + m_factor7Button->setText( i18n( "7" ) ); + m_factor11Button->setText( i18n( "11" ) ); + m_factor13Button->setText( i18n( "13" ) ); + m_factor17Button->setText( i18n( "17" ) ); + m_factor19Button->setText( i18n( "19" ) ); + QObject::connect(m_factor2Button, SIGNAL(clicked()), this, SLOT(slotFactor2ButtonClicked())); + QObject::connect(m_factor3Button, SIGNAL(clicked()), this, SLOT(slotFactor3ButtonClicked())); + QObject::connect(m_factor5Button, SIGNAL(clicked()), this, SLOT(slotFactor5ButtonClicked())); + QObject::connect(m_factor7Button, SIGNAL(clicked()), this, SLOT(slotFactor7ButtonClicked())); + QObject::connect(m_factor11Button, SIGNAL(clicked()), this, SLOT(slotFactor11ButtonClicked())); + QObject::connect(m_factor13Button, SIGNAL(clicked()), this, SLOT(slotFactor13ButtonClicked())); + QObject::connect(m_factor17Button, SIGNAL(clicked()), this, SLOT(slotFactor17ButtonClicked())); + QObject::connect(m_factor19Button, SIGNAL(clicked()), this, SLOT(slotFactor19ButtonClicked())); + + // add tooltips to the factor buttons + QToolTip::add(m_factor2Button, i18n("Add prime factor 2.")); + QToolTip::add(m_factor3Button, i18n("Add prime factor 3.")); + QToolTip::add(m_factor5Button, i18n("Add prime factor 5.")); + QToolTip::add(m_factor7Button, i18n("Add prime factor 7.")); + QToolTip::add(m_factor11Button, i18n("Add prime factor 11.")); + QToolTip::add(m_factor13Button, i18n("Add prime factor 13.")); + QToolTip::add(m_factor17Button, i18n("Add prime factor 17.")); + QToolTip::add(m_factor19Button, i18n("Add prime factor 19.")); + + // the remove last factor button + m_removeLastFactorButton->setText( i18n( "&Remove Last Factor" ) ); + m_removeLastFactorButton->setEnabled(false); + QObject::connect(m_removeLastFactorButton, SIGNAL(clicked()), this, SLOT(slotRemoveLastFactorButtonClicked())); + QToolTip::add(m_removeLastFactorButton, i18n("Removes the last entered prime factor.")); + + // the check task button + m_checkButton->setText( i18n( "&Check Task" ) ); + QToolTip::add(m_checkButton, i18n("Click on this button to check your result. The button will not work if you have not entered a result yet.")); + QObject::connect(m_checkButton, SIGNAL(clicked()), this, SLOT(slotCheckButtonClicked())); + m_checkButton->setDefault(true); // is the default button of the dialog + + // that the user can start choosing the prime factors + m_factor2Button->setFocus(); + + // set the tab order + setTabOrder(m_factor2Button, m_factor3Button); + setTabOrder(m_factor3Button, m_factor5Button); + setTabOrder(m_factor5Button, m_factor7Button); + setTabOrder(m_factor7Button, m_factor11Button); + setTabOrder(m_factor13Button, m_factor17Button); + setTabOrder(m_factor17Button, m_factor19Button); + setTabOrder(m_factor19Button, m_removeLastFactorButton); + + // add tooltip and qwhatsthis help to the widget + QToolTip::add(this, i18n("In this exercise you have to factorize a given number.")); + QWhatsThis::add(this, i18n("In this exercise you have to factorize a given number. You have to enter all prime factors of the number. You can add a prime factor by clicking on the corresponding button. The chosen prime factors will be shown in the input field. Do not forget to enter all prime factors, even when a prime factor repeats several times!")); +} + +/* destructor */ +ExerciseFactorize::~ExerciseFactorize() +{ +#ifdef DEBUG + kdDebug() << "destructor ExerciseFactorize()" << endl; +#endif + + /* no need to delete any child widgets, Qt does it by itself */ +} + +/** resets the current state, creates a new task and count the last task as + * wrong, if it wasn't solved (in _NEXT_TASK state) yet + * mainly used after changing the task parameters */ +void ExerciseFactorize::forceNewTask() +{ +#ifdef DEBUG + kdDebug() << "forceNewTask ExerciseFactorize()" << endl; +#endif + + if (m_currentState == _CHECK_TASK) + { + // emit the signal for wrong + signalExerciseSolvedWrong(); + } + m_currentState = _CHECK_TASK; + m_checkButton->setText(i18n("&Check Task")); + + // generate next task + (void) nextTask(); +} + + +/* ------ public slots ------ */ + +void ExerciseFactorize::update() +{ + // now set the color for the task label + m_taskLabel->setPaletteForegroundColor(SettingsClass::numberColor()); + + // now set the color for the equal sign + m_equalSignLabel->setPaletteForegroundColor(SettingsClass::operationColor()); + + // and the factors + m_factorsWidget->updateAndRepaint(); + + // update for itself + ((QWidget *) this)->update(); +} + + +/* ------ private member functions ------ */ + +// +// The following method was added to fix +// bug #116831 (reverse layout in RTL desktops) +// Amit Ramon amit.ramon@kdemail.net +// + +/** Create the layout that hold the exercise widgets + */ +QHBoxLayout* ExerciseFactorize::createFactorsLayout() +{ + // first create all widgets + QHBoxLayout* layout = new QHBoxLayout( 0, 0, 6, "layout4"); + + m_taskLabel = new QLabel( this, "m_taskLabel" ); + + m_equalSignLabel = new QLabel( this, "m_equalSignLabel" ); + + m_factorsEnteredEdit = new QLineEdit( this, "m_factorsEnteredEdit" ); + m_factorsEnteredEdit->setReadOnly(true); + m_factorsEnteredEdit->setEnabled(false); + m_factorsEnteredEdit->setPaletteForegroundColor(QColor(0, 0, 0)); + + m_factorsWidget = + new FactorizedWidget( this, "m_factorsWidget", m_factorsResult); + + m_factorsWidget->hide(); + + result_label = new QLabel( this, "result_label" ); + + spacer1 = new QSpacerItem( 25, 20, QSizePolicy::Expanding, + QSizePolicy::Minimum ); + + // now add the widgets to the layout. + // if we are in a RTL desktop, add them + // in a reverse order + if (QApplication::reverseLayout()) + { + layout->addItem( spacer1 ); + layout->addWidget( result_label ); + layout->addWidget( m_factorsWidget ); + layout->addWidget( m_factorsEnteredEdit ); + layout->addWidget( m_equalSignLabel ); + layout->addWidget( m_taskLabel ); + } + else + { + layout->addWidget( m_taskLabel ); + layout->addWidget( m_equalSignLabel ); + layout->addWidget( m_factorsEnteredEdit ); + layout->addWidget( m_factorsWidget ); + layout->addWidget( result_label ); + layout->addItem( spacer1 ); + } + + return layout; +} + + +// +// The following method was added to fix +// bug #116831 (reverse layout in RTL desktops) +// Amit Ramon amit.ramon@kdemail.net +// + +/** Create the layout that hold the exercise widgets + */ +QGridLayout* ExerciseFactorize::createButtonsLayout() +{ + const int _COLS = 4; // number of buttons in each row + const int _ROWS = 2; // number of rows + + QGridLayout* layout = new QGridLayout( 0, 1, 1, 0, 6, "layout1"); + + // first row buttons + m_factor2Button = new QPushButton( this, "m_factor2Button" ); + m_factor3Button = new QPushButton( this, "m_factor3Button" ); + m_factor5Button = new QPushButton( this, "m_factor5Button" ); + m_factor7Button = new QPushButton( this, "m_factor7Button" ); + + // second row buttons + m_factor11Button = new QPushButton( this, "m_factor11Button" ); + m_factor13Button = new QPushButton( this, "m_factor13Button" ); + m_factor17Button = new QPushButton( this, "m_factor17Button" ); + m_factor19Button = new QPushButton( this, "m_factor19Button" ); + + // temp array to help with adding the buttons + // to the grid + QPushButton* buttons[_ROWS][_COLS] = + { + { + m_factor2Button, + m_factor3Button, + m_factor5Button, + m_factor7Button + }, + { + m_factor11Button, + m_factor13Button, + m_factor17Button, + m_factor19Button + } + }; + + + int buttonIdxStart = 0; + int step = 1; + + // if we are in a RTL desktop, this helps adding the + // buttons in a reverse order + if (QApplication::reverseLayout()) + { + buttonIdxStart = _COLS - 1; + step = -1; + } + + // now add the buttons to the grid + for (int row = 0; row < _ROWS; row++) + { + int buttonIdx = buttonIdxStart; + + for (int col = 0; col < _COLS; col++) + { + layout->addWidget(buttons[row][buttonIdx], row, col ); + buttonIdx += step; + } + } + + return layout; +} + + +void ExerciseFactorize::createTask() +{ + uint uint_number; + primenumber tmp_primenumber; + + // just pick one number out of the possible numbers to factorize + m_taskNumber = possibleTasks[uint((double(rand()) / RAND_MAX) * numberPossibleTasks)]; + + // now get the primefactors of the taskNumber + m_factorsResult.clear(); + uint_number = m_taskNumber; + tmp_primenumber.move_first(); + do + { + // check if the current primenumber is a divisor + if (uint_number % tmp_primenumber.get_current() != 0) + { + // no, it is not a divisor, go on with next primenumber + tmp_primenumber.move_forward(); + } else { + // current primenumber is a divisor + m_factorsResult.append(tmp_primenumber.get_current()); + uint_number = uint(uint_number / tmp_primenumber.get_current()); + } + } while (uint_number != 1); + + return; +} + +/** - checks, if the user solved the task correctly + - emits signals if task was solved correctly or wrong */ +void ExerciseFactorize::showResult() +{ + QString tmp_str, tmp_str2; /* to build a string for a label */ + QPalette pal; + QColorGroup cg; + uint uint_result = 0; + + // change the tooltip of the check button + QToolTip::add(m_checkButton, i18n("Click on this button to get to the next task.")); + + // disable prime factor buttons + m_factor2Button->setEnabled(false); + m_factor3Button->setEnabled(false); + m_factor5Button->setEnabled(false); + m_factor7Button->setEnabled(false); + m_factor11Button->setEnabled(false); + m_factor13Button->setEnabled(false); + m_factor17Button->setEnabled(false); + m_factor19Button->setEnabled(false); + + // disable factor removal button as well + m_removeLastFactorButton->setEnabled(false); + + // show the result + m_factorsWidget->setFactors(m_factorsResult); + m_factorsWidget->show(); + + // now calculate the product of the prime factors entered by the user + for (uint tmp_uint = 0; tmp_uint < m_factorsEntered.count(); tmp_uint++) + { + if (tmp_uint == 0) + { + uint_result = m_factorsEntered[0]; + } else { + uint_result *= m_factorsEntered[tmp_uint]; + } + } + + if (uint_result == m_taskNumber) + { + // emit the signal for correct + signalExerciseSolvedCorrect(); + + /* yes, the user entered the correct result */ + result_label->setText(i18n("CORRECT")); + pal = result_label->palette(); /* set green font color */ + cg = pal.active(); + cg.setColor(QColorGroup::Foreground, QColor(6, 179, 0)); + pal.setActive(cg); + cg = pal.inactive(); + cg.setColor(QColorGroup::Foreground, QColor(6, 179, 0)); + pal.setInactive(cg); + result_label->setPalette(pal); + } else { + // emit the signal for wrong + signalExerciseSolvedWrong(); + + /* no, the user entered the wrong result */ + result_label->setText(i18n("WRONG")); + pal = result_label->palette(); /* set red font color */ + cg = pal.active(); + cg.setColor(QColorGroup::Foreground, QColor(red)); + pal.setActive(cg); + cg = pal.inactive(); + cg.setColor(QColorGroup::Foreground, QColor(red)); + pal.setInactive(cg); + result_label->setPalette(pal); + + } /* if (entered_result == result) */ + + result_label->show(); /* show the result at the end of the task */ + + return; +} + +/** generate the next task and show it to the user */ +void ExerciseFactorize::nextTask() +{ + // change the tooltip of the check button + QToolTip::add(m_checkButton, i18n("Click on this button to check your result. The button will not work if you have not entered a result yet.")); + + // enable prime factor buttons + m_factor2Button->setEnabled(true); + m_factor3Button->setEnabled(true); + m_factor5Button->setEnabled(true); + m_factor7Button->setEnabled(true); + m_factor11Button->setEnabled(true); + m_factor13Button->setEnabled(true); + m_factor17Button->setEnabled(true); + m_factor19Button->setEnabled(true); + + // disable the factor removal button, there are no factors to be removed yet + m_removeLastFactorButton->setEnabled(false); + + result_label->hide(); /* do not show the result at the end of the task */ + m_factorsWidget->hide(); + + /* clear user input */ + m_factorsEntered.clear(); + m_factorsResult.clear(); + m_factorsEnteredEdit->setText(""); + + m_factor2Button->setFocus(); + + /* create a new task */ + QApplication::setOverrideCursor(waitCursor); /* show the sand clock */ + createTask(); + QApplication::restoreOverrideCursor(); /* show the normal cursor */ + + // update the task widget + QString tmp_str; + tmp_str.setNum(m_taskNumber); + m_taskLabel->setText(tmp_str); + + return; +} + +void ExerciseFactorize::addFactor(uint factor) +{ + // add the new entered factor + m_factorsEntered.append(factor); + + // a factor was added, so the user can can remove one again + m_removeLastFactorButton->setEnabled(true); + + // update the line edit + updateEnteredEdit(); + + return; +} + +void ExerciseFactorize::updateEnteredEdit() +{ + // the string to be shown in the entered edit + QString str_output = ""; + QString str_tmp; + + // find the end of the list + uintList::iterator it; + + + for (it = m_factorsEntered.begin(); it != m_factorsEntered.end(); ++it) + { + // convert the factor into a string + str_tmp.setNum(*it); + + // add the factor with a * + if (it == m_factorsEntered.begin()) + { + str_output = str_tmp; + } else { + str_output += " * " + str_tmp; + } + } + + // set the text into the line edit + m_factorsEnteredEdit->setText(str_output); + + return; +} + +/* ------ private slots ------ */ + +void ExerciseFactorize::slotCheckButtonClicked() +{ + if (m_currentState == _CHECK_TASK) + { + // if nothing has been entered by the user, we don't check the result yet + if (m_factorsEntered.count() == 0) + return; + m_currentState = _NEXT_TASK; + m_checkButton->setText(i18n("N&ext Task")); + (void) showResult(); + } else { + m_currentState = _CHECK_TASK; + m_checkButton->setText(i18n("&Check Task")); + (void) nextTask(); + } + + // update the line edit + updateEnteredEdit(); + + return; +} + +void ExerciseFactorize::slotFactor2ButtonClicked() +{ + addFactor(2); + + return; +} + +void ExerciseFactorize::slotFactor3ButtonClicked() +{ + addFactor(3); + + return; +} + +void ExerciseFactorize::slotFactor5ButtonClicked() +{ + addFactor(5); + + return; +} + +void ExerciseFactorize::slotFactor7ButtonClicked() +{ + addFactor(7); + + return; +} + +void ExerciseFactorize::slotFactor11ButtonClicked() +{ + addFactor(11); + + return; +} + +void ExerciseFactorize::slotFactor13ButtonClicked() +{ + addFactor(13); + + return; +} + +void ExerciseFactorize::slotFactor17ButtonClicked() +{ + addFactor(17); + + return; +} + +void ExerciseFactorize::slotFactor19ButtonClicked() +{ + addFactor(19); + + return; +} + +void ExerciseFactorize::slotRemoveLastFactorButtonClicked() +{ + if (m_factorsEntered.count() > 0) + { + // find the end of the list + uintList::iterator it = m_factorsEntered.end(); + --it; + + // remove last item + m_factorsEntered.remove(it); + } + + // if the list is empty, we have to disable the delete button + if (m_factorsEntered.count() == 0) + m_removeLastFactorButton->setEnabled(false); + + // update the line edit + updateEnteredEdit(); + + return; +} |