koBgSpellCheck.cc
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "koBgSpellCheck.h"
00023 #include "koBgSpellCheck.moc"
00024 #include <qtimer.h>
00025 #include <kdebug.h>
00026 #include <kospell.h>
00027 #include <koSconfig.h>
00028 #include <ksconfig.h>
00029 #include <kotextobject.h>
00030 #include <klocale.h>
00031
00032
00033
00034 class KoBgSpellCheck::KoBgSpellCheckPrivate
00035 {
00036 public:
00037 KSpellConfig * m_pKSpellConfig;
00038 QTimer * startTimer;
00039 QTimer * nextParagraphTimer;
00040 };
00041
00042 KoBgSpellCheck::KoBgSpellCheck()
00043 {
00044 #ifdef DEBUG_BGSPELLCHECKING
00045 kdDebug(32500) << "KoBgSpellCheck::KoBgSpellCheck " << this << endl;
00046 #endif
00047 d = new KoBgSpellCheck::KoBgSpellCheckPrivate;
00048 d->m_pKSpellConfig=0L;
00049 d->startTimer = new QTimer( this );
00050 connect( d->startTimer, SIGNAL( timeout() ),
00051 this, SLOT( startBackgroundSpellCheck() ) );
00052 d->nextParagraphTimer = new QTimer( this );
00053 connect( d->nextParagraphTimer, SIGNAL( timeout() ),
00054 this, SLOT( spellCheckNextParagraph() ) );
00055
00056 m_bgSpell.kspell=0L;
00057 m_bDontCheckUpperWord=false;
00058 m_bSpellCheckEnabled=false;
00059 m_bDontCheckTitleCase=false;
00060 m_bSpellCheckConfigure=false;
00061 m_bgSpell.currentTextObj=0L;
00062 m_bgSpell.needsRepaint=false;
00063 }
00064
00065 KoBgSpellCheck::~KoBgSpellCheck()
00066 {
00067 if ( m_bgSpell.kspell ) {
00068 m_bgSpell.kspell->cleanUp();
00069 delete m_bgSpell.kspell;
00070 }
00071 delete d->m_pKSpellConfig;
00072 delete d;
00073 }
00074
00075 void KoBgSpellCheck::addPersonalDictonary( const QString & word )
00076 {
00077 if ( m_bgSpell.kspell )
00078 {
00079 m_bgSpell.kspell->addPersonal ( word);
00080 }
00081 }
00082
00083 void KoBgSpellCheck::spellCheckParagraphDeleted( KoTextParag *_parag, KoTextObject *obj)
00084 {
00085 if ( m_bgSpell.currentTextObj == obj && m_bgSpell.currentParag == _parag)
00086 {
00087 stopSpellChecking();
00088 startBackgroundSpellCheck();
00089 }
00090 }
00091
00092
00093 void KoBgSpellCheck::enableBackgroundSpellCheck( bool b )
00094 {
00095 m_bSpellCheckEnabled=b;
00096 startBackgroundSpellCheck();
00097 }
00098
00099 void KoBgSpellCheck::setIgnoreUpperWords( bool b)
00100 {
00101 stopSpellChecking();
00102 m_bDontCheckUpperWord = b;
00103 startBackgroundSpellCheck();
00104 }
00105
00106 void KoBgSpellCheck::setIgnoreTitleCase( bool b)
00107 {
00108 stopSpellChecking();
00109 m_bDontCheckTitleCase = b;
00110 startBackgroundSpellCheck();
00111 }
00112
00113 void KoBgSpellCheck::addIgnoreWordAll( const QString & word)
00114 {
00115 if( m_spellListIgnoreAll.findIndex( word )==-1)
00116 m_spellListIgnoreAll.append( word );
00117 stopSpellChecking();
00118 spellConfig()->setIgnoreList( m_spellListIgnoreAll );
00119 startBackgroundSpellCheck();
00120 }
00121
00122 void KoBgSpellCheck::addIgnoreWordAllList( const QStringList & list)
00123 {
00124 m_spellListIgnoreAll.clear();
00125 stopSpellChecking();
00126 spellConfig()->setIgnoreList( list );
00127 startBackgroundSpellCheck();
00128 }
00129
00130 void KoBgSpellCheck::clearIgnoreWordAll( )
00131 {
00132 m_spellListIgnoreAll.clear();
00133 stopSpellChecking();
00134 spellConfig()->setIgnoreList( m_spellListIgnoreAll );
00135 startBackgroundSpellCheck();
00136 }
00137
00138 void KoBgSpellCheck::startBackgroundSpellCheck()
00139 {
00140 d->startTimer->stop();
00141 if ( !m_bSpellCheckEnabled )
00142 return;
00143
00144 if ( !m_bgSpell.currentTextObj )
00145 {
00146 m_bgSpell.currentTextObj = nextTextObject(m_bgSpell.currentTextObj );
00147 }
00148 if ( !m_bgSpell.currentTextObj )
00149 {
00150 #ifdef DEBUG_BGSPELLCHECKING
00151
00152 #endif
00153 d->startTimer->start( 1000, true );
00154 return;
00155 }
00156 #ifdef DEBUG_BGSPELLCHECKING
00157 kdDebug(32500) << "KoBgSpellCheck::startBackgroundSpellCheck" << endl;
00158 #endif
00159
00160 m_bgSpell.currentParag = m_bgSpell.currentTextObj->textDocument()->firstParag();
00161 nextParagraphNeedingCheck();
00162
00163 #ifdef DEBUG_BGSPELLCHECKING
00164 kdDebug(32500) << "fs=" << m_bgSpell.currentTextObj << " parag=" << m_bgSpell.currentParag << endl;
00165 #endif
00166
00167 if ( !m_bgSpell.currentTextObj || !m_bgSpell.currentParag ) {
00168 if ( m_bgSpell.currentTextObj )
00169 {
00170 if ( (m_bgSpell.currentTextObj->textDocument()->firstParag() == m_bgSpell.currentTextObj->textDocument()->lastParag()) && m_bgSpell.currentTextObj->textDocument()->firstParag()->length() <= 1)
00171 m_bgSpell.currentTextObj->setNeedSpellCheck(false);
00172 }
00173
00174 #ifdef DEBUG_BGSPELLCHECKING
00175 kdDebug(32500) << "KoBgSpellCheck::startBackgroundSpellCheck nothing to check this time." << endl;
00176 #endif
00177 d->startTimer->start( 1000, true );
00178 return;
00179 }
00180
00181 bool needsWait = false;
00182 if ( !m_bgSpell.kspell )
00183 {
00184 m_bgSpell.kspell = new KoSpell(0L, this, SLOT( spellCheckerReady() ), d->m_pKSpellConfig );
00185
00186 needsWait = true;
00187 connect( m_bgSpell.kspell, SIGNAL( death() ),
00188 this, SLOT( spellCheckerFinished() ) );
00189 connect( m_bgSpell.kspell, SIGNAL( misspelling( const QString &, int ) ),
00190 this, SLOT( spellCheckerMisspelling( const QString &, int ) ) );
00191 connect( m_bgSpell.kspell, SIGNAL( done() ),
00192 this, SLOT( spellCheckerDone() ) );
00193 }
00194 m_bgSpell.kspell->setIgnoreUpperWords( m_bDontCheckUpperWord );
00195 m_bgSpell.kspell->setIgnoreTitleCase( m_bDontCheckTitleCase );
00196 if ( !needsWait )
00197 spellCheckerReady();
00198 }
00199
00200 void KoBgSpellCheck::spellCheckerReady()
00201 {
00202
00203
00204 if (m_bgSpell.currentTextObj)
00205 m_bgSpell.currentParag = m_bgSpell.currentTextObj->textDocument()->firstParag();
00206
00207 #ifdef DEBUG_BGSPELLCHECKING
00208 kdDebug(32500) << "KoBgSpellCheck::spellCheckerReady textobj=" << m_bgSpell.currentTextObj << endl;
00209 #endif
00210 d->nextParagraphTimer->start( 10, true );
00211 }
00212
00213
00214
00215 void KoBgSpellCheck::nextParagraphNeedingCheck()
00216 {
00217 #ifdef DEBUG_BGSPELLCHECKING
00218 kdDebug(32500) << "KoBgSpellCheck::nextParagraphNeedingCheck textobj=" <<m_bgSpell.currentTextObj <<endl;
00219 #endif
00220 if ( !m_bgSpell.currentTextObj ) {
00221 m_bgSpell.currentParag = 0L;
00222 return;
00223 }
00224
00225
00226
00227
00228 if(m_bgSpell.needsRepaint)
00229 {
00230 slotRepaintChanged( m_bgSpell.currentTextObj );
00231 m_bgSpell.needsRepaint=false;
00232 }
00233
00234 KoTextParag* parag = m_bgSpell.currentParag;
00235 if ( parag && parag->string() && parag->string()->needsSpellCheck() )
00236 {
00237 #ifdef DEBUG_BGSPELLCHECKING
00238 kdDebug(32500) << "current parag " << parag << " needs checking again." <<endl;
00239 #endif
00240 return;
00241 }
00242
00243 if ( parag && parag->next() )
00244 parag = parag->next();
00245
00246 while ( parag && !parag->string()->needsSpellCheck() )
00247 parag = parag->next();
00248 while ( parag && parag->length() <= 1 )
00249 {
00250 parag->string()->setNeedsSpellCheck( false );
00251 while ( parag && !parag->string()->needsSpellCheck() )
00252 parag = parag->next();
00253 }
00254
00255 if ( !parag ) {
00256 parag = m_bgSpell.currentTextObj->textDocument()->firstParag();
00257 while ( parag != m_bgSpell.currentParag && !parag->string()->needsSpellCheck() )
00258 parag = parag->next();
00259 while ( parag != m_bgSpell.currentParag && parag->length() <= 1 )
00260 {
00261 parag->string()->setNeedsSpellCheck( false );
00262 while ( parag != m_bgSpell.currentParag && !parag->string()->needsSpellCheck() )
00263 parag = parag->next();
00264 }
00265 if ( parag == m_bgSpell.currentParag && !parag->string()->needsSpellCheck() )
00266 parag = 0;
00267 }
00268
00269 if ( parag )
00270 m_bgSpell.currentParag = parag;
00271 else
00272 {
00273 KoTextObject *obj = m_bgSpell.currentTextObj;
00274
00275 obj->setNeedSpellCheck(false);
00276
00277 m_bgSpell.currentTextObj = nextTextObject( m_bgSpell.currentTextObj );
00278
00279 if ( m_bgSpell.currentTextObj && m_bgSpell.currentTextObj != obj)
00280 {
00281 m_bgSpell.currentParag = m_bgSpell.currentTextObj->textDocument()->firstParag();
00282 }
00283 else
00284 {
00285 if ( m_bgSpell.currentTextObj )
00286 m_bgSpell.currentTextObj->setNeedSpellCheck( false );
00287 m_bgSpell.currentParag = 0L;
00288 }
00289 }
00290
00291
00292 }
00293
00294 void KoBgSpellCheck::spellCheckNextParagraph()
00295 {
00296 #ifdef DEBUG_BGSPELLCHECKING
00297 kdDebug(32500) << "KoBgSpellCheck::spellCheckNextParagraph" << endl;
00298 #endif
00299
00300 nextParagraphNeedingCheck();
00301 #ifdef DEBUG_BGSPELLCHECKING
00302 kdDebug(32500) << "textobj=" << m_bgSpell.currentTextObj << " parag=" << m_bgSpell.currentParag << endl;
00303 #endif
00304 if ( !m_bgSpell.currentTextObj || !m_bgSpell.currentParag )
00305 {
00306 #ifdef DEBUG_BGSPELLCHECKING
00307 kdDebug(32500) << "KoBgSpellCheck::spellCheckNextParagraph scheduling restart" << endl;
00308 #endif
00309
00310
00311 d->startTimer->start( 100, true );
00312 return;
00313 }
00314
00315
00316 KoTextStringChar *ch = m_bgSpell.currentParag->at( 0 );
00317 KoTextFormat format( *ch->format() );
00318 format.setMisspelled( false );
00319 m_bgSpell.currentParag->setFormat( 0, m_bgSpell.currentParag->length()-1, &format, true, KoTextFormat::Misspelled );
00320 #ifdef DEBUG_BGSPELLCHECKING
00321 kdDebug(32500) << "KoBgSpellCheck::spellCheckNextParagraph spell checking parag " << m_bgSpell.currentParag->paragId() << endl;
00322 #endif
00323
00324
00325 QString text = m_bgSpell.currentParag->string()->toString();
00326 text.remove( text.length() - 1, 1 );
00327
00328
00329
00330
00331
00332 m_bgSpell.currentParag->string()->setNeedsSpellCheck( false );
00333
00334
00335 m_bgSpell.kspell->check(text);
00336 }
00337
00338 void KoBgSpellCheck::spellCheckerMisspelling(const QString &old, int pos )
00339 {
00340 KoTextObject * textobj = m_bgSpell.currentTextObj;
00341 #ifdef DEBUG_BGSPELLCHECKING
00342 kdDebug(32500) << "KoBgSpellCheck::spellCheckerMisspelling textobj=" << textobj << " old=" << old << " pos=" << pos << endl;
00343 #endif
00344 Q_ASSERT( textobj );
00345 if ( !textobj ) return;
00346 KoTextParag* parag = m_bgSpell.currentParag;
00347 if ( !parag ) return;
00348 #ifdef DEBUG_BGSPELLCHECKING
00349 kdDebug(32500) << "KoBgSpellCheck::spellCheckerMisspelling parag=" << parag << " (id=" << parag->paragId() << ", length=" << parag->length() << ") pos=" << pos << " length=" << old.length() << endl;
00350 #endif
00351 KoTextStringChar *ch = parag->at( pos );
00352 KoTextFormat format( *ch->format() );
00353 format.setMisspelled( true );
00354 parag->setFormat( pos, old.length(), &format, true, KoTextFormat::Misspelled );
00355 }
00356
00357 void KoBgSpellCheck::spellCheckerDone()
00358 {
00359
00360
00361 m_bgSpell.currentParag->setChanged( true );
00362 m_bgSpell.needsRepaint=true;
00363
00364 #ifdef DEBUG_BGSPELLCHECKING
00365 kdDebug(32500) << "KoBgSpellCheck::spellCheckerDone" << endl;
00366 #endif
00367
00368 d->nextParagraphTimer->start( 10, true );
00369 }
00370
00371 void KoBgSpellCheck::spellCheckerFinished()
00372 {
00373 #ifdef DEBUG_BGSPELLCHECKING
00374 kdDebug(32500) << "--- KoBgSpellCheck::spellCheckerFinished ---" << endl;
00375 #endif
00376 KoSpell::spellStatus status = m_bgSpell.kspell->status();
00377 m_bgSpell.kspell->cleanUp();
00378 delete m_bgSpell.kspell;
00379 m_bgSpell.kspell = 0;
00380 m_bgSpell.currentParag = 0;
00381 m_bgSpell.currentTextObj = 0;
00382 if (status == KoSpell::Error)
00383 {
00384
00385 kdWarning() << "ISpell/ASpell not configured correctly." << endl;
00386 if ( !m_bSpellCheckConfigure )
00387 {
00388 m_bSpellCheckConfigure=true;
00389 configurateSpellChecker();
00390 }
00391 return;
00392 }
00393 else if (status == KoSpell::Crashed)
00394 {
00395 kdWarning() << "ISpell/ASpell seems to have crashed." << endl;
00396 return;
00397 }
00398
00399 }
00400
00401 KSpellConfig* KoBgSpellCheck::spellConfig()
00402 {
00403 if ( !d->m_pKSpellConfig )
00404 d->m_pKSpellConfig = new KSpellConfig();
00405 return d->m_pKSpellConfig;
00406 }
00407
00408 void KoBgSpellCheck::setKSpellConfig(const KOSpellConfig &_kspell)
00409 {
00410 (void)spellConfig();
00411 stopSpellChecking();
00412
00413 d->m_pKSpellConfig->setNoRootAffix(_kspell.noRootAffix ());
00414 d->m_pKSpellConfig->setRunTogether(_kspell.runTogether ());
00415 d->m_pKSpellConfig->setDictionary(_kspell.dictionary ());
00416 d->m_pKSpellConfig->setDictFromList(_kspell.dictFromList());
00417 d->m_pKSpellConfig->setEncoding(_kspell.encoding());
00418 d->m_pKSpellConfig->setClient(_kspell.client());
00419 m_bSpellCheckConfigure = false;
00420 startBackgroundSpellCheck();
00421 }
00422
00423 void KoBgSpellCheck::stopSpellChecking()
00424 {
00425 #ifdef DEBUG_BGSPELLCHECKING
00426 kdDebug(32500) << "KoBgSpellCheck::stopSpellChecking" << endl;
00427 #endif
00428 if ( m_bgSpell.kspell ) {
00429 m_bgSpell.kspell->cleanUp();
00430 delete m_bgSpell.kspell;
00431 m_bgSpell.kspell = 0;
00432 }
00433 m_bgSpell.currentParag = 0;
00434 m_bgSpell.currentTextObj = 0;
00435 d->startTimer->stop();
00436 d->nextParagraphTimer->stop();
00437 }
This file is part of the documentation for lib Library Version 1.3.5.