• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

keduca

keducaview.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           keducaview.cpp  -  description
00003                              -------------------
00004     begin                : Thu May 24 2001
00005     copyright            : (C) 2001 by Javier Campos
00006     email                : javi@asyris.org
00007 ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "keducaview.h"
00019 #include "keducaview.moc"
00020 #include "settings.h"
00021 #include "../libkeduca/fileread.h"
00022 #include "kquestion.h"
00023 #include "kgroupeduca.h"
00024 
00025 #include <stdlib.h>
00026 
00027 #include <klocale.h>
00028 #include <kstandarddirs.h>
00029 #include <kmessagebox.h>
00030 #include <kfiledialog.h>
00031 #include <kpushbutton.h>
00032 #include <kdebug.h>
00033 #include <kio/netaccess.h>
00034 
00035 #include <qtimer.h>
00036 #include <qlayout.h>
00037 #include <qlabel.h>
00038 #include <qtextedit.h>
00039 
00040 KEducaView::KEducaView( QWidget *parent, const char *name )
00041     : QWidgetStack( parent, name ), _keducaFile( 0 ), _timeoutTimer( 0 )
00042 {
00043     init();
00044 }
00045 
00046 KEducaView::~KEducaView()
00047 {
00048     delete _questionText;
00049     delete _buttonGroup;
00050     delete _split;
00051     delete _buttonNext;
00052     delete _buttonSave;
00053     delete _viewResults;
00054     delete _keducaFile;
00055 }
00056 
00058 void KEducaView::init()
00059 {
00060     // Intro Screen
00061     _introWidget = new QLabel( this, "introScreen" );
00062     _introWidget->setBackgroundColor( Qt::white );
00063     _introWidget->setAlignment( AlignCenter );
00064     _introWidget->setPixmap( QPixmap( locate("data","keduca/pics/keduca_init.png") ) );
00065     addWidget( _introWidget, 0 );
00066 
00067     // Info Widget
00068     _infoWidget = new QVBox( this, "infoWidget" );
00069     _viewInfo = new QTextEdit( _infoWidget );
00070     _viewInfo->setReadOnly( true );
00071     _buttonStartTest = new KPushButton( i18n( "&Start Test" ), _infoWidget );
00072     connect( _buttonStartTest, SIGNAL( clicked() ), SLOT( slotButtonNext() ) );
00073     addWidget( _infoWidget, 1 );
00074 
00075     // Question Widget
00076     _questionWidget = new QVBox( this, "questionWidget" );
00077     _split  = new QSplitter( QSplitter::Vertical, _questionWidget );
00078     _questionText = new KQuestion( _split, "kquestion" );
00079     _buttonGroup = new KGroupEduca( _split, "ButtonGroup" );
00080     _buttonGroup->setRadioButtonExclusive( true );
00081     _buttonNext = new KPushButton( i18n( "&Next >>" ), _questionWidget, "ButtonNext" );
00082     connect( _buttonNext, SIGNAL( clicked() ), SLOT( slotButtonNext() ) );
00083     addWidget( _questionWidget, 2 );
00084 
00085     // Results Widget
00086     _resultsWidget = new QVBox( this, "resultsWidget" );
00087     _viewResults = new QTextEdit( _resultsWidget );
00088     _viewResults->setReadOnly( true );
00089     _buttonSave = new KPushButton( i18n( "&Save Results..." ), _resultsWidget );
00090     connect( _buttonSave, SIGNAL( clicked() ), SLOT( slotButtonSave() ) );
00091     /* FIXME: This is a hack
00092      * The results widget can be shown only in the end of the test (when you should be shown the
00093      * option to save the results) or at the middle of the test, after each question (when there should
00094      * be a "Next" button).
00095      */
00096     _buttonResultsNext = new KPushButton( i18n( "&Next >>" ), _resultsWidget );
00097     connect( _buttonResultsNext, SIGNAL( clicked() ), SLOT( slotButtonNext() ) );
00098     _buttonResultsNext->hide();
00099     addWidget( _resultsWidget, 3 );
00100 
00101     raiseWidget( _introWidget );
00102 
00103     // Restore splitter size
00104     _split->setSizes( Settings::splitter_size() );
00105 }
00106 
00107 void KEducaView::slotButtonStartTest()
00108 {
00109     raiseWidget( _questionWidget );
00110     showRecord();
00111 }
00112 
00114 void KEducaView::slotButtonNext()
00115 {
00116     // stop the timer
00117     if (_timeoutTimer)
00118     {
00119       _currentTime += _questionText->getCurrentTime();
00120       _timeoutTimer->stop();
00121       _questionText->countdown(0);
00122     }
00123 
00124     if( ( visibleWidget() == _questionWidget ) && !_isInitStatus )
00125       setResults();
00126 
00127     _buttonGroup->clearAnswers();
00128 
00129     if( ( Settings::resultFinish()== Settings::EnumResultFinish::afterEachQuestion ) 
00130         && _questionText->isVisible() )
00131     {
00132         showResults( _currentResults + "<HR>" + currentStatusPoints() );
00133     }
00134     else
00135     {
00136         if( questionNext() )
00137           showRecord();
00138         else
00139           {
00140           configWrite();
00141           showResults( setFinalResult() + currentStatusPoints() + "<HR><P>" + _results + "</HTML>"
00142 );
00143           }
00144     }
00145 }
00146 
00148 void KEducaView::slotButtonSave()
00149 {
00150     KFileDialog *dialog=new KFileDialog(QString::null, QString::null, this, "file dialog", true);
00151     dialog->setCaption( i18n("Save Results As") );
00152     dialog->setKeepLocation( true );
00153     dialog->setOperationMode( KFileDialog::Saving );
00154     QStringList mimeFilter( "text/html");
00155     dialog->setMimeFilter( mimeFilter );
00156     KURL newURL;
00157     QString outputFormat ("text/html");
00158 
00159     bool bOk;
00160     do {
00161         bOk=true;
00162         if(dialog->exec()==QDialog::Accepted) {
00163             newURL=dialog->selectedURL();
00164             outputFormat=dialog->currentMimeFilter();
00165         }
00166         else
00167         {
00168             bOk = false;
00169             break;
00170         }
00171         kdDebug()<<"Requested saving to file "<<newURL.prettyURL() <<endl;
00172 
00173         if ( QFileInfo( newURL.path() ).extension().isEmpty() ) {
00174             // No more extensions in filters. We need to get it from the mimetype.
00175             QString extension = ".html";
00176             newURL.setPath( newURL.path() + extension );
00177         }
00178 
00179         if ( KIO::NetAccess::exists( newURL, false, this ) ) { // this file exists => ask for confirmation
00180             bOk = KMessageBox::warningContinueCancel( this,
00181                                               i18n("A document with this name already exists.\n"\
00182                                                    "Do you want to overwrite it?"),
00183                                               i18n("Warning"), i18n("Overwrite") ) == KMessageBox::Continue;
00184         }
00185     } while ( !bOk );
00186 
00187     delete dialog;  
00188     if( bOk ) {
00189         if (!_keducaFile->saveResults( newURL, _viewResults->text() ))
00190           {
00191           kdDebug()<< "saving of file failed" <<endl;
00192           KMessageBox::sorry( this, i18n("Save failed.") ); 
00193           }
00194         }else {
00195         kdDebug()<< "KControlDoc: no valid filename selected" <<endl;
00196     }
00197 }
00198 
00200 void KEducaView::showRecord()
00201 {
00202     QString questionTextTemp = "";
00203     
00204     raiseWidget( _questionWidget );
00205     
00206     _keducaFileIndex++;
00207     bool MultiAnswer = _keducaFile->isMultiAnswer();
00208 
00209     // SHOW QUESTION *******************************************************************
00210     _questionText->setPixmap( _keducaFile->getPicturePixmap() );
00211     questionTextTemp =  "<table width=100%><tr><td><b>"
00212                         + i18n("Question %1").arg(_keducaFileIndex) + "</b>";
00213 
00214     if( _keducaFile->getTotalPoints() > 0 )
00215       questionTextTemp  += "</td><td align=center bgColor=#336699><font color=#ffffff><b>"
00216                         + _keducaFile->getQuestion( FileRead::QF_POINTS )
00217                         + " " + i18n("Points")
00218                         + "</b></font>";
00219                        
00220     questionTextTemp    += "</tr></td></table><hr/><table><tr><td>"
00221                         + _keducaFile->getQuestion( FileRead::QF_TEXT )
00222                         + "</td></tr></table>";
00223 
00224     _questionText->setText( questionTextTemp );
00225                             
00226     // SHOW ANSWERS ********************************************************************
00227     if( MultiAnswer )
00228         _buttonGroup->setType( KGroupEduca::Check );
00229     else
00230         _buttonGroup->setType( KGroupEduca::Radio );
00231 
00232 
00233     if( Settings::randomAnswers() )
00234       {
00235       _randomAnswers.clear();
00236       QValueList<unsigned int> tmpRandom;
00237       unsigned int index;
00238       for( index = 0 ; index < _keducaFile->recordAnswerCount() ; index ++ )
00239         { tmpRandom.append( index ); }
00240       for( index = 0 ; index < _keducaFile->recordAnswerCount() ; index ++ )
00241         {
00242         unsigned int random = rand() % tmpRandom.count();
00243         QValueList<unsigned int>::iterator itTmpRandom = tmpRandom.begin();
00244         for( unsigned int i = 0; i < random; i++) { ++itTmpRandom; }
00245         _keducaFile->recordAnswerAt( (*itTmpRandom) );
00246         _randomAnswers.append( (*itTmpRandom) );
00247         _buttonGroup->insertAnswer( _keducaFile->getAnswer(FileRead::AF_TEXT) );
00248         tmpRandom.remove( itTmpRandom );
00249         }
00250       }
00251     else
00252       {
00253         _keducaFile->recordAnswerFirst();
00254         while( !_keducaFile->recordAnswerEOF() )
00255         {
00256             if( !_keducaFile->getAnswer(FileRead::AF_TEXT).isEmpty() )
00257                 _buttonGroup->insertAnswer( _keducaFile->getAnswer(FileRead::AF_TEXT) );
00258             _keducaFile->recordAnswerNext();
00259         };
00260       }
00261 
00262     
00263     // START THE TIMER *****************************************************************
00264     if( _keducaFile->getQuestionInt(FileRead::QF_TIME) > 0 )
00265     {
00266         KMessageBox::information( this,
00267                                   i18n( "You have %1 seconds to complete this question.\n\n"
00268                                         "Press OK when you are ready." )
00269                                   .arg( _keducaFile->getQuestion(FileRead::QF_TIME) ) );
00270      }
00271 
00272     int timeout = _keducaFile->getQuestionInt(FileRead::QF_TIME);
00273     if (timeout > 0)
00274     {
00275       if (!_timeoutTimer)
00276       {
00277         _timeoutTimer = new QTimer(this);
00278         connect(_timeoutTimer, SIGNAL(timeout()),
00279                 this, SLOT(questionTimedOut()));
00280       }
00281       _timeoutTimer->start(1000*timeout);
00282       _questionText->countdown(timeout);
00283       _questionText->countdownVisible(true);
00284     }
00285     else
00286     {
00287       _questionText->countdownVisible(false);
00288     }
00289 }
00290 
00291 void KEducaView::questionTimedOut()
00292 {
00293   _currentTime += _keducaFile->getQuestionInt(FileRead::QF_TIME);
00294   slotButtonNext();
00295 }
00296 
00298 void KEducaView::showResults( const QString &text )
00299 {
00300     _viewResults->setText( text );
00301    
00302     if ( _keducaFile->recordEOF() )
00303     {
00304         _buttonSave->show();
00305        _buttonResultsNext->hide();
00306     }
00307     else
00308     {
00309         _buttonSave->hide();
00310        _buttonResultsNext->show();
00311     }
00312     
00313     raiseWidget( _resultsWidget );
00314 }
00315 
00317 void KEducaView::setResults()
00318 {
00319     bool isCorrect = true;
00320     QString yourAnswer = "";
00321     QString correctAnswer = "";
00322     QValueList<uint>::iterator itRandom = _randomAnswers.begin();
00323     
00324     Settings::randomAnswers() ? _keducaFile->recordAnswerAt(*itRandom) : _keducaFile->recordAnswerFirst();
00325 
00326     for( unsigned index = 0 ; index < _keducaFile->recordAnswerCount() ; index++ )
00327     {
00328         QString answertext = _keducaFile->getAnswer( FileRead::AF_TEXT );
00329         if( !answertext.isEmpty() )
00330         {
00331             if(_buttonGroup->isChecked(index) != _keducaFile->getAnswerValue())
00332             {
00333                 isCorrect=false;
00334                 if(_buttonGroup->isChecked(index)) yourAnswer += "<BR><FONT COLOR=#b84747><B>" + answertext + "</B></FONT>";
00335                 if(_keducaFile->getAnswerValue()) correctAnswer += "<BR><FONT COLOR=#006b6b><B>" + answertext + "</B></FONT>";
00336             }
00337             else
00338             {
00339                 if(_buttonGroup->isChecked(index)) yourAnswer += "<BR><B>" + answertext + "</B>";
00340                 if(_keducaFile->getAnswerValue()) correctAnswer += "<BR><FONT COLOR=#006b6b><B>" + answertext + "</B></FONT>";
00341             }
00342         }
00343         if( Settings::randomAnswers() )
00344           {
00345           ++itRandom;
00346           _keducaFile->recordAnswerAt(*itRandom);
00347           }
00348         else
00349           _keducaFile->recordAnswerNext();
00350     }
00351 
00352     if( isCorrect)
00353       {
00354       _correctAnswer++;
00355       if( _keducaFile->getTotalPoints() > 0 )
00356         _correctPoints += _keducaFile->getQuestionInt(FileRead::QF_POINTS);
00357       }
00358     else
00359       {
00360       _incorrectAnswer++;
00361       if( _keducaFile->getTotalPoints() > 0 )
00362         _incorrectPoints += _keducaFile->getQuestionInt(FileRead::QF_POINTS);
00363       }
00364     
00365   _results += getTableQuestion( isCorrect, correctAnswer, yourAnswer );
00366 }
00367 
00369 QString KEducaView::setFinalResult()
00370 {
00371   QString finalResult = "";
00372   
00373   if( !_keducaFile->isResult() ) return "";
00374 
00375   finalResult = "<TABLE WIDTH=100% BORDER=0 BGCOLOR=#EEEEDD CELLSPACING=0><TR><TD BGCOLOR=#DDDDCC COLSPAN=2 ALIGN=CENTER><FONT COLOR=#222211><B>"
00376               + i18n("Result")
00377               + "</B></FONT></TD></TR>";
00378   
00379   _keducaFile->recordResultFirst();
00380   while( !_keducaFile->recordResultEOF() )
00381     {
00382         if( _correctPoints >= _keducaFile->getResultInt(FileRead::RS_MIN) &&
00383             _correctPoints <= _keducaFile->getResultInt(FileRead::RS_MAX) )
00384           {
00385              if( _keducaFile->getResult(FileRead::RS_PICTURE).isEmpty() )
00386                finalResult += "<TR><TD COLSPAN=2 ALIGN=CENTER>";
00387                else
00388                finalResult += "<TR><TD><IMG SRC=" + _keducaFile->getResult(FileRead::RS_PICTURE) + " : </TD><TD>";
00389                
00390              finalResult += _keducaFile->getResult(FileRead::RS_TEXT) + "</TD><TR>";
00391           }
00392         _keducaFile->recordResultNext();
00393     }
00394 
00395   finalResult += "</TABLE>";
00396 
00397   return finalResult;
00398 }
00399 
00401 bool KEducaView::openURL( const KURL &url)
00402 {
00403     _keducaFile = new FileRead();
00404     if ( !_keducaFile->openFile( url ) )
00405         return false;
00406 
00407     _isInitStatus = true;
00408     _results = "<HTML>";
00409     _correctAnswer = 0;
00410     _correctPoints = 0;
00411     _currentTime = 0;
00412     _incorrectAnswer = 0;
00413     _incorrectPoints = 0;
00414     _keducaFileIndex = 0;
00415 
00416     if( Settings::randomQuestions() )
00417       {
00418       unsigned int index;
00419       for( index = 0 ; index < _keducaFile->getTotalQuestions() ; index ++ )
00420             {   _randomQuestions.append( index ); }
00421       }
00422 
00423     _keducaFile->recordFirst();
00424     _keducaFile->recordAnswerFirst();
00425     
00426     _viewInfo->setText( getInformation() );
00427     raiseWidget( _infoWidget );
00428     
00429     return true;
00430 }
00431 
00433 void KEducaView::configWrite()
00434 {
00435     Settings::setSplitter_size( _split->sizes() );
00436     Settings::writeConfig();
00437 }
00438 
00440 QString KEducaView::currentStatusPoints()
00441 {
00442   QString tempStatus;
00443  
00444   tempStatus = insertTable()
00445               + insertRow( i18n("Statistics"), true, 4)
00446               + insertRow( i18n("Correct questions"),
00447                            QString().setNum( _correctAnswer ),
00448                            i18n("Incorrect questions"),
00449                            QString().setNum( _incorrectAnswer ), true);
00450 
00451   if( _keducaFile->getTotalPoints() > 0 )
00452     tempStatus += insertRow( i18n("Total points"), true, 4 )
00453                 + insertRow( i18n("Correct points"),
00454                              QString().setNum( _correctPoints ),
00455                              i18n("Incorrect points"),
00456                              QString().setNum( _incorrectPoints ), true );
00457 
00458   if( _keducaFile->getTotalTime() > 0 )
00459     tempStatus += insertRow( i18n("Time"), true, 4 )
00460                 + insertRow( i18n("Total time"),
00461                              QString().setNum( _keducaFile->getTotalTime() ),
00462                              i18n("Time in tests"),
00463                              QString().setNum( _currentTime ), true );
00464   tempStatus += insertTableClose();
00465   return tempStatus;
00466 }
00467 
00469 QString KEducaView::getTableQuestion( bool isCorrect, const QString &correct, const QString &incorrect)
00470 {
00471   _currentResults = "<TABLE WIDTH=100% BORDER=0><TR><TD VALIGN=TOP WIDTH=70><IMG WIDTH=64 HEIGHT=64 SRC=";                     
00472   if( isCorrect )
00473     _currentResults += locate("data","keduca/pics/keduca_correct_64.png");
00474     else
00475     _currentResults += locate("data","keduca/pics/keduca_incorrect_64.png");
00476 
00477   _currentResults += "></TD><TD VALIGN=TOP>";
00478 
00479   _currentResults += "<B><FONT COLOR=#336699>" + _keducaFile->getQuestion( FileRead::QF_TEXT ) + "</FONT></B>";
00480 
00481   if( _keducaFile->getQuestionInt(FileRead::QF_POINTS) > 0 )
00482     _currentResults += "<SMALL> ( " + _keducaFile->getQuestion(FileRead::QF_POINTS) + " " + i18n("Points") + " )</SMALL>";
00483     
00484   _currentResults += "<HR><SMALL>";
00485 
00486   if( isCorrect )
00487     _currentResults += i18n( "The answer is: ");
00488     else
00489     _currentResults += i18n( "The correct answer is: ");
00490 
00491   _currentResults += correct + "<BR>";
00492 
00493   if( !isCorrect )
00494     {
00495         _currentResults += i18n( "Your answer was: ");
00496         _currentResults += incorrect;
00497     }
00498  
00499   _currentResults += "</SMALL></TD></TR></TABLE><P>";
00500   return _currentResults;
00501 }
00502 
00504 bool KEducaView::questionNext()
00505 {
00506   if( !Settings::randomQuestions() && !_isInitStatus )
00507     {
00508     _keducaFile->recordNext();
00509     return _keducaFile->recordEOF() ? false : true;
00510     }
00511 
00512   if( _isInitStatus )
00513     {
00514     _isInitStatus = false;
00515     if( !Settings::randomQuestions() ) return true;
00516     }
00517  
00518   if( _randomQuestions.count() > 0 )
00519     { 
00520     unsigned int randomQuestion = rand() % _randomQuestions.count();
00521     QValueList<uint>::iterator itRandom = _randomQuestions.begin();
00522     for( unsigned int i = 0; i < randomQuestion; ++i)
00523       { ++itRandom; }
00524     _keducaFile->recordAt( (*itRandom) );
00525     _randomQuestions.remove( itRandom );
00526     return true;
00527     }
00528     else
00529     return false;
00530 }
00531 
00533 QString KEducaView::getInformation()
00534 {
00535 
00536   QString tmp = "";
00537   
00538   if ( _keducaFile )
00539   {
00540     if( !(_keducaFile->getHeader("startupinfo")).isEmpty() )
00541     {
00542       tmp += insertTable( "<img src=" + locate("data","keduca/pics/alert.png") + ">", 2 )
00543 //          + insertRow( i18n("Additional Information")+"<br>", true, 2 )
00544           + insertRow( _keducaFile->getHeader("startupinfo") + "<br>", false )
00545           + insertTableClose();
00546     }
00547 
00548     tmp += insertTable( "<img src=" + locate("data","keduca/pics/info.png") + ">", 2 );
00549     tmp += insertRow( i18n("Information")+"<br>", true, 2);
00550     tmp += insertRow( i18n("Title"), _keducaFile->getHeader("title"), true );
00551     tmp += insertRow( i18n("Category"), _keducaFile->getHeader("category"), true );
00552     tmp += insertRow( i18n("Type"), _keducaFile->getHeader("type"), true );
00553     tmp += insertRow( i18n("Language"), _keducaFile->getHeader("language"), true );
00554     tmp += insertTableClose();
00555   }
00556   else
00557   {
00558     tmp += "<html><body>";
00559     tmp += "<img src=" + locate("data","keduca/pics/keduca_init.png") + "/>";
00560     tmp += "</body></html>";
00561   }
00562 
00563   return tmp;
00564 }
00565 
00567 QString KEducaView::insertTable( const QString &title, unsigned int col){
00568   QString tmp;
00569 
00570   tmp = "<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 BGCOLOR=#EEEEDD>";
00571 
00572   if( !title.isEmpty() ) {
00573     tmp += "<TR><TD ";
00574 
00575     if( col > 0 ) tmp += "COLSPAN=" + QString().setNum( col ) + " ";
00576 
00577     tmp += "ALIGN=CENTER><FONT COLOR=#222211><B>"
00578         + title
00579         + "</B></FONT></TD></TR>";
00580     }
00581   return tmp;
00582 }
00583 
00585 QString KEducaView::insertRow( const QString &text, bool title, unsigned colSpan ){
00586   QString tmp;
00587   tmp = "<TR><TD";
00588   if( colSpan>0 ) tmp+= " COLSPAN=" + QString().setNum(colSpan);
00589   if( title ) tmp += " ALIGN=CENTER";
00590   tmp += ">";
00591   if( title ) tmp += "<B>";
00592   tmp += text;
00593   if( title ) tmp += "</B>";
00594   tmp += "</TD></TR>";
00595   return tmp;
00596 }
00597 
00599 QString KEducaView::insertRow( const QString &label, const QString &field, bool formBased ){
00600   QString tmp;
00601   tmp = "<TR><TD";
00602   if( formBased ) tmp += " ALIGN=RIGHT";
00603   tmp += ">" + label;
00604   if( formBased ) tmp += ": ";
00605   tmp += "</TD><TD>" + field + "</TD></TR>";
00606   return tmp;
00607 }
00608 
00609 QString KEducaView::insertRow( const QString &label1, const QString &field1, const QString &label2, const QString &field2, bool formBased ){
00610   QString tmp;
00611   tmp = "<TR><TD";
00612   if( formBased ) tmp += " ALIGN=RIGHT";
00613   tmp += ">" + label1;
00614   if( formBased ) tmp += ": ";
00615   tmp += "</TD><TD>" + field1 + "</TD>";
00616   tmp += "<TD";
00617   if( formBased ) tmp += " ALIGN=RIGHT";
00618   tmp += ">" + label2;
00619   if( formBased ) tmp += ": ";
00620   tmp += "</TD><TD>" + field2 + "</TD></TR>";
00621   return tmp;
00622 }
00623 
00624 
00626 QString KEducaView::insertTableClose(){
00627   return "</TABLE>";
00628 }
00629 

keduca

Skip menu "keduca"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members

API Reference

Skip menu "API Reference"
  • keduca
  • kstars
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal