From kde-commits Tue Apr 07 20:37:00 2009 From: Jakub Stachowski Date: Tue, 07 Apr 2009 20:37:00 +0000 To: kde-commits Subject: branches/work/sonnet-multilang/kdeui Message-Id: <1239136620.420590.7760.nullmailer () svn ! kde ! org> X-MARC-Message: https://marc.info/?l=kde-commits&m=123913662732766 SVN commit 950814 by qbast: Cache languagefilter instance and Sentence->language map M +67 -5 highlighter.cpp M +1 -0 highlighter.h --- branches/work/sonnet-multilang/kdeui/highlighter.cpp #950813:950814 @@ -43,14 +43,32 @@ #include #include #include +#include namespace Sonnet { +class LanguageCache : public QTextBlockUserData { +public: + QMap, QString> languages; + void invalidate(int pos) { + kDebug() << "Invalidate at " << pos << " there was " << languages; + QMutableMapIterator, QString> it(languages); + it.toBack(); + while (it.hasPrevious()) { + it.previous(); + if (it.key().first+it.key().second >=pos) it.remove(); + else break; + } + kDebug() << languages << " left"; + } +}; + class Highlighter::Private { public: ~Private(); WordTokenizer* words; + LanguageFilter* langs; Loader *loader; Speller *dict; QTextEdit *edit; @@ -59,6 +77,7 @@ bool completeRehighlightRequired; bool intraWordEditing; bool spellCheckerFound; + bool connected; int disablePercentage; int disableWordCount; int wordCount, errorCount; @@ -70,6 +89,8 @@ Highlighter::Private::~Private() { delete dict; + delete langs; + delete words; } Highlighter::Highlighter(QTextEdit *textEdit, @@ -84,11 +105,13 @@ d->automatic = true; d->wordCount = 0; d->errorCount = 0; + d->connected=false; d->intraWordEditing = false; d->completeRehighlightRequired = false; d->spellCheckerFound = true; d->spellColor = _col.isValid() ? _col : Qt::red; d->suggestionListeners = 0; + d->langs=new LanguageFilter(new SentenceTokenizer()); textEdit->installEventFilter( this ); textEdit->viewport()->installEventFilter( this ); @@ -259,10 +282,28 @@ return d->active; } +void Highlighter::contentsChange(int pos, int add, int rem) +{ + kDebug() << "Change " << pos << " +" << add << " -"<findBlock(pos); + LanguageCache* cache=dynamic_cast(block.userData()); + //FIXME: invalidate only affected part + if (cache) cache->invalidate(pos-block.position()); +} + void Highlighter::highlightBlock(const QString &text) { if (text.isEmpty() || !d->active || !d->spellCheckerFound) return; + + //FIXME: deal with editor->setDocument() + if (!d->connected) { + connect(document(),SIGNAL(contentsChange(int,int,int)),this,SLOT(contentsChange(int,int,int))); + d->connected=true; + } + QTextCursor cursor = d->edit->textCursor(); int index = cursor.position(); @@ -270,14 +311,35 @@ if ( index != lengthPosition || ( lengthPosition > 0 && !text[lengthPosition-1].isLetter() ) ) { - LanguageFilter langs(new SentenceTokenizer(text)); + d->langs->setBuffer(text); + + LanguageCache* cache=dynamic_cast(currentBlockUserData()); + if (!cache) { + cache = new LanguageCache; + setCurrentBlockUserData(cache); + } - while (langs.hasNext()) { - QStringRef sentence=langs.next(); + while (d->langs->hasNext()) { + QStringRef sentence=d->langs->next(); if (d->dict->testAttribute(Speller::AutodetectLanguage)) { - if (!langs.isSpellcheckable()) continue; - d->dict->setLanguage(langs.language()); + + QString lang; + QPair spos=QPair(sentence.position(),sentence.length()); + // try cache first + if (cache->languages.contains(spos)) { + lang=cache->languages.value(spos); + kDebug() << "Got from cache " << spos << " : " << lang; + } else { + lang=d->langs->language(); + if (!d->langs->isSpellcheckable()) lang.clear(); + cache->languages[spos]=lang; + kDebug() << "Not in cache " << spos << " : " << lang; + } + if (lang.isEmpty()) continue; + d->dict->setLanguage(lang); } + + d->words->setBuffer( sentence.toString() ); int offset=sentence.position(); while ( d->words->hasNext() ) { --- branches/work/sonnet-multilang/kdeui/highlighter.h #950813:950814 @@ -161,6 +161,7 @@ public Q_SLOTS: void slotAutoDetection(); void slotRehighlight(); + void contentsChange(int pos, int added, int removed); private: virtual void connectNotify(const char* signal); virtual void disconnectNotify(const char* signal);