1 /***************************************************************************
5 copyright : (C) 2004 by Sebastian Stein
6 email : seb.kde@hpfsc.de
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 ***************************************************************************/
18 #include "exercisefactorize.h"
19 #include "exercisefactorize.moc"
21 /* these includes are needed for KDE support */
22 #include <kapplication.h>
24 #include <kmessagebox.h>
25 #include <knumvalidator.h>
27 /* these includes are needed for Qt support */
30 #include <qlineedit.h>
31 #include <qpushbutton.h>
33 #include <qwhatsthis.h>
35 /* standard C++ library includes */
38 #include "factorizedwidget.h"
39 #include "primenumber.h"
40 #include "rationalwidget.h"
41 #include "resultwidget.h"
42 #include "settingsclass.h"
44 /* ----- public member functions ----- */
47 ExerciseFactorize::ExerciseFactorize(QWidget
* parent
, const char * name
):
48 ExerciseBase(parent
, name
)
53 kdDebug() << "constructor ExerciseFactorize()" << endl
;
56 /* create a new task */
57 QApplication::setOverrideCursor(waitCursor
); /* show the sand clock */
59 QApplication::restoreOverrideCursor(); /* show the normal cursor */
61 // the next thing to do on a button click would be to check the entered
63 m_currentState
= _CHECK_TASK
;
65 Form1Layout
= new QVBoxLayout( this, 11, 6, "Form1Layout");
67 layout9
= new QVBoxLayout( 0, 0, 6, "layout9");
69 layout4
= new QHBoxLayout( 0, 0, 6, "layout4");
71 m_taskLabel
= new QLabel( this, "m_taskLabel" );
72 layout4
->addWidget( m_taskLabel
);
74 m_equalSignLabel
= new QLabel( this, "m_equalSignLabel" );
75 layout4
->addWidget( m_equalSignLabel
);
77 m_factorsEnteredEdit
= new QLineEdit( this, "m_factorsEnteredEdit" );
78 layout4
->addWidget( m_factorsEnteredEdit
);
79 m_factorsEnteredEdit
->setReadOnly(true);
80 m_factorsEnteredEdit
->setEnabled(false);
81 m_factorsEnteredEdit
->setPaletteForegroundColor(QColor(0, 0, 0));
83 m_factorsWidget
= new FactorizedWidget( this, "m_factorsWidget", m_factorsResult
);
84 layout4
->addWidget( m_factorsWidget
);
85 m_factorsWidget
->hide();
87 result_label
= new QLabel( this, "result_label" );
88 layout4
->addWidget( result_label
);
89 spacer1
= new QSpacerItem( 25, 20, QSizePolicy::Expanding
, QSizePolicy::Minimum
);
90 layout4
->addItem( spacer1
);
92 layout9
->addLayout( layout4
);
93 spacer2
= new QSpacerItem( 20, 21, QSizePolicy::Minimum
, QSizePolicy::Expanding
);
94 layout9
->addItem( spacer2
);
96 layout2
= new QVBoxLayout( 0, 0, 6, "layout2");
98 layout1
= new QGridLayout( 0, 1, 1, 0, 6, "layout1");
100 m_factor3Button
= new QPushButton( this, "m_factor3Button" );
101 layout1
->addWidget( m_factor3Button
, 0, 1 );
103 m_factor2Button
= new QPushButton( this, "m_factor2Button" );
104 layout1
->addWidget( m_factor2Button
, 0, 0 );
106 m_factor13Button
= new QPushButton( this, "m_factor13Button" );
107 layout1
->addWidget( m_factor13Button
, 1, 1 );
109 m_factor7Button
= new QPushButton( this, "m_factor7Button" );
110 layout1
->addWidget( m_factor7Button
, 0, 3 );
112 m_factor11Button
= new QPushButton( this, "m_factor11Button" );
113 layout1
->addWidget( m_factor11Button
, 1, 0 );
115 m_factor19Button
= new QPushButton( this, "m_factor19Button" );
116 layout1
->addWidget( m_factor19Button
, 1, 3 );
118 m_factor5Button
= new QPushButton( this, "m_factor5Button" );
119 layout1
->addWidget( m_factor5Button
, 0, 2 );
121 m_factor17Button
= new QPushButton( this, "m_factor17Button" );
122 layout1
->addWidget( m_factor17Button
, 1, 2 );
124 layout2
->addLayout( layout1
);
126 m_removeLastFactorButton
= new QPushButton( this, "m_removeLastFactorButton" );
127 layout2
->addWidget( m_removeLastFactorButton
);
128 layout9
->addLayout( layout2
);
130 spacer4
= new QSpacerItem( 20, 21, QSizePolicy::Minimum
, QSizePolicy::Expanding
);
131 layout9
->addItem( spacer4
);
133 layout7
= new QHBoxLayout( 0, 0, 6, "layout7");
134 spacer3
= new QSpacerItem( 361, 20, QSizePolicy::Expanding
, QSizePolicy::Minimum
);
135 layout7
->addItem( spacer3
);
137 m_checkButton
= new QPushButton( this, "m_checkButton" );
138 layout7
->addWidget( m_checkButton
);
139 layout9
->addLayout( layout7
);
140 Form1Layout
->addLayout( layout9
);
144 tmp_str
.setNum(m_taskNumber
);
145 m_taskLabel
->setText(tmp_str
);
147 // now set the color for the task label
148 m_taskLabel
->setPaletteForegroundColor(SettingsClass::numberColor());
151 m_equalSignLabel
->setText("=");
153 // now set the color for the equal sign
154 m_equalSignLabel
->setPaletteForegroundColor(SettingsClass::operationColor());
156 // the wrong/correct label, we hide it
157 result_label
->setText(i18n("WRONG"));
158 result_label
->hide();
160 // the prime factor buttons
161 m_factor2Button
->setText( i18n( "2" ) );
162 m_factor3Button
->setText( i18n( "3" ) );
163 m_factor5Button
->setText( i18n( "5" ) );
164 m_factor7Button
->setText( i18n( "7" ) );
165 m_factor11Button
->setText( i18n( "11" ) );
166 m_factor13Button
->setText( i18n( "13" ) );
167 m_factor17Button
->setText( i18n( "17" ) );
168 m_factor19Button
->setText( i18n( "19" ) );
169 QObject::connect(m_factor2Button
, SIGNAL(clicked()), this, SLOT(slotFactor2ButtonClicked()));
170 QObject::connect(m_factor3Button
, SIGNAL(clicked()), this, SLOT(slotFactor3ButtonClicked()));
171 QObject::connect(m_factor5Button
, SIGNAL(clicked()), this, SLOT(slotFactor5ButtonClicked()));
172 QObject::connect(m_factor7Button
, SIGNAL(clicked()), this, SLOT(slotFactor7ButtonClicked()));
173 QObject::connect(m_factor11Button
, SIGNAL(clicked()), this, SLOT(slotFactor11ButtonClicked()));
174 QObject::connect(m_factor13Button
, SIGNAL(clicked()), this, SLOT(slotFactor13ButtonClicked()));
175 QObject::connect(m_factor17Button
, SIGNAL(clicked()), this, SLOT(slotFactor17ButtonClicked()));
176 QObject::connect(m_factor19Button
, SIGNAL(clicked()), this, SLOT(slotFactor19ButtonClicked()));
178 // add tooltips to the factor buttons
179 QToolTip::add(m_factor2Button
, i18n("Add prime factor 2."));
180 QToolTip::add(m_factor3Button
, i18n("Add prime factor 3."));
181 QToolTip::add(m_factor5Button
, i18n("Add prime factor 5."));
182 QToolTip::add(m_factor7Button
, i18n("Add prime factor 7."));
183 QToolTip::add(m_factor11Button
, i18n("Add prime factor 11."));
184 QToolTip::add(m_factor13Button
, i18n("Add prime factor 13."));
185 QToolTip::add(m_factor17Button
, i18n("Add prime factor 17."));
186 QToolTip::add(m_factor19Button
, i18n("Add prime factor 19."));
188 // the remove last factor button
189 m_removeLastFactorButton
->setText( i18n( "&Remove Last Factor" ) );
190 m_removeLastFactorButton
->setEnabled(false);
191 QObject::connect(m_removeLastFactorButton
, SIGNAL(clicked()), this, SLOT(slotRemoveLastFactorButtonClicked()));
192 QToolTip::add(m_removeLastFactorButton
, i18n("Removes the last entered prime factor."));
194 // the check task button
195 m_checkButton
->setText( i18n( "&Check Task" ) );
196 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."));
197 QObject::connect(m_checkButton
, SIGNAL(clicked()), this, SLOT(slotCheckButtonClicked()));
198 m_checkButton
->setDefault(true); // is the default button of the dialog
200 // that the user can start choosing the prime factors
201 m_factor2Button
->setFocus();
204 setTabOrder(m_factor2Button
, m_factor3Button
);
205 setTabOrder(m_factor3Button
, m_factor5Button
);
206 setTabOrder(m_factor5Button
, m_factor7Button
);
207 setTabOrder(m_factor7Button
, m_factor11Button
);
208 setTabOrder(m_factor13Button
, m_factor17Button
);
209 setTabOrder(m_factor17Button
, m_factor19Button
);
210 setTabOrder(m_factor19Button
, m_removeLastFactorButton
);
212 // add tooltip and qwhatsthis help to the widget
213 QToolTip::add(this, i18n("In this exercise you have to factorize a given number."));
214 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!"));
218 ExerciseFactorize::~ExerciseFactorize()
221 kdDebug() << "destructor ExerciseFactorize()" << endl
;
224 /* no need to delete any child widgets, Qt does it by itself */
227 /** resets the current state, creates a new task and count the last task as
228 * wrong, if it wasn't solved (in _NEXT_TASK state) yet
229 * mainly used after changing the task parameters */
230 void ExerciseFactorize::forceNewTask()
233 kdDebug() << "forceNewTask ExerciseFactorize()" << endl
;
236 if (m_currentState
== _CHECK_TASK
)
238 // emit the signal for wrong
239 signalExerciseSolvedWrong();
241 m_currentState
= _CHECK_TASK
;
242 m_checkButton
->setText(i18n("&Check Task"));
244 // generate next task
249 /* ------ public slots ------ */
251 void ExerciseFactorize::update()
253 // now set the color for the task label
254 m_taskLabel
->setPaletteForegroundColor(SettingsClass::numberColor());
256 // now set the color for the equal sign
257 m_equalSignLabel
->setPaletteForegroundColor(SettingsClass::operationColor());
260 m_factorsWidget
->updateAndRepaint();
263 ((QWidget
*) this)->update();
267 /* ------ private member functions ------ */
269 void ExerciseFactorize::createTask()
272 primenumber tmp_primenumber
;
274 // just pick one number out of the possible numbers to factorize
275 m_taskNumber
= possibleTasks
[uint((double(rand()) / RAND_MAX
) * numberPossibleTasks
)];
277 // now get the primefactors of the taskNumber
278 m_factorsResult
.clear();
279 uint_number
= m_taskNumber
;
280 tmp_primenumber
.move_first();
283 // check if the current primenumber is a divisor
284 if (uint_number
% tmp_primenumber
.get_current() != 0)
286 // no, it is not a divisor, go on with next primenumber
287 tmp_primenumber
.move_forward();
289 // current primenumber is a divisor
290 m_factorsResult
.append(tmp_primenumber
.get_current());
291 uint_number
= uint(uint_number
/ tmp_primenumber
.get_current());
293 } while (uint_number
!= 1);
298 /** - checks, if the user solved the task correctly
299 - emits signals if task was solved correctly or wrong */
300 void ExerciseFactorize::showResult()
302 QString tmp_str
, tmp_str2
; /* to build a string for a label */
305 uint uint_result
= 0;
307 // change the tooltip of the check button
308 QToolTip::add(m_checkButton
, i18n("Click on this button to get to the next task."));
310 // disable prime factor buttons
311 m_factor2Button
->setEnabled(false);
312 m_factor3Button
->setEnabled(false);
313 m_factor5Button
->setEnabled(false);
314 m_factor7Button
->setEnabled(false);
315 m_factor11Button
->setEnabled(false);
316 m_factor13Button
->setEnabled(false);
317 m_factor17Button
->setEnabled(false);
318 m_factor19Button
->setEnabled(false);
320 // disable factor removal button as well
321 m_removeLastFactorButton
->setEnabled(false);
324 m_factorsWidget
->setFactors(m_factorsResult
);
325 m_factorsWidget
->show();
327 // now calculate the product of the prime factors entered by the user
328 for (uint tmp_uint
= 0; tmp_uint
< m_factorsEntered
.count(); tmp_uint
++)
332 uint_result
= m_factorsEntered
[0];
334 uint_result
*= m_factorsEntered
[tmp_uint
];
338 if (uint_result
== m_taskNumber
)
340 // emit the signal for correct
341 signalExerciseSolvedCorrect();
343 /* yes, the user entered the correct result */
344 result_label
->setText(i18n("CORRECT"));
345 pal
= result_label
->palette(); /* set green font color */
347 cg
.setColor(QColorGroup::Foreground
, QColor(6, 179, 0));
350 cg
.setColor(QColorGroup::Foreground
, QColor(6, 179, 0));
352 result_label
->setPalette(pal
);
354 // emit the signal for wrong
355 signalExerciseSolvedWrong();
357 /* no, the user entered the wrong result */
358 result_label
->setText(i18n("WRONG"));
359 pal
= result_label
->palette(); /* set red font color */
361 cg
.setColor(QColorGroup::Foreground
, QColor(red
));
364 cg
.setColor(QColorGroup::Foreground
, QColor(red
));
366 result_label
->setPalette(pal
);
368 } /* if (entered_result == result) */
370 result_label
->show(); /* show the result at the end of the task */
375 /** generate the next task and show it to the user */
376 void ExerciseFactorize::nextTask()
378 // change the tooltip of the check button
379 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."));
381 // enable prime factor buttons
382 m_factor2Button
->setEnabled(true);
383 m_factor3Button
->setEnabled(true);
384 m_factor5Button
->setEnabled(true);
385 m_factor7Button
->setEnabled(true);
386 m_factor11Button
->setEnabled(true);
387 m_factor13Button
->setEnabled(true);
388 m_factor17Button
->setEnabled(true);
389 m_factor19Button
->setEnabled(true);
391 // disable the factor removal button, there are no factors to be removed yet
392 m_removeLastFactorButton
->setEnabled(false);
394 result_label
->hide(); /* do not show the result at the end of the task */
395 m_factorsWidget
->hide();
397 /* clear user input */
398 m_factorsEntered
.clear();
399 m_factorsResult
.clear();
400 m_factorsEnteredEdit
->setText("");
402 m_factor2Button
->setFocus();
404 /* create a new task */
405 QApplication::setOverrideCursor(waitCursor
); /* show the sand clock */
407 QApplication::restoreOverrideCursor(); /* show the normal cursor */
409 // update the task widget
411 tmp_str
.setNum(m_taskNumber
);
412 m_taskLabel
->setText(tmp_str
);
417 void ExerciseFactorize::addFactor(uint factor
)
419 // add the new entered factor
420 m_factorsEntered
.append(factor
);
422 // a factor was added, so the user can can remove one again
423 m_removeLastFactorButton
->setEnabled(true);
425 // update the line edit
431 void ExerciseFactorize::updateEnteredEdit()
433 // the string to be shown in the entered edit
434 QString str_output
= "";
437 // find the end of the list
438 uintList::iterator it
;
441 for (it
= m_factorsEntered
.begin(); it
!= m_factorsEntered
.end(); ++it
)
443 // convert the factor into a string
446 // add the factor with a *
447 if (it
== m_factorsEntered
.begin())
449 str_output
= str_tmp
;
451 str_output
+= " * " + str_tmp
;
455 // set the text into the line edit
456 m_factorsEnteredEdit
->setText(str_output
);
461 /* ------ private slots ------ */
463 void ExerciseFactorize::slotCheckButtonClicked()
465 if (m_currentState
== _CHECK_TASK
)
467 // if nothing has been entered by the user, we don't check the result yet
468 if (m_factorsEntered
.count() == 0)
470 m_currentState
= _NEXT_TASK
;
471 m_checkButton
->setText(i18n("N&ext Task"));
474 m_currentState
= _CHECK_TASK
;
475 m_checkButton
->setText(i18n("&Check Task"));
479 // update the line edit
485 void ExerciseFactorize::slotFactor2ButtonClicked()
492 void ExerciseFactorize::slotFactor3ButtonClicked()
499 void ExerciseFactorize::slotFactor5ButtonClicked()
506 void ExerciseFactorize::slotFactor7ButtonClicked()
513 void ExerciseFactorize::slotFactor11ButtonClicked()
520 void ExerciseFactorize::slotFactor13ButtonClicked()
527 void ExerciseFactorize::slotFactor17ButtonClicked()
534 void ExerciseFactorize::slotFactor19ButtonClicked()
541 void ExerciseFactorize::slotRemoveLastFactorButtonClicked()
543 if (m_factorsEntered
.count() > 0)
545 // find the end of the list
546 uintList::iterator it
= m_factorsEntered
.end();
550 m_factorsEntered
.remove(it
);
553 // if the list is empty, we have to disable the delete button
554 if (m_factorsEntered
.count() == 0)
555 m_removeLastFactorButton
->setEnabled(false);
557 // update the line edit