You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
328 lines
10 KiB
328 lines
10 KiB
15 years ago
|
/***************************************************************************
|
||
|
exercisecompare.cpp
|
||
|
-------------------
|
||
|
begin : 2004/06/03
|
||
|
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 "exercisecompare.h"
|
||
|
#include "exercisecompare.moc"
|
||
|
|
||
|
/* these includes are needed for KDE support */
|
||
|
#include <kapplication.h>
|
||
|
#include <klocale.h>
|
||
|
|
||
|
/* these includes are needed for Qt support */
|
||
|
#include <qlabel.h>
|
||
|
#include <qlayout.h>
|
||
|
#include <qpushbutton.h>
|
||
|
#include <qtooltip.h>
|
||
|
#include <qwhatsthis.h>
|
||
|
|
||
|
/* standard C++ library includes */
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
/* ----- public member functions ----- */
|
||
|
|
||
|
/* constructor */
|
||
|
ExerciseCompare::ExerciseCompare(QWidget * parent, const char * name):
|
||
|
ExerciseBase(parent, name)
|
||
|
{
|
||
|
#ifdef DEBUG
|
||
|
kdDebug() << "constructor ExerciseCompare()" << 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;
|
||
|
|
||
|
baseWidget = new QWidget(this, "baseWidget");
|
||
|
baseGrid = new QGridLayout(this, 1, 1, 0, -1, "baseGrid");
|
||
|
baseGrid->addWidget(baseWidget, 0, 0);
|
||
|
|
||
|
// this is a VBox
|
||
|
realLayout = new QVBoxLayout(baseWidget, 5, 5, "realLayout");
|
||
|
|
||
|
// add a spacer at the top of the VBox
|
||
|
QSpacerItem * v_spacer = new QSpacerItem(1, 1);
|
||
|
realLayout->addItem(v_spacer);
|
||
|
|
||
|
// now a line holding the task, input fields and result
|
||
|
QHBoxLayout * taskLineHBoxLayout = new QHBoxLayout(5, "taskLineHBoxLayout");
|
||
|
realLayout->addLayout(taskLineHBoxLayout);
|
||
|
|
||
|
// spacer
|
||
|
v_spacer = new QSpacerItem(1, 1);
|
||
|
taskLineHBoxLayout->addItem(v_spacer);
|
||
|
|
||
|
// first the first ratio widget
|
||
|
m_firstRatioWidget = new RatioWidget(baseWidget, "m_firstRatioWidget", m_firstRatio);
|
||
|
taskLineHBoxLayout->addWidget(m_firstRatioWidget);
|
||
|
|
||
|
// spacer
|
||
|
v_spacer = new QSpacerItem(1, 1);
|
||
|
taskLineHBoxLayout->addItem(v_spacer);
|
||
|
|
||
|
// now the button where the user has to choose the comparison sign
|
||
|
m_signButton = new QPushButton(baseWidget, "m_signButton");
|
||
|
|
||
|
// RTL BUG, see slotSignButtonClicked() for more information
|
||
|
m_signButton->setText( QApplication::reverseLayout()?">":"<");
|
||
|
|
||
|
m_signButtonState = lessThen;
|
||
|
taskLineHBoxLayout->addWidget(m_signButton);
|
||
|
QObject::connect(m_signButton, SIGNAL(clicked()), this, SLOT(slotSignButtonClicked()));
|
||
|
QToolTip::add(m_signButton, i18n("Click on this button to change the comparison sign."));
|
||
|
|
||
|
// spacer
|
||
|
v_spacer = new QSpacerItem(1, 1);
|
||
|
taskLineHBoxLayout->addItem(v_spacer);
|
||
|
|
||
|
// now the second ratio widget
|
||
|
m_secondRatioWidget = new RatioWidget(baseWidget, "m_secondRatioWidget", m_secondRatio);
|
||
|
taskLineHBoxLayout->addWidget(m_secondRatioWidget);
|
||
|
|
||
|
// spacer
|
||
|
v_spacer = new QSpacerItem(1, 1);
|
||
|
taskLineHBoxLayout->addItem(v_spacer);
|
||
|
|
||
|
// at the right end we have a label just showing CORRECT or WRONG
|
||
|
result_label = new QLabel(baseWidget, "result_label");
|
||
|
result_label->setText(i18n("WRONG"));
|
||
|
taskLineHBoxLayout->addWidget(result_label);
|
||
|
result_label->hide();
|
||
|
|
||
|
// --- that is the end of the horizontal line ---
|
||
|
|
||
|
// add another spacer in the middle of the VBox
|
||
|
v_spacer = new QSpacerItem(1, 1);
|
||
|
realLayout->addItem(v_spacer);
|
||
|
|
||
|
// the lower part of the VBox holds just a right aligned button
|
||
|
QHBoxLayout * lowerHBox = new QHBoxLayout(1, "lowerHBox");
|
||
|
realLayout->addLayout(lowerHBox);
|
||
|
lowerHBox->addStretch(100);
|
||
|
|
||
|
// the right aligned button
|
||
|
m_checkButton = new QPushButton( baseWidget, "m_checkButton" );
|
||
|
m_checkButton->setText(i18n("&Check Task"));
|
||
|
m_checkButton->setDefault(true); // is the default button of the dialog
|
||
|
QToolTip::add(m_checkButton, i18n("Click on this button to check your result."));
|
||
|
lowerHBox->addWidget(m_checkButton, 1, Qt::AlignRight);
|
||
|
QObject::connect(m_checkButton, SIGNAL(clicked()), this, SLOT(slotCheckButtonClicked()));
|
||
|
|
||
|
// that the user can start typing without moving the focus
|
||
|
m_signButton->setFocus();
|
||
|
|
||
|
// show the whole layout
|
||
|
baseWidget->show();
|
||
|
|
||
|
// add tooltip and qwhatsthis help to the widget
|
||
|
QToolTip::add(this, i18n("In this exercise you have to compare 2 given fractions."));
|
||
|
QWhatsThis::add(this, i18n("In this exercise you have to compare 2 given fractions by choosing the correct comparison sign. You can change the comparison sign by just clicking on the button showing the sign."));
|
||
|
}
|
||
|
|
||
|
/* destructor */
|
||
|
ExerciseCompare::~ExerciseCompare()
|
||
|
{
|
||
|
#ifdef DEBUG
|
||
|
kdDebug() << "destructor ExerciseCompare()" << 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 ExerciseCompare::forceNewTask()
|
||
|
{
|
||
|
#ifdef DEBUG
|
||
|
kdDebug() << "forceNewTask ExerciseCompare()" << 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 ExerciseCompare::update()
|
||
|
{
|
||
|
// call update of components
|
||
|
m_firstRatioWidget->updateAndRepaint();
|
||
|
m_secondRatioWidget->updateAndRepaint();
|
||
|
|
||
|
// update for itself
|
||
|
((QWidget *) this)->update();
|
||
|
}
|
||
|
|
||
|
|
||
|
/* ------ private member functions ------ */
|
||
|
|
||
|
void ExerciseCompare::createTask()
|
||
|
{
|
||
|
// generate the first ratio
|
||
|
m_firstRatio = ratio(int((double(rand()) / RAND_MAX) * 10 + 1), int((double(rand()) / RAND_MAX) * 10 + 1));
|
||
|
|
||
|
// now the second ratio, but make sure, the second ratio is different from
|
||
|
// the first one
|
||
|
do
|
||
|
{
|
||
|
m_secondRatio = ratio(int((double(rand()) / RAND_MAX) * 10 + 1), int((double(rand()) / RAND_MAX) * 10 + 1));
|
||
|
} while (m_firstRatio == m_secondRatio);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/** - checks, if the user solved the task correctly
|
||
|
- emits signals if task was solved correctly or wrong */
|
||
|
void ExerciseCompare::showResult()
|
||
|
{
|
||
|
QPalette pal;
|
||
|
QColorGroup cg;
|
||
|
bool result = m_firstRatio < m_secondRatio;
|
||
|
|
||
|
// change the tooltip of the check button
|
||
|
QToolTip::add(m_checkButton, i18n("Click on this button to get to the next task."));
|
||
|
|
||
|
// disable sign button
|
||
|
m_signButton->setEnabled(false);
|
||
|
|
||
|
if ((m_signButtonState == lessThen && result == true) ||
|
||
|
(m_signButtonState == greaterThen && result == false))
|
||
|
{
|
||
|
// 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);
|
||
|
result_label->show(); /* show the result at the end of the task */
|
||
|
} 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);
|
||
|
|
||
|
result_label->show(); /* show the result at the end of the task */
|
||
|
} /* if (entered_result == result) */
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/** generate the next task and show it to the user */
|
||
|
void ExerciseCompare::nextTask()
|
||
|
{
|
||
|
// change the tooltip of the check button
|
||
|
QToolTip::add(m_checkButton, i18n("Click on this button to check your result."));
|
||
|
|
||
|
// enable sign button
|
||
|
m_signButton->setEnabled(true);
|
||
|
|
||
|
result_label->hide(); /* do not show the result at the end of the task */
|
||
|
|
||
|
// reset the signButton
|
||
|
// RTL BUG, see slotSignButtonClicked() for more information
|
||
|
m_signButton->setText( QApplication::reverseLayout()?">":"<");
|
||
|
m_signButtonState = lessThen;
|
||
|
|
||
|
/* create a new task */
|
||
|
QApplication::setOverrideCursor(waitCursor); /* show the sand clock */
|
||
|
createTask();
|
||
|
QApplication::restoreOverrideCursor(); /* show the normal cursor */
|
||
|
|
||
|
// set the ratio widgets with the new ratios
|
||
|
m_firstRatioWidget->setRatio(m_firstRatio);
|
||
|
m_secondRatioWidget->setRatio(m_secondRatio);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* ------ private slots ------ */
|
||
|
|
||
|
void ExerciseCompare::slotCheckButtonClicked()
|
||
|
{
|
||
|
if (m_currentState == _CHECK_TASK)
|
||
|
{
|
||
|
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();
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void ExerciseCompare::slotSignButtonClicked()
|
||
|
{
|
||
|
// in RTL desktops, we still need to allign the
|
||
|
// execise to the left. On Qt4, you can set the direction
|
||
|
// of the layout to LTR (instead of inherit), but on Qt3
|
||
|
// the only way of fixing it is inserting the widgets in reversed
|
||
|
// order to the layout.
|
||
|
//
|
||
|
// But... as an ugly hack, we can also display the "other" operation
|
||
|
// thats damm ugly, but will work as well :)
|
||
|
//
|
||
|
// See also taskview.cpp for the same bug.
|
||
|
//
|
||
|
// (if you need help with this feel free to contact
|
||
|
// (me - Diego <elcuco@kde.org> )
|
||
|
// This shuold fix parts of bug #116831,
|
||
|
|
||
|
if (m_signButtonState == lessThen)
|
||
|
{
|
||
|
m_signButton->setText( QApplication::reverseLayout()?"<":">");
|
||
|
m_signButtonState = greaterThen;
|
||
|
} else {
|
||
|
m_signButton->setText( QApplication::reverseLayout()?">":"<");
|
||
|
m_signButtonState = lessThen;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|