/**
This file is part of Kiten , a KDE Japanese Reference Tool . . .
Copyright ( C ) 2001 Jason Katz - Brown < jason @ katzbrown . com >
( C ) 2005 Paul Temple < paul . temple @ gmx . net >
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 .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301
USA
* */
# include <kaction.h>
# include <kapplication.h>
# include <kdebug.h>
# include <kfiledialog.h>
# include <klistview.h>
# include <klocale.h>
# include <kmessagebox.h>
# include <kpushbutton.h>
# include <kstatusbar.h>
# include <kstringhandler.h>
# include <tqbuttongroup.h>
# include <tqheader.h>
# include <tqlayout.h>
# include <tqtabwidget.h>
# include <tqtimer.h>
# include <tqtextcodec.h>
# include <stdlib.h> // RAND_MAX
# include <cassert>
# include <set>
# include "kitenconfig.h"
# include "dict.h"
# include "kloader.h"
# include "ksaver.h"
# include "learn.h"
LearnItem : : LearnItem ( TQListView * parent , TQString label1 , TQString label2 , TQString label3 , TQString label4 , TQString label5 , TQString label6 , TQString label7 , TQString label8 )
: TQListViewItem ( parent , label1 , label2 , label3 , label4 , label5 , label6 , label7 , label8 )
{
}
int LearnItem : : compare ( TQListViewItem * item , int col , bool ascending ) const
{
// "Returns < 0 if this item is less than i [item] , 0 if they
// are equal and > 0 if this item is greater than i [item]."
return key ( col , ascending ) . toInt ( ) - item - > key ( col , ascending ) . toInt ( ) ;
}
const int Learn : : numberOfAnswers = 5 ;
Learn : : Learn ( Dict : : Index * parentDict , TQWidget * parent , const char * name )
: KMainWindow ( parent , name ) , initialized ( false ) , isMod ( false ) , prevItem ( 0 ) , curItem ( 0 )
{
index = parentDict ;
TQWidget * dummy = new TQWidget ( this ) ;
setCentralWidget ( dummy ) ;
TQVBoxLayout * veryTop = new TQVBoxLayout ( dummy , 0 , KDialog : : spacingHint ( ) ) ;
Tabs = new TQTabWidget ( dummy ) ;
connect ( Tabs , TQT_SIGNAL ( currentChanged ( TQWidget * ) ) , TQT_SLOT ( tabChanged ( TQWidget * ) ) ) ;
veryTop - > addWidget ( Tabs ) ;
listTop = new TQSplitter ( Tabs ) ;
listTop - > setOrientation ( Qt : : Vertical ) ;
quizTop = new TQWidget ( Tabs ) ;
Tabs - > addTab ( listTop , i18n ( " &List " ) ) ;
Tabs - > addTab ( quizTop , i18n ( " &Quiz " ) ) ;
View = new ResultView ( true , listTop , " View " ) ;
View - > setBasicMode ( true ) ;
connect ( View , TQT_SIGNAL ( linkClicked ( const TQString & ) ) , this , TQT_SIGNAL ( linkClicked ( const TQString & ) ) ) ;
List = new KListView ( listTop ) ;
List - > addColumn ( i18n ( " Kanji " ) ) ;
List - > addColumn ( i18n ( " Meanings " ) ) ;
List - > addColumn ( i18n ( " Readings " ) ) ;
List - > addColumn ( i18n ( " Grade " ) ) ;
List - > addColumn ( i18n ( " Your Score " ) ) ;
List - > setAllColumnsShowFocus ( true ) ;
List - > setColumnWidthMode ( 0 , TQListView : : Maximum ) ;
List - > setColumnWidthMode ( 1 , TQListView : : Maximum ) ;
List - > setColumnWidthMode ( 2 , TQListView : : Maximum ) ;
List - > setColumnWidthMode ( 3 , TQListView : : Maximum ) ;
List - > setMultiSelection ( true ) ;
List - > setDragEnabled ( true ) ;
List - > setSorting ( 4 ) ;
List - > setSelectionModeExt ( KListView : : Extended ) ;
connect ( List , TQT_SIGNAL ( executed ( TQListViewItem * ) ) , TQT_SLOT ( showKanji ( TQListViewItem * ) ) ) ;
connect ( List , TQT_SIGNAL ( selectionChanged ( ) ) , this , TQT_SLOT ( itemSelectionChanged ( ) ) ) ;
TQStringList grades ( i18n ( " Grade 1 " ) ) ;
grades . append ( i18n ( " Grade 2 " ) ) ;
grades . append ( i18n ( " Grade 3 " ) ) ;
grades . append ( i18n ( " Grade 4 " ) ) ;
grades . append ( i18n ( " Grade 5 " ) ) ;
grades . append ( i18n ( " Grade 6 " ) ) ;
grades . append ( i18n ( " Others in Jouyou " ) ) ;
grades . append ( i18n ( " Jinmeiyou " ) ) ;
/*KAction *closeAction = */ ( void ) KStdAction : : close ( TQT_TQOBJECT ( this ) , TQT_SLOT ( close ( ) ) , actionCollection ( ) ) ;
printAct = KStdAction : : print ( TQT_TQOBJECT ( this ) , TQT_SLOT ( print ( ) ) , actionCollection ( ) ) ;
forwardAct = KStdAction : : forward ( TQT_TQOBJECT ( this ) , TQT_SLOT ( next ( ) ) , actionCollection ( ) ) ;
forwardAct - > plug ( toolBar ( ) ) ;
backAct = KStdAction : : back ( TQT_TQOBJECT ( this ) , TQT_SLOT ( prev ( ) ) , actionCollection ( ) ) ;
backAct - > plug ( toolBar ( ) ) ;
cheatAct = new KAction ( i18n ( " &Cheat " ) , CTRL + Key_C , TQT_TQOBJECT ( this ) , TQT_SLOT ( cheat ( ) ) , actionCollection ( ) , " cheat " ) ;
randomAct = new KAction ( i18n ( " &Random " ) , " goto " , CTRL + Key_R , TQT_TQOBJECT ( this ) , TQT_SLOT ( random ( ) ) , actionCollection ( ) , " random " ) ;
gradeAct = new KListAction ( i18n ( " Grade " ) , 0 , 0 , 0 , actionCollection ( ) , " grade " ) ;
gradeAct - > setItems ( grades ) ;
connect ( gradeAct , TQT_SIGNAL ( activated ( const TQString & ) ) , TQT_SLOT ( updateGrade ( ) ) ) ;
removeAct = new KAction ( i18n ( " &Delete " ) , " edit_remove " , CTRL + Key_X , TQT_TQOBJECT ( this ) , TQT_SLOT ( del ( ) ) , actionCollection ( ) , " del " ) ;
addAct = new KAction ( i18n ( " &Add " ) , " edit_add " , CTRL + Key_A , TQT_TQOBJECT ( this ) , TQT_SLOT ( add ( ) ) , actionCollection ( ) , " add " ) ;
addAllAct = new KAction ( i18n ( " Add A&ll " ) , 0 , TQT_TQOBJECT ( this ) , TQT_SLOT ( addAll ( ) ) , actionCollection ( ) , " addall " ) ;
newAct = KStdAction : : openNew ( TQT_TQOBJECT ( this ) , TQT_SLOT ( openNew ( ) ) , actionCollection ( ) ) ;
openAct = KStdAction : : open ( TQT_TQOBJECT ( this ) , TQT_SLOT ( open ( ) ) , actionCollection ( ) ) ;
saveAct = KStdAction : : save ( TQT_TQOBJECT ( this ) , TQT_SLOT ( save ( ) ) , actionCollection ( ) ) ;
saveAsAct = KStdAction : : saveAs ( TQT_TQOBJECT ( this ) , TQT_SLOT ( saveAs ( ) ) , actionCollection ( ) ) ;
( void ) KStdAction : : preferences ( TQT_TQOBJECT ( this ) , TQT_SIGNAL ( configureLearn ( ) ) , actionCollection ( ) ) ;
removeAct - > setEnabled ( false ) ;
TQVBoxLayout * quizLayout = new TQVBoxLayout ( quizTop , KDialog : : marginHint ( ) , KDialog : : spacingHint ( ) ) ;
quizLayout - > addStretch ( ) ;
TQHBoxLayout * htqlayout = new TQHBoxLayout ( quizLayout ) ;
qKanji = new TQPushButton ( quizTop ) ;
connect ( qKanji , TQT_SIGNAL ( clicked ( ) ) , this , TQT_SLOT ( qKanjiClicked ( ) ) ) ;
htqlayout - > addStretch ( ) ;
htqlayout - > addWidget ( qKanji ) ;
htqlayout - > addStretch ( ) ;
quizLayout - > addStretch ( ) ;
answers = new TQButtonGroup ( 1 , Qt : : Horizontal , quizTop ) ;
for ( int i = 0 ; i < numberOfAnswers ; + + i )
answers - > insert ( new KPushButton ( answers ) , i ) ;
quizLayout - > addWidget ( answers ) ;
quizLayout - > addStretch ( ) ;
connect ( answers , TQT_SIGNAL ( clicked ( int ) ) , this , TQT_SLOT ( answerClicked ( int ) ) ) ;
createGUI ( " learnui.rc " ) ;
//closeAction->plug(toolBar());
resize ( 600 , 400 ) ;
applyMainWindowSettings ( Config : : self ( ) - > config ( ) , " LearnWindow " ) ;
statusBar ( ) - > message ( i18n ( " Put on your thinking cap! " ) ) ;
nogood = false ;
// this is so learn doesn't take so long to show itself
TQTimer : : singleShot ( 200 , this , TQT_SLOT ( finishCtor ( ) ) ) ;
}
void Learn : : finishCtor ( )
{
Config * config = Config : : self ( ) ;
setCurrentGrade ( config - > grade ( ) ) ;
/*
* this must be done now , because
* to start a quiz , we need a working randomMeaning ( )
* and that needs a loaded grade !
*/
updateGrade ( ) ;
updateQuizConfiguration ( ) ; // first
TQString entry = config - > lastFile ( ) ;
//kdDebug() << "lastFile: " << entry << endl;
if ( ! entry . isEmpty ( ) )
{
filename = entry ;
read ( filename ) ;
}
else
{
openNew ( ) ;
}
initialized = true ;
}
Learn : : ~ Learn ( )
{
emit destroyed ( this ) ;
}
bool Learn : : warnClose ( )
{
if ( isMod )
{
int result = KMessageBox : : warningYesNoCancel ( this , i18n ( " There are unsaved changes to learning list. Save them? " ) , i18n ( " Unsaved Changes " ) , KStdGuiItem : : save ( ) , KStdGuiItem : : discard ( ) , " DiscardAsk " , true ) ;
switch ( result )
{
case KMessageBox : : Yes :
saveAct - > activate ( ) ;
// fallthrough
case KMessageBox : : No :
return true ;
case KMessageBox : : Cancel :
return false ;
}
}
return true ;
}
bool Learn : : closeWindow ( )
{
if ( ! warnClose ( ) )
{
return false ;
}
else
{
close ( ) ;
return true ;
}
}
bool Learn : : queryClose ( )
{
if ( ! warnClose ( ) )
return false ; // cancel
saveScores ( ) ; // also sync()s;
saveMainWindowSettings ( Config : : self ( ) - > config ( ) , " LearnWindow " ) ;
return true ;
}
void Learn : : random ( )
{
int rand = static_cast < int > ( static_cast < float > ( list . count ( ) ) / ( static_cast < float > ( RAND_MAX ) / kapp - > random ( ) ) ) ;
current = list . at ( rand - 1 ) ;
update ( ) ;
}
void Learn : : next ( )
{
+ + current ;
if ( current = = list . end ( ) )
current = list . begin ( ) ;
update ( ) ;
}
void Learn : : prev ( )
{
if ( Tabs - > currentPageIndex ( ) = = 1 )
{
if ( ! prevItem )
return ;
curItem = prevItem ;
statusBar ( ) - > clear ( ) ;
qupdate ( ) ;
nogood = true ;
backAct - > setEnabled ( false ) ;
return ;
}
if ( current = = list . begin ( ) )
current = list . end ( ) ;
- - current ;
update ( ) ;
}
void Learn : : update ( )
{
View - > clear ( ) ;
Dict : : Entry curKanji = * current ;
if ( ! curKanji . kanji ( ) )
{
statusBar ( ) - > message ( i18n ( " Grade not loaded " ) ) ; // oops
return ;
}
View - > addKanjiResult ( curKanji ) ;
// now show some compounds in which this kanji appears
TQString kanji = curKanji . kanji ( ) ;
Dict : : SearchResult compounds = index - > search ( TQRegExp ( kanji ) , kanji , true ) ;
View - > addHeader ( i18n ( " %1 in compounds " ) . tqarg ( kanji ) ) ;
for ( TQValueListIterator < Dict : : Entry > it = compounds . list . begin ( ) ; it ! = compounds . list . end ( ) ; + + it )
{
kapp - > processEvents ( ) ;
View - > addResult ( * it , true ) ;
}
View - > flush ( ) ;
}
void Learn : : updateGrade ( )
{
int grade = getCurrentGrade ( ) ;
TQString regexp ( " G%1 " ) ;
regexp = regexp . tqarg ( grade ) ;
Dict : : SearchResult result = index - > searchKanji ( TQRegExp ( regexp ) , regexp , false ) ;
list = result . list ;
statusBar ( ) - > message ( i18n ( " %1 entries in grade %2 " ) . tqarg ( list . count ( ) ) . tqarg ( grade ) ) ;
list . remove ( list . begin ( ) ) ;
current = list . begin ( ) ;
update ( ) ;
Config : : self ( ) - > setGrade ( grade ) ;
}
void Learn : : read ( const KURL & url )
{
List - > clear ( ) ;
KLoader loader ( url ) ;
if ( ! loader . open ( ) )
{
KMessageBox : : error ( this , loader . error ( ) , i18n ( " Error " ) ) ;
return ;
}
TQTextCodec & codec = * TQTextCodec : : codecForName ( " eucJP " ) ;
TQTextStream & stream = loader . textStream ( ) ;
stream . setCodec ( & codec ) ;
while ( ! stream . atEnd ( ) )
{
TQChar kanji ;
stream > > kanji ;
// ignore whitespace
if ( ! kanji . isSpace ( ) )
{
TQRegExp regexp ( TQString ( " ^%1 \\ W " ) . tqarg ( kanji ) ) ;
Dict : : SearchResult res = index - > searchKanji ( regexp , kanji , false ) ;
Dict : : Entry first = Dict : : firstEntry ( res ) ;
if ( first . extendedKanjiInfo ( ) )
add ( first , true ) ;
}
}
setClean ( ) ;
}
void Learn : : open ( )
{
if ( ! warnClose ( ) )
return ;
KURL prevname = filename ;
filename = KFileDialog : : getOpenURL ( TQString ( ) , " *.kiten " ) ;
if ( filename . isEmpty ( ) )
{
filename = prevname ;
return ;
}
read ( filename ) ;
//kdDebug() << "saving lastFile\n";
Config * config = Config : : self ( ) ;
config - > setLastFile ( filename . url ( ) ) ;
// redo quiz, because we deleted the current quiz item
curItem = List - > firstChild ( ) ;
backAct - > setEnabled ( false ) ;
prevItem = curItem ;
qnew ( ) ;
numChanged ( ) ;
}
void Learn : : openNew ( )
{
if ( ! warnClose ( ) )
return ;
filename = " " ;
setCaption ( " " ) ;
List - > clear ( ) ;
setClean ( ) ;
numChanged ( ) ;
}
void Learn : : saveAs ( )
{
KURL prevname = filename ;
filename = KFileDialog : : getSaveURL ( TQString ( ) , " *.kiten " ) ;
if ( filename . isEmpty ( ) )
{
filename = prevname ;
return ;
}
save ( ) ;
}
void Learn : : save ( )
{
if ( filename . isEmpty ( ) )
saveAs ( ) ;
if ( filename . isEmpty ( ) )
return ;
write ( filename ) ;
Config * config = Config : : self ( ) ;
config - > setLastFile ( filename . url ( ) ) ;
}
void Learn : : write ( const KURL & url )
{
KSaver saver ( url ) ;
if ( ! saver . open ( ) )
{
KMessageBox : : error ( this , saver . error ( ) , i18n ( " Error " ) ) ;
return ;
}
TQTextCodec & codec = * TQTextCodec : : codecForName ( " eucJP " ) ;
TQTextStream & stream = saver . textStream ( ) ;
stream . setCodec ( & codec ) ;
for ( TQListViewItemIterator it ( List ) ; it . current ( ) ; + + it )
stream < < it . current ( ) - > text ( 0 ) . tqat ( 0 ) ;
if ( ! saver . close ( ) )
{
KMessageBox : : error ( this , saver . error ( ) , i18n ( " Error " ) ) ;
return ;
}
saveScores ( ) ;
setClean ( ) ;
statusBar ( ) - > message ( i18n ( " %1 written " ) . tqarg ( url . prettyURL ( ) ) ) ;
}
void Learn : : saveScores ( )
{
KConfig & config = * Config : : self ( ) - > config ( ) ;
config . setGroup ( " Learn Scores " ) ;
for ( TQListViewItemIterator it ( List ) ; it . current ( ) ; + + it )
config . writeEntry ( it . current ( ) - > text ( 0 ) , it . current ( ) - > text ( 4 ) . toInt ( ) ) ;
config . sync ( ) ;
Config : : self ( ) - > writeConfig ( ) ;
}
void Learn : : add ( Dict : : Entry toAdd , bool noEmit )
{
// Remove peripheral readings: This is a study mode, not a reference mode
TQRegExp inNames ( " , \\ s*[A-Za-z ]+:.* " ) ;
TQString readings = Dict : : prettyKanjiReading ( toAdd . readings ( ) ) . replace ( inNames , " " ) ;
TQString meanings = shortenString ( Dict : : prettyMeaning ( toAdd . meanings ( ) ) . replace ( inNames , " " ) ) ;
TQString kanji = toAdd . kanji ( ) ;
// here's a dirty rotten cheat (well, not really)
// noEmit always means it's not added by the user, so this check isn't needed
if ( ! noEmit )
{
for ( TQListViewItemIterator it ( List ) ; it . current ( ) ; + + it )
{
if ( it . current ( ) - > text ( 0 ) = = kanji )
{
statusBar ( ) - > message ( i18n ( " %1 already on your list " ) . tqarg ( kanji ) ) ;
return ;
}
}
}
statusBar ( ) - > message ( i18n ( " %1 added to your list " ) . tqarg ( kanji ) ) ;
KConfig & config = * Config : : self ( ) - > config ( ) ;
int score = 0 ;
config . setGroup ( " Learn Scores " ) ;
score = config . readNumEntry ( kanji , score ) ;
unsigned int grade = toAdd . grade ( ) ;
addItem ( new LearnItem ( List , kanji , meanings , readings , TQString : : number ( grade ) , TQString : : number ( score ) ) , noEmit ) ;
numChanged ( ) ;
}
void Learn : : add ( )
{
add ( * current ) ;
setDirty ( ) ;
}
void Learn : : addAll ( )
{
int grade = getCurrentGrade ( ) ;
TQString regexp ( " G%1 " ) ;
regexp = regexp . tqarg ( grade ) ;
Dict : : SearchResult result = index - > searchKanji ( TQRegExp ( regexp ) , regexp , false ) ;
for ( TQValueListIterator < Dict : : Entry > i = result . list . begin ( ) ; i ! = result . list . end ( ) ; + + i )
{
// don't add headers
if ( ( * i ) . dictName ( ) = = " __NOTSET " & & ( * i ) . header ( ) = = " __NOTSET " )
add ( * i ) ;
}
}
void Learn : : addItem ( TQListViewItem * item , bool noEmit )
{
// 2 is the magic jump
if ( List - > childCount ( ) = = 2 )
{
curItem = item ;
prevItem = curItem ;
qnew ( ) ; // init first quiz
//kdDebug() << "initting first quiz in addItem\n";
}
if ( ! noEmit )
{
List - > ensureItemVisible ( item ) ;
setDirty ( ) ;
}
}
void Learn : : showKanji ( TQListViewItem * item )
{
assert ( item ) ;
TQString kanji ( item - > text ( 0 ) ) ;
int grade = item - > text ( 3 ) . toUInt ( ) ;
if ( getCurrentGrade ( ) ! = grade )
{
setCurrentGrade ( grade ) ;
updateGrade ( ) ;
}
// Why does this fail to find the kanji sometimes?
for ( current = list . begin ( ) ; current ! = list . end ( ) & & ( * current ) . kanji ( ) ! = kanji ; + + current ) ;
update ( ) ;
}
void Learn : : del ( )
{
// quiz page
if ( Tabs - > currentPageIndex ( ) = = 1 )
{
delete curItem ;
curItem = prevItem ; // needs to be something
qnew ( ) ;
}
else // setup page
{
TQPtrList < TQListViewItem > selected = List - > selectedItems ( ) ;
assert ( selected . count ( ) ) ;
bool makenewq = false ; // must make new quiz if we
// delete the current item
for ( TQPtrListIterator < TQListViewItem > i ( selected ) ; * i ; + + i )
{
if ( curItem = = i )
makenewq = true ;
delete * i ;
}
curItem = List - > firstChild ( ) ;
prevItem = curItem ;
backAct - > setEnabled ( false ) ;
if ( makenewq )
{
qnew ( ) ;
}
setDirty ( ) ;
}
itemSelectionChanged ( ) ;
numChanged ( ) ;
}
// too easy...
void Learn : : print ( )
{
View - > clear ( ) ;
View - > addHeader ( TQString ( " <h1>%1</h1> " ) . tqarg ( i18n ( " Learning List " ) ) , 1 ) ;
TQListViewItemIterator it ( List ) ;
for ( ; it . current ( ) ; + + it )
{
TQString kanji = it . current ( ) - > text ( 0 ) ;
Dict : : SearchResult result = index - > searchKanji ( TQRegExp ( kanji ) , kanji , false ) ;
for ( TQValueListIterator < Dict : : Entry > i = result . list . begin ( ) ; i ! = result . list . end ( ) ; + + i )
{
if ( ( * i ) . dictName ( ) = = " __NOTSET " & & ( * i ) . header ( ) = = " __NOTSET " )
{
View - > addKanjiResult ( * i ) ;
break ;
}
}
}
View - > print ( ) ;
}
void Learn : : answerClicked ( int i )
{
if ( ! curItem )
return ;
int newscore = 0 ;
// KConfig &config = *Config::self()->config();
// config.setGroup("Learn");
bool donew = false ;
if ( seikai = = i )
{
statusBar ( ) - > message ( i18n ( " Good! " ) ) ;
if ( ! nogood ) // add two to their score
newscore = curItem - > text ( 4 ) . toInt ( ) + 2 ;
else
{
qnew ( ) ;
return ;
}
donew = true ;
}
else
{
statusBar ( ) - > message ( i18n ( " Wrong " ) ) ;
// take one off score
newscore = curItem - > text ( 4 ) . toInt ( ) - 1 ;
if ( ! nogood )
nogood = true ;
else
return ;
}
//config.writeEntry(curItem->text(0) + "_4", newscore);
TQListViewItem * newItem = new LearnItem ( List , curItem - > text ( 0 ) , curItem - > text ( 1 ) , curItem - > text ( 2 ) , curItem - > text ( 3 ) , TQString : : number ( newscore ) ) ;
// readd, so it sorts
// 20 November 2004: why?? why not List->sort() ??
// haha I used to be naive
delete curItem ;
curItem = newItem ;
if ( donew )
qnew ( ) ;
}
TQString Learn : : randomMeaning ( TQStringList & oldMeanings )
{
TQString meaning ;
do
{
float rand = kapp - > random ( ) ;
if ( ( rand > ( RAND_MAX / 2 ) ) | | ( List - > childCount ( ) < numberOfAnswers ) )
{
// get a meaning from dict
//kdDebug() << "from our dict\n";
rand = kapp - > random ( ) ;
float rand2 = RAND_MAX / rand ;
rand = ( ( float ) list . count ( ) - 1 ) / rand2 ;
//rand -= 1;
//kdDebug() << "rand: " << rand << endl;
//kdDebug() << "list.count(): " << list.count() << endl;
switch ( guessOn )
{
case 1 :
meaning = shortenString ( Dict : : prettyMeaning ( ( * list . at ( static_cast < unsigned int > ( rand ) ) ) . meanings ( ) ) ) ;
break ;
case 2 :
meaning = Dict : : prettyKanjiReading ( ( * list . at ( static_cast < unsigned int > ( rand ) ) ) . readings ( ) ) ;
break ;
case 0 :
meaning = ( * list . at ( static_cast < unsigned int > ( rand ) ) ) . kanji ( ) ;
}
}
else
{
// get a meaning from our list
//kdDebug() << "from our list\n";
rand = kapp - > random ( ) ;
float rand2 = RAND_MAX / rand ;
rand = List - > childCount ( ) / rand2 ;
int max = ( int ) rand ;
TQListViewItemIterator it ( List ) ;
it + = max ;
meaning = it . current ( ) - > text ( guessOn ) ;
}
//kdDebug() << "meaning: " << meaning << endl;
for ( TQStringList : : Iterator it = oldMeanings . begin ( ) ; it ! = oldMeanings . end ( ) ; + + it )
{
//kdDebug() << "oldMeaning: " << *it << endl;
}
//kdDebug() << "curMeaning: " << curItem->text(guessOn) << endl;
}
while ( oldMeanings . contains ( meaning ) | | meaning = = curItem - > text ( guessOn ) ) ;
oldMeanings . append ( meaning ) ;
meaning = shortenString ( meaning ) ;
return meaning ;
}
void Learn : : qupdate ( )
{
if ( ! curItem )
return ;
qKanji - > setText ( curItem - > text ( quizOn ) ) ;
TQFont newFont = font ( ) ;
if ( quizOn = = 0 )
newFont . setPixelSize ( 24 ) ;
qKanji - > setFont ( newFont ) ;
float rand = kapp - > random ( ) ;
float rand2 = RAND_MAX / rand ;
seikai = static_cast < int > ( numberOfAnswers / rand2 ) ;
TQStringList oldMeanings ;
for ( int i = 0 ; i < numberOfAnswers ; + + i )
answers - > find ( i ) - > setText ( randomMeaning ( oldMeanings ) ) ;
answers - > find ( seikai ) - > setText ( curItem - > text ( guessOn ) ) ;
}
struct Learn : : scoreCompare
{
bool operator ( ) ( const TQListViewItem * v1 , const TQListViewItem * v2 )
{
return v1 - > text ( 4 ) . toInt ( ) < v2 - > text ( 4 ) . toInt ( ) ;
}
} ;
void Learn : : qnew ( ) // new quiz kanji
{
//kdDebug() << "qnew\n";
nogood = false ;
statusBar ( ) - > clear ( ) ;
statusBar ( ) - > message ( TQString ( " %1 %2 %3 " ) . tqarg ( curItem - > text ( 0 ) ) . tqarg ( curItem - > text ( 1 ) ) . tqarg ( curItem - > text ( 2 ) ) ) ;
backAct - > setEnabled ( true ) ;
unsigned int count = List - > childCount ( ) ;
if ( count < 2 )
return ;
// the following lines calculate which kanji will be used next:
// use f(2) every third time, f(1) otherwise
// where f(1) = numberOfItems * rand[0..1]
// and f(2) = numberOfItems * rand[0..1] * rand[0..1]
// rand[0..1] = kapp->random() / RAND_MAX
float max = static_cast < float > ( count ) / ( static_cast < float > ( RAND_MAX ) / kapp - > random ( ) ) ;
if ( kapp - > random ( ) < ( static_cast < float > ( RAND_MAX ) / 3.25 ) )
max / = ( static_cast < float > ( RAND_MAX ) / ( kapp - > random ( ) + 1 ) ) ;
max = static_cast < int > ( max ) ;
if ( max > count )
max = count ;
std : : multiset < const TQListViewItem * , scoreCompare > scores ;
TQListViewItemIterator sIt ( List ) ;
for ( ; sIt . current ( ) ; + + sIt )
scores . insert ( sIt . current ( ) ) ;
std : : multiset < const TQListViewItem * , scoreCompare > : : iterator it = scores . begin ( ) ;
std : : multiset < const TQListViewItem * , scoreCompare > : : iterator tmp = scores . begin ( ) ;
int i ;
for ( i = 2 ; i < = max ; + + it )
{ i + + ; + + tmp ; }
if ( curItem - > text ( 0 ) = = ( * it ) - > text ( 0 ) ) // same, don't use
{
+ + it ;
if ( it = = scores . end ( ) )
{
tmp - - ;
it = tmp ;
}
}
if ( it = = scores . end ( ) )
{
return ;
}
prevItem = curItem ;
curItem = const_cast < TQListViewItem * > ( * it ) ;
qKanji - > setFocus ( ) ;
qupdate ( ) ;
}
void Learn : : cheat ( )
{
answers - > find ( seikai ) - > setFocus ( ) ;
statusBar ( ) - > message ( i18n ( " Better luck next time " ) ) ;
nogood = true ;
}
TQString Learn : : shortenString ( const TQString & thestring )
{
return KStringHandler : : rsqueeze ( thestring , 60 ) . stripWhiteSpace ( ) ;
}
void Learn : : tabChanged ( TQWidget * widget )
{
bool isQuiz = ( widget = = quizTop ) ;
if ( isQuiz )
backAct - > setEnabled ( prevItem ! = 0 ) ;
else
backAct - > setEnabled ( true ) ;
forwardAct - > setEnabled ( ! isQuiz ) ;
gradeAct - > setEnabled ( ! isQuiz ) ;
saveAct - > setEnabled ( ! isQuiz ) ;
addAct - > setEnabled ( ! isQuiz ) ;
addAllAct - > setEnabled ( ! isQuiz ) ;
randomAct - > setEnabled ( ! isQuiz ) ;
openAct - > setEnabled ( ! isQuiz ) ;
newAct - > setEnabled ( ! isQuiz ) ;
saveAsAct - > setEnabled ( ! isQuiz ) ;
cheatAct - > setEnabled ( isQuiz ) ;
// also handled below for !isQuiz case
removeAct - > setEnabled ( isQuiz ) ;
if ( isQuiz )
{
qKanji - > setFocus ( ) ;
}
else
{
// handle removeAct;
itemSelectionChanged ( ) ;
}
statusBar ( ) - > clear ( ) ;
}
void Learn : : updateQuiz ( )
{
if ( List - > childCount ( ) < 3 )
Tabs - > setTabEnabled ( quizTop , false ) ;
else
Tabs - > setTabEnabled ( quizTop , true ) ;
}
void Learn : : itemSelectionChanged ( )
{
removeAct - > setEnabled ( List - > selectedItems ( ) . count ( ) > 0 ) ;
}
int Learn : : getCurrentGrade ( void )
{
int grade = gradeAct - > currentItem ( ) + 1 ;
if ( grade > 6 ) + + grade ;
return grade ;
}
void Learn : : setCurrentGrade ( int grade )
{
if ( grade > 6 ) - - grade ;
gradeAct - > setCurrentItem ( grade - 1 ) ;
}
void Learn : : updateQuizConfiguration ( )
{
Config * config = Config : : self ( ) ;
quizOn = config - > quizOn ( ) ;
guessOn = config - > guessOn ( ) ;
answers - > setTitle ( List - > columnText ( guessOn ) ) ;
View - > updateFont ( ) ;
if ( List - > childCount ( ) > = 2 & & initialized )
qnew ( ) ;
}
void Learn : : setDirty ( )
{
isMod = true ;
setCaption ( filename . prettyURL ( ) , true ) ;
}
void Learn : : setClean ( )
{
isMod = false ;
if ( ! filename . prettyURL ( ) . isEmpty ( ) )
setCaption ( filename . prettyURL ( ) , false ) ;
}
void Learn : : qKanjiClicked ( )
{
if ( ! curItem )
return ;
showKanji ( curItem ) ;
nogood = true ;
}
void Learn : : numChanged ( )
{
Tabs - > setTabEnabled ( quizTop , List - > childCount ( ) > = 2 ) ;
//quizTop->setEnabled(List->childCount() >= 2);
}
# include "learn.moc"