/*************************************************************************** keducaview.cpp - description ------------------- begin : Thu May 24 2001 copyright : (C) 2001 by Javier Campos email : javi@asyris.org ***************************************************************************/ /*************************************************************************** * * * 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 "keducaview.h" #include "keducaview.moc" #include "settings.h" #include "../libkeduca/fileread.h" #include "kquestion.h" #include "kgroupeduca.h" #include #include #include #include #include #include #include #include #include #include #include #include KEducaView::KEducaView( TQWidget *parent, const char *name ) : TQWidgetStack( parent, name ), _keducaFile( 0 ), _timeoutTimer( 0 ) { init(); } KEducaView::~KEducaView() { delete _questionText; delete _buttonGroup; delete _split; delete _buttonNext; delete _buttonSave; delete _viewResults; delete _keducaFile; } /** Init graphical interface */ void KEducaView::init() { // Intro Screen _introWidget = new TQLabel( this, "introScreen" ); _introWidget->setBackgroundColor( TQt::white ); _introWidget->setAlignment( AlignCenter ); _introWidget->setPixmap( TQPixmap( locate("data","keduca/pics/keduca_init.png") ) ); addWidget( _introWidget, 0 ); // Info Widget _infoWidget = new TQVBox( this, "infoWidget" ); _viewInfo = new TQTextEdit( _infoWidget ); _viewInfo->setReadOnly( true ); _buttonStartTest = new KPushButton( i18n( "&Start Test" ), _infoWidget ); connect( _buttonStartTest, TQT_SIGNAL( clicked() ), TQT_SLOT( slotButtonNext() ) ); addWidget( _infoWidget, 1 ); // Question Widget _questionWidget = new TQVBox( this, "questionWidget" ); _split = new TQSplitter( Qt::Vertical, _questionWidget ); _questionText = new KQuestion( _split, "kquestion" ); _buttonGroup = new KGroupEduca( _split, "ButtonGroup" ); _buttonGroup->setRadioButtonExclusive( true ); _buttonNext = new KPushButton( i18n( "&Next >>" ), _questionWidget, "ButtonNext" ); connect( _buttonNext, TQT_SIGNAL( clicked() ), TQT_SLOT( slotButtonNext() ) ); addWidget( _questionWidget, 2 ); // Results Widget _resultsWidget = new TQVBox( this, "resultsWidget" ); _viewResults = new TQTextEdit( _resultsWidget ); _viewResults->setReadOnly( true ); _buttonSave = new KPushButton( i18n( "&Save Results..." ), _resultsWidget ); connect( _buttonSave, TQT_SIGNAL( clicked() ), TQT_SLOT( slotButtonSave() ) ); /* FIXME: This is a hack * The results widget can be shown only in the end of the test (when you should be shown the * option to save the results) or at the middle of the test, after each question (when there should * be a "Next" button). */ _buttonResultsNext = new KPushButton( i18n( "&Next >>" ), _resultsWidget ); connect( _buttonResultsNext, TQT_SIGNAL( clicked() ), TQT_SLOT( slotButtonNext() ) ); _buttonResultsNext->hide(); addWidget( _resultsWidget, 3 ); raiseWidget( _introWidget ); // Restore splitter size _split->setSizes( Settings::splitter_size() ); } void KEducaView::slotButtonStartTest() { raiseWidget( _questionWidget ); showRecord(); } /** Button Next action */ void KEducaView::slotButtonNext() { // stop the timer if (_timeoutTimer) { _currentTime += _questionText->getCurrentTime(); _timeoutTimer->stop(); _questionText->countdown(0); } if( ( visibleWidget() == _questionWidget ) && !_isInitStatus ) setResults(); _buttonGroup->clearAnswers(); if( ( Settings::resultFinish()== Settings::EnumResultFinish::afterEachQuestion ) && _questionText->isVisible() ) { showResults( _currentResults + "
" + currentStatusPoints() ); } else { if( questionNext() ) showRecord(); else { configWrite(); showResults( setFinalResult() + currentStatusPoints() + "

" + _results + "" ); } } } /** Button Save action */ void KEducaView::slotButtonSave() { KFileDialog *dialog=new KFileDialog(TQString(), TQString(), this, "file dialog", true); dialog->setCaption( i18n("Save Results As") ); dialog->setKeepLocation( true ); dialog->setOperationMode( KFileDialog::Saving ); TQStringList mimeFilter( "text/html"); dialog->setMimeFilter( mimeFilter ); KURL newURL; TQString outputFormat ("text/html"); bool bOk; do { bOk=true; if(dialog->exec()==TQDialog::Accepted) { newURL=dialog->selectedURL(); outputFormat=dialog->currentMimeFilter(); } else { bOk = false; break; } kdDebug()<<"Requested saving to file "< ask for confirmation bOk = KMessageBox::warningContinueCancel( this, i18n("A document with this name already exists.\n"\ "Do you want to overwrite it?"), i18n("Warning"), i18n("Overwrite") ) == KMessageBox::Continue; } } while ( !bOk ); delete dialog; if( bOk ) { if (!_keducaFile->saveResults( newURL, _viewResults->text() )) { kdDebug()<< "saving of file failed" <isMultiAnswer(); // SHOW QUESTION ******************************************************************* _questionText->setPixmap( _keducaFile->getPicturePixmap() ); questionTextTemp = "
" + i18n("Question %1").arg(_keducaFileIndex) + ""; if( _keducaFile->getTotalPoints() > 0 ) questionTextTemp += "" + _keducaFile->getQuestion( FileRead::TQF_POINTS ) + " " + i18n("Points") + ""; questionTextTemp += "


" + _keducaFile->getQuestion( FileRead::TQF_TEXT ) + "
"; _questionText->setText( questionTextTemp ); // SHOW ANSWERS ******************************************************************** if( MultiAnswer ) _buttonGroup->setType( KGroupEduca::Check ); else _buttonGroup->setType( KGroupEduca::Radio ); if( Settings::randomAnswers() ) { _randomAnswers.clear(); TQValueList tmpRandom; unsigned int index; for( index = 0 ; index < _keducaFile->recordAnswerCount() ; index ++ ) { tmpRandom.append( index ); } for( index = 0 ; index < _keducaFile->recordAnswerCount() ; index ++ ) { unsigned int random = rand() % tmpRandom.count(); TQValueList::iterator itTmpRandom = tmpRandom.begin(); for( unsigned int i = 0; i < random; i++) { ++itTmpRandom; } _keducaFile->recordAnswerAt( (*itTmpRandom) ); _randomAnswers.append( (*itTmpRandom) ); _buttonGroup->insertAnswer( _keducaFile->getAnswer(FileRead::AF_TEXT) ); tmpRandom.remove( itTmpRandom ); } } else { _keducaFile->recordAnswerFirst(); while( !_keducaFile->recordAnswerEOF() ) { if( !_keducaFile->getAnswer(FileRead::AF_TEXT).isEmpty() ) _buttonGroup->insertAnswer( _keducaFile->getAnswer(FileRead::AF_TEXT) ); _keducaFile->recordAnswerNext(); }; } // START THE TIMER ***************************************************************** if( _keducaFile->getQuestionInt(FileRead::TQF_TIME) > 0 ) { KMessageBox::information( this, i18n( "You have %1 seconds to complete this question.\n\n" "Press OK when you are ready." ) .arg( _keducaFile->getQuestion(FileRead::TQF_TIME) ) ); } int timeout = _keducaFile->getQuestionInt(FileRead::TQF_TIME); if (timeout > 0) { if (!_timeoutTimer) { _timeoutTimer = new TQTimer(this); connect(_timeoutTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(questionTimedOut())); } _timeoutTimer->start(1000*timeout); _questionText->countdown(timeout); _questionText->countdownVisible(true); } else { _questionText->countdownVisible(false); } } void KEducaView::questionTimedOut() { _currentTime += _keducaFile->getQuestionInt(FileRead::TQF_TIME); slotButtonNext(); } /** Show results */ void KEducaView::showResults( const TQString &text ) { _viewResults->setText( text ); if ( _keducaFile->recordEOF() ) { _buttonSave->show(); _buttonResultsNext->hide(); } else { _buttonSave->hide(); _buttonResultsNext->show(); } raiseWidget( _resultsWidget ); } /** Set results */ void KEducaView::setResults() { bool isCorrect = true; TQString yourAnswer = ""; TQString correctAnswer = ""; TQValueList::iterator itRandom = _randomAnswers.begin(); Settings::randomAnswers() ? _keducaFile->recordAnswerAt(*itRandom) : _keducaFile->recordAnswerFirst(); for( unsigned index = 0 ; index < _keducaFile->recordAnswerCount() ; index++ ) { TQString answertext = _keducaFile->getAnswer( FileRead::AF_TEXT ); if( !answertext.isEmpty() ) { if(_buttonGroup->isChecked(index) != _keducaFile->getAnswerValue()) { isCorrect=false; if(_buttonGroup->isChecked(index)) yourAnswer += "
" + answertext + ""; if(_keducaFile->getAnswerValue()) correctAnswer += "
" + answertext + ""; } else { if(_buttonGroup->isChecked(index)) yourAnswer += "
" + answertext + ""; if(_keducaFile->getAnswerValue()) correctAnswer += "
" + answertext + ""; } } if( Settings::randomAnswers() ) { ++itRandom; _keducaFile->recordAnswerAt(*itRandom); } else _keducaFile->recordAnswerNext(); } if( isCorrect) { _correctAnswer++; if( _keducaFile->getTotalPoints() > 0 ) _correctPoints += _keducaFile->getQuestionInt(FileRead::TQF_POINTS); } else { _incorrectAnswer++; if( _keducaFile->getTotalPoints() > 0 ) _incorrectPoints += _keducaFile->getQuestionInt(FileRead::TQF_POINTS); } _results += getTableQuestion( isCorrect, correctAnswer, yourAnswer ); } /** Set results */ TQString KEducaView::setFinalResult() { TQString finalResult = ""; if( !_keducaFile->isResult() ) return ""; finalResult = ""; _keducaFile->recordResultFirst(); while( !_keducaFile->recordResultEOF() ) { if( _correctPoints >= _keducaFile->getResultInt(FileRead::RS_MIN) && _correctPoints <= _keducaFile->getResultInt(FileRead::RS_MAX) ) { if( _keducaFile->getResult(FileRead::RS_PICTURE).isEmpty() ) finalResult += ""; } _keducaFile->recordResultNext(); } finalResult += "
" + i18n("Result") + "
"; else finalResult += "
"; finalResult += _keducaFile->getResult(FileRead::RS_TEXT) + "
"; return finalResult; } /** Open url */ bool KEducaView::openURL( const KURL &url) { _keducaFile = new FileRead(); if ( !_keducaFile->openFile( url ) ) return false; _isInitStatus = true; _results = ""; _correctAnswer = 0; _correctPoints = 0; _currentTime = 0; _incorrectAnswer = 0; _incorrectPoints = 0; _keducaFileIndex = 0; if( Settings::randomQuestions() ) { unsigned int index; for( index = 0 ; index < _keducaFile->getTotalQuestions() ; index ++ ) { _randomQuestions.append( index ); } } _keducaFile->recordFirst(); _keducaFile->recordAnswerFirst(); _viewInfo->setText( getInformation() ); raiseWidget( _infoWidget ); return true; } /** Write settings */ void KEducaView::configWrite() { Settings::setSplitter_size( _split->sizes() ); Settings::writeConfig(); } /** current Status Points */ TQString KEducaView::currentStatusPoints() { TQString tempStatus; tempStatus = insertTable() + insertRow( i18n("Statistics"), true, 4) + insertRow( i18n("Correct questions"), TQString().setNum( _correctAnswer ), i18n("Incorrect questions"), TQString().setNum( _incorrectAnswer ), true); if( _keducaFile->getTotalPoints() > 0 ) tempStatus += insertRow( i18n("Total points"), true, 4 ) + insertRow( i18n("Correct points"), TQString().setNum( _correctPoints ), i18n("Incorrect points"), TQString().setNum( _incorrectPoints ), true ); if( _keducaFile->getTotalTime() > 0 ) tempStatus += insertRow( i18n("Time"), true, 4 ) + insertRow( i18n("Total time"), TQString().setNum( _keducaFile->getTotalTime() ), i18n("Time in tests"), TQString().setNum( _currentTime ), true ); tempStatus += insertTableClose(); return tempStatus; } /** Set HTML table view with correct and incorrect answers */ TQString KEducaView::getTableQuestion( bool isCorrect, const TQString &correct, const TQString &incorrect) { _currentResults = "
getQuestion( FileRead::TQF_TEXT ) + ""; if( _keducaFile->getQuestionInt(FileRead::TQF_POINTS) > 0 ) _currentResults += " ( " + _keducaFile->getQuestion(FileRead::TQF_POINTS) + " " + i18n("Points") + " )"; _currentResults += "
"; if( isCorrect ) _currentResults += i18n( "The answer is: "); else _currentResults += i18n( "The correct answer is: "); _currentResults += correct + "
"; if( !isCorrect ) { _currentResults += i18n( "Your answer was: "); _currentResults += incorrect; } _currentResults += "

"; return _currentResults; } /** Define the next questions (random, secuencial) */ bool KEducaView::questionNext() { if( !Settings::randomQuestions() && !_isInitStatus ) { _keducaFile->recordNext(); return _keducaFile->recordEOF() ? false : true; } if( _isInitStatus ) { _isInitStatus = false; if( !Settings::randomQuestions() ) return true; } if( _randomQuestions.count() > 0 ) { unsigned int randomQuestion = rand() % _randomQuestions.count(); TQValueList::iterator itRandom = _randomQuestions.begin(); for( unsigned int i = 0; i < randomQuestion; ++i) { ++itRandom; } _keducaFile->recordAt( (*itRandom) ); _randomQuestions.remove( itRandom ); return true; } else return false; } /** Get document information */ TQString KEducaView::getInformation() { TQString tmp = ""; if ( _keducaFile ) { if( !(_keducaFile->getHeader("startupinfo")).isEmpty() ) { tmp += insertTable( "", 2 ) // + insertRow( i18n("Additional Information")+"
", true, 2 ) + insertRow( _keducaFile->getHeader("startupinfo") + "
", false ) + insertTableClose(); } tmp += insertTable( "", 2 ); tmp += insertRow( i18n("Information")+"
", true, 2); tmp += insertRow( i18n("Title"), _keducaFile->getHeader("title"), true ); tmp += insertRow( i18n("Category"), _keducaFile->getHeader("category"), true ); tmp += insertRow( i18n("Type"), _keducaFile->getHeader("type"), true ); tmp += insertRow( i18n("Language"), _keducaFile->getHeader("language"), true ); tmp += insertTableClose(); } else { tmp += ""; tmp += ""; tmp += ""; } return tmp; } /** Init table with title and colspan */ TQString KEducaView::insertTable( const TQString &title, unsigned int col){ TQString tmp; tmp = ""; if( !title.isEmpty() ) { tmp += ""; } return tmp; } /** Insert row */ TQString KEducaView::insertRow( const TQString &text, bool title, unsigned colSpan ){ TQString tmp; tmp = "0 ) tmp+= " COLSPAN=" + TQString().setNum(colSpan); if( title ) tmp += " ALIGN=CENTER"; tmp += ">"; if( title ) tmp += ""; tmp += text; if( title ) tmp += ""; tmp += ""; return tmp; } /** Insert row */ TQString KEducaView::insertRow( const TQString &label, const TQString &field, bool formBased ){ TQString tmp; tmp = ""; return tmp; } TQString KEducaView::insertRow( const TQString &label1, const TQString &field1, const TQString &label2, const TQString &field2, bool formBased ){ TQString tmp; tmp = ""; tmp += ""; return tmp; } /** Close current table */ TQString KEducaView::insertTableClose(){ return "
0 ) tmp += "COLSPAN=" + TQString().setNum( col ) + " "; tmp += "ALIGN=CENTER>" + title + "
"; }