[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    branches/work/sonnet-multilang/kdeui
From:       Jakub Stachowski <qbast () go2 ! pl>
Date:       2009-04-07 20:37:00
Message-ID: 1239136620.420590.7760.nullmailer () svn ! kde ! org
[Download RAW message or body]

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 <QEvent>
 #include <QKeyEvent>
 #include <QApplication>
+#include <QMutableMapIterator>
 
 namespace Sonnet {
 
+class LanguageCache : public QTextBlockUserData {
+public:
+    QMap<QPair<int,int>, QString> languages;
+    void invalidate(int pos) {
+        kDebug() << "Invalidate at " << pos << " there was " << languages;
+        QMutableMapIterator<QPair<int,int>, 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 << " -"<<rem;
+    if ((add-rem) == 0 ) return;
+    //FIXME: go over all blocks
+    QTextBlock block=document()->findBlock(pos);
+    LanguageCache* cache=dynamic_cast<LanguageCache*>(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<LanguageCache*>(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<int,int> spos=QPair<int,int>(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);
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic