24#include <QtGui/QColor>
25#include <QtCore/QRegExp>
26#include <Qt3Support/Q3SyntaxHighlighter>
27#include <QtCore/QTimer>
35#include <Qt3Support/Q3Dict>
48class K3SyntaxHighlighter::K3SyntaxHighlighterPrivate
51 QColor col1, col2, col3, col4, col5;
56class K3SpellingHighlighter::K3SpellingHighlighterPrivate
60 K3SpellingHighlighterPrivate() :
61 alwaysEndsWithSpace( true ),
62 intraWordEditing( false ) {}
66 bool alwaysEndsWithSpace;
68 bool intraWordEditing;
71class K3DictSpellingHighlighter::K3DictSpellingHighlighterPrivate
74 K3DictSpellingHighlighterPrivate() :
78 rehighlightRequest( 0 ),
83 spellReady( false ) {}
85 ~K3DictSpellingHighlighterPrivate() {
86 delete rehighlightRequest;
90 static Q3Dict<int>* sDict()
93 statDict =
new Q3Dict<int>(50021);
99 Q3Dict<int> autoIgnoreDict;
100 static QObject *sDictionaryMonitor;
103 QTimer *rehighlightRequest, *spellTimeout;
105 int wordCount, errorCount;
106 int checksRequested, checksDone;
107 int disablePercentage;
108 int disableWordCount;
109 bool completeRehighlightRequired;
110 bool active, automatic, autoReady;
111 bool globalConfig, spellReady;
113 static Q3Dict<int>* statDict;
117Q3Dict<int>* K3DictSpellingHighlighter::K3DictSpellingHighlighterPrivate::statDict = 0;
122 const QColor& depth0,
123 const QColor& depth1,
124 const QColor& depth2,
125 const QColor& depth3,
130 d->enabled = colorQuoting;
148 setFormat( 0, text.length(), textEdit()->viewport()->paletteForegroundColor() );
152 QString simplified = text;
153 simplified = simplified.replace( QRegExp(
"\\s" ), QString() ).replace(
'|', QLatin1String(
">") );
154 while ( simplified.startsWith( QLatin1String(
">>>>") ) )
155 simplified = simplified.mid(3);
156 if ( simplified.startsWith( QLatin1String(
">>>") ) || simplified.startsWith( QString::fromLatin1(
"> > >") ) )
157 setFormat( 0, text.length(), d->col2 );
158 else if ( simplified.startsWith( QLatin1String(
">>") ) || simplified.startsWith( QString::fromLatin1(
"> >") ) )
159 setFormat( 0, text.length(), d->col3 );
160 else if ( simplified.startsWith( QLatin1String(
">") ) )
161 setFormat( 0, text.length(), d->col4 );
163 setFormat( 0, text.length(), d->col5 );
168 const QColor& spellColor,
170 const QColor& depth0,
171 const QColor& depth1,
172 const QColor& depth2,
173 const QColor& depth3 )
174 :
K3SyntaxHighlighter( textEdit, colorQuoting, depth0, depth1, depth2, depth3 ),d(new K3SpellingHighlighterPrivate())
177 d->color = spellColor;
191 QString diffAndCo(
">|" );
193 bool isCode = diffAndCo.contains(text[0]);
195 if ( !text.endsWith(
' ') )
196 d->alwaysEndsWithSpace =
false;
202 textEdit()->getCursorPosition( ¶, &index );
203 int len = text.length();
204 if ( d->alwaysEndsWithSpace )
209 for (
int i = 0; i < len; i++ ) {
210 if ( !text[i].isLetter() && (!(text[i] ==
'\'')) ) {
211 if ( ( para != paraNo ) ||
213 ( i - d->currentWord.length() > index ) ||
219 d->currentPos = i + 1;
221 d->currentWord += text[i];
224 if ( ( len > 0 && !text[len - 1].isLetter() ) ||
225 ( index + 1 ) != text.length() ||
236 l.append(
"KOrganizer" );
237 l.append(
"KAddressBook" );
241 l.append(
"Konqueror" );
242 l.append(
"K3Spell" );
243 l.append(
"Kontact" );
248void K3SpellingHighlighter::flushCurrentWord()
250 while ( d->currentWord[0].isPunct() ) {
251 d->currentWord = d->currentWord.mid( 1 );
256 while ( !d->currentWord.isEmpty() && ( ch = d->currentWord[(
int) d->currentWord.length() - 1] ).isPunct() &&
257 ch !=
'(' && ch !=
'@' )
258 d->currentWord.truncate( d->currentWord.length() - 1 );
260 if ( !d->currentWord.isEmpty() ) {
262 setFormat( d->currentPos, d->currentWord.length(), d->color );
269QObject *K3DictSpellingHighlighter::K3DictSpellingHighlighterPrivate::sDictionaryMonitor = 0;
272 bool spellCheckingActive ,
274 const QColor& spellColor,
276 const QColor& depth0,
277 const QColor& depth1,
278 const QColor& depth2,
279 const QColor& depth3,
282 colorQuoting, depth0, depth1, depth2, depth3 ),d(new K3DictSpellingHighlighterPrivate())
285 d->mSpellConfig = spellConfig;
286 d->globalConfig = ( !spellConfig );
287 d->automatic = autoEnable;
288 d->active = spellCheckingActive;
289 d->checksRequested = 0;
291 d->completeRehighlightRequired =
false;
294 d->disablePercentage = cg.
readEntry(
"K3Spell_AsYouTypeDisablePercentage", QVariant(42 )).toInt();
295 d->disablePercentage = qMin( d->disablePercentage, 101 );
296 d->disableWordCount = cg.
readEntry(
"K3Spell_AsYouTypeDisableWordCount", QVariant(100 )).toInt();
298 textEdit->installEventFilter(
this );
299 textEdit->viewport()->installEventFilter(
this );
301 d->rehighlightRequest =
new QTimer(
this);
302 connect( d->rehighlightRequest, SIGNAL(
timeout()),
304 d->spellTimeout =
new QTimer(
this);
305 connect( d->spellTimeout, SIGNAL(
timeout()),
308 if ( d->globalConfig ) {
311 if ( !d->sDictionaryMonitor )
312 d->sDictionaryMonitor =
new QObject();
315 d->mDict =
new Q3Dict<int>(4001);
316 connect( d->mSpellConfig, SIGNAL(configChanged()),
334 kDebug(0) <<
"KDictSpellingHighlighter::slotSpellReady( " << spell <<
" )";
335 if ( d->globalConfig ) {
336 connect( d->sDictionaryMonitor, SIGNAL(destroyed()),
339 if ( spell != d->spell )
344 d->spellReady =
true;
346 for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it ) {
347 d->spell->addPersonal( *it );
349 connect( spell, SIGNAL(misspelling(QString,QStringList,uint)),
351 connect( spell, SIGNAL(corrected(QString,QString,uint)),
353 d->checksRequested = 0;
355 d->completeRehighlightRequired =
true;
356 d->rehighlightRequest->start( 0,
true );
371 d->autoIgnoreDict.replace( word,
Ignore );
374 Q3Dict<int>* dict = ( d->globalConfig ? d->sDict() : d->mDict );
375 if ( !dict->isEmpty() && (*dict)[word] ==
NotOkay ) {
376 if ( d->autoReady && ( d->autoDict[word] !=
NotOkay )) {
377 if ( !d->autoIgnoreDict[word] )
379 d->autoDict.replace( word,
NotOkay );
384 if ( !dict->isEmpty() && (*dict)[word] ==
Okay ) {
385 if ( d->autoReady && !d->autoDict[word] ) {
386 d->autoDict.replace( word,
Okay );
391 if ((dict->isEmpty() || !((*dict)[word])) && d->spell ) {
393 textEdit()->getCursorPosition( ¶, &index );
395 dict->replace( word,
Unknown );
396 ++d->checksRequested;
397 if (currentParagraph() != para)
398 d->completeRehighlightRequired =
true;
400 d->spell->checkWord( word,
false );
407 return d->intraWordEditing;
412 d->intraWordEditing = editing;
418 Q_UNUSED( suggestions );
420 if ( d->globalConfig )
421 d->sDict()->replace( originalWord,
NotOkay );
423 d->mDict->replace( originalWord,
NotOkay );
435 Q3Dict<int>* dict = ( d->globalConfig ? d->sDict() : d->mDict );
436 if ( !dict->isEmpty() && (*dict)[word] ==
Unknown ) {
437 dict->replace( word,
Okay );
440 if (d->checksDone == d->checksRequested) {
441 d->spellTimeout->stop();
450 QObject *oldMonitor = K3DictSpellingHighlighterPrivate::sDictionaryMonitor;
451 K3DictSpellingHighlighterPrivate::sDictionaryMonitor =
new QObject();
452 K3DictSpellingHighlighterPrivate::sDict()->clear();
458 kDebug(0) <<
"KDictSpellingHighlighter::restartBackgroundSpellCheck()";
464 if ( active == d->active )
472 emit activeChanged(
i18n(
"As-you-type spell checking disabled.") );
482 if ( automatic == d->automatic )
485 d->automatic = automatic;
497 kDebug(0) <<
"KDictSpellingHighlighter::slotRehighlight()";
498 if (d->completeRehighlightRequired) {
502 textEdit()->getCursorPosition( ¶, &index );
504 textEdit()->insertAt(
"", para, index );
506 if (d->checksDone == d->checksRequested)
507 d->completeRehighlightRequired =
false;
514 d->spellReady =
false;
519 d->spell =
new K3Spell( 0,
i18n(
"Incremental Spellcheck" ),
this,
525 kDebug(0) <<
"KDictSpellingHighlighter::slotSpellConfigChanged()";
536 key += QString::number( cg.
readEntry(
"K3Spell_NoRootAffix", QVariant(0 )).toInt());
538 key += QString::number( cg.
readEntry(
"K3Spell_RunTogether", QVariant(0 )).toInt());
540 key += cg.
readEntry(
"K3Spell_Dictionary",
"" );
542 key += QString::number( cg.
readEntry(
"K3Spell_DictFromList", QVariant(
false )).toInt());
563 bool savedActive = d->active;
565 if ( d->automatic ) {
567 bool tme = ( d->wordCount >= d->disableWordCount ) && ( d->errorCount * 100 >= d->disablePercentage * d->wordCount );
568 if ( d->active && tme )
570 else if ( !d->active && !tme )
573 if ( d->active != savedActive ) {
574 if ( d->wordCount > 1 ) {
578 emit activeChanged(
i18n(
"Too many misspelled words. "
579 "As-you-type spell checking disabled." ) );
581 d->completeRehighlightRequired =
true;
582 d->rehighlightRequest->start( 100,
true );
588 static int retries = 0;
590 if ( d->globalConfig )
603 if (o == textEdit() && (e->type() == QEvent::FocusIn)) {
604 if ( d->globalConfig ) {
606 if ( d->spell && d->spellKey != skey ) {
613 if (o == textEdit() && (e->type() == QEvent::KeyPress)) {
614 QKeyEvent *k =
static_cast<QKeyEvent *
>(e);
616 if (d->rehighlightRequest->isActive())
617 d->rehighlightRequest->start( 500 );
618 if ( k->key() == Qt::Key_Enter ||
619 k->key() == Qt::Key_Return ||
620 k->key() == Qt::Key_Up ||
621 k->key() == Qt::Key_Down ||
622 k->key() == Qt::Key_Left ||
623 k->key() == Qt::Key_Right ||
624 k->key() == Qt::Key_PageUp ||
625 k->key() == Qt::Key_PageDown ||
626 k->key() == Qt::Key_Home ||
627 k->key() == Qt::Key_End ||
628 (( k->state() & Qt::ControlModifier ) &&
629 ((k->key() == Qt::Key_A) ||
630 (k->key() == Qt::Key_B) ||
631 (k->key() == Qt::Key_E) ||
632 (k->key() == Qt::Key_N) ||
633 (k->key() == Qt::Key_P))) ) {
636 d->completeRehighlightRequired =
true;
637 d->rehighlightRequest->start( 500,
true );
639 if (d->checksDone != d->checksRequested) {
642 d->completeRehighlightRequired =
true;
643 d->rehighlightRequest->start( 500,
true );
648 if ( k->key() == Qt::Key_Space ||
649 k->key() == Qt::Key_Enter ||
650 k->key() == Qt::Key_Return ) {
655 else if ( o == textEdit()->viewport() &&
656 ( e->type() == QEvent::MouseButtonPress )) {
660 d->completeRehighlightRequired =
true;
661 d->rehighlightRequest->start( 0,
true );
668#include "k3syntaxhighlighter.moc"
~K3DictSpellingHighlighter()
void restartBackgroundSpellCheck()
K3DictSpellingHighlighter(Q3TextEdit *textEdit, bool spellCheckingActive=true, bool autoEnable=true, const QColor &spellColor=Qt::red, bool colorQuoting=false, const QColor &QuoteColor0=Qt::black, const QColor &QuoteColor1=QColor(0x00, 0x80, 0x00), const QColor &QuoteColor2=QColor(0x00, 0x70, 0x00), const QColor &QuoteColor3=QColor(0x00, 0x60, 0x00), K3SpellConfig *spellConfig=0)
void slotCorrected(const QString &originalWord, const QString &, unsigned int)
void setActive(bool active)
Enable/Disable spell checking.
bool isActive() const
Returns the state of spell checking.
void slotK3SpellNotResponding()
bool eventFilter(QObject *o, QEvent *e)
void newSuggestions(const QString &originalword, const QStringList &suggestions, unsigned int pos)
void slotDictionaryChanged()
virtual bool isMisspelled(const QString &word)
void setAutomatic(bool automatic)
En-/Disable automatic (de)activation in case of too many errors.
void slotLocalSpellConfigChanged()
void slotMisspelling(const QString &originalWord, const QStringList &suggestions, unsigned int pos)
static void dictionaryChanged()
bool automatic() const
Returns the state of automatic (de)activation.
void slotSpellReady(K3Spell *spell)
void activeChanged(const QString &)
A configuration class/dialog for K3Spell.
bool intraWordEditing() const
void setIntraWordEditing(bool editing)
virtual int highlightParagraph(const QString &text, int endStateOfLastPara)
K3SpellingHighlighter(Q3TextEdit *textEdit, const QColor &spellColor=Qt::red, bool colorQuoting=false, const QColor &QuoteColor0=Qt::black, const QColor &QuoteColor1=QColor(0x00, 0x80, 0x00), const QColor &QuoteColor2=QColor(0x00, 0x80, 0x00), const QColor &QuoteColor3=QColor(0x00, 0x80, 0x00))
static QStringList personalWords()
virtual bool isMisspelled(const QString &word)=0
Syntax sensitive text highlighter.
int highlightParagraph(const QString &text, int endStateOfLastPara)
K3SyntaxHighlighter(Q3TextEdit *textEdit, bool colorQuoting=false, const QColor &QuoteColor0=Qt::black, const QColor &QuoteColor1=QColor(0x00, 0x80, 0x00), const QColor &QuoteColor2=QColor(0x00, 0x80, 0x00), const QColor &QuoteColor3=QColor(0x00, 0x80, 0x00), SyntaxMode mode=PlainTextMode)
QString readEntry(const char *key, const char *aDefault=0) const
static const int tenSeconds
QString i18n(const char *text)
KSharedConfigPtr config()