code clean
[mdictionary] / src / plugins / stardict / StarDictPlugin.cpp
index 88acba9..a6b3c9f 100644 (file)
     Copyright 2010 Comarch S.A.
 
 *******************************************************************************/
+/*!
+     \file StarDictPlugin.cpp
+     \brief Implementation of stardict plugin's main class.
 
-/*! \file xdxfplugin.cpp
-\author Jakub Jaszczynski <j.j.jaszczynski@gmail.com>
+     \author Jakub Jaszczynski
 */
 
 #include "StarDictPlugin.h"
-#include <QDebug>
-#include "../../include/Notify.h"
-#include <QTranslator>
-#include <QCoreApplication>
-#include <QThread>
+
+/**/
+uint qHash(const TranslationStarDict &key) {
+   return qHash(key.key());
+}
+
 
 StarDictPlugin::StarDictPlugin(QObject *parent) : CommonDictInterface(parent),
                     _langFrom(""), _langTo(""),_name(""), _infoNote("") {
@@ -38,22 +41,24 @@ StarDictPlugin::StarDictPlugin(QObject *parent) : CommonDictInterface(parent),
     connect(_dictDialog, SIGNAL(notify(Notify::NotifyType,QString)),
             this, SIGNAL(notify(Notify::NotifyType,QString)));
 
-
-    _settings->setValue("type","xdxf");
-    _icon = QIcon("/usr/share/mdictionary/xdxf.png");
-    _wordsCount = -1;
+    _settings->setValue("type","stardict");
+    _iconPath = "/usr/share/mdictionary/stardict.png";
+    _icon = QIcon(_iconPath);
     stopped = false;
 
+    _settings->setValue("strip_accents","true");
+
     initAccents();
+
 }
 
+
 void StarDictPlugin::retranslate() {
     QString locale = QLocale::system().name();
-
     QTranslator *translator = new QTranslator(this);
 
-    if(!translator->load(":/xdxf/translations/" + locale)) {
-        translator->load(":/xdxf/translations/en_US");
+    if(!translator->load(":/stardict/translations/" + locale)) {
+        translator->load(":/stardict/translations/en_US");
     }
     QCoreApplication::installTranslator(translator);
 }
@@ -86,141 +91,176 @@ QString StarDictPlugin::type() const {
 
 
 QString StarDictPlugin::infoNote() const {
-    return _infoNote;
+    return _name;
 }
 
 
 QList<Translation*> StarDictPlugin::searchWordList(QString word, int limit) {
+    QList<TranslationStarDict> translations;
+    bool is32b = false;
+    bool err = 0;
+    int wordcount = settings()->value("wordcount").toInt(&err);
+    int counter = 0;
+    int counterLimit = 0;
+    QString idxPath = settings()->value("idxFileName");
+    StarDictReader * reader = StarDictReaderFactory::createReader(idxPath);
+    QString fkey;
+    qint64 offset = 0,
+    len = 0;
+
     if( word.indexOf("*")==-1 && word.indexOf("?")==-1 &&
         word.indexOf("_")==-1 && word.indexOf("%")==-1)
         word+="*";
+    QRegExp keyword(word, Qt::CaseInsensitive, QRegExp::Wildcard);
 
-    if(isCached())
-        return searchWordListCache(word,limit);
-    return searchWordListFile(word, limit);
-}
+    if((settings()->value("idxoffsetbits") == "32") ||
+                         (settings()->value("idxoffsetbits") == ""))
+        is32b = true;
 
+    if(!err)
+        return QList<Translation*>();
 
-
-QList<Translation*> StarDictPlugin::searchWordListFile(QString word, int limit) {
-    QSet<Translation*> translations;
-    QFile dictionaryFile(_settings->value("path"));
-    word = word.toLower();
-    stopped = false;
-
-    QRegExp regWord(word);
-    regWord.setCaseSensitivity(Qt::CaseInsensitive);
-    regWord.setPatternSyntax(QRegExp::Wildcard);
-
-    /*check xdxf file exist*/
-    if(!QFile::exists(_settings->value("path"))
-                || !dictionaryFile.open(QFile::ReadOnly | QFile::Text)) {
-        qDebug()<<"Error: could not open file";
-        Q_EMIT notify(Notify::Warning,
-                QString(tr("XDXF file cannot be read for %1").arg(name())));
-        return translations.toList();
-    }
-
-    QXmlStreamReader reader(&dictionaryFile);
-    QString readKey;
-    int i=0;
-
-    /*search words list*/
-    while(!reader.atEnd() && !stopped){
-        reader.readNextStartElement();
-        if(reader.name()=="ar") {
-            while(reader.name()!="k" && !reader.atEnd())
-                reader.readNextStartElement();
-            if(!reader.atEnd())
-                readKey = reader.readElementText();
-            if((regWord.exactMatch(readKey)
-                    || regWord.exactMatch(removeAccents(readKey)))
-                    && (i<limit || limit==0) && !reader.atEnd())  {
- //               qDebug()<<readKey;
-                translations<<(new TranslationStarDict(readKey.toLower(),
-                               _dictionaryInfo,this));
-                if(translations.size()==limit && limit!=0)
-                    break;
-            }
+    stopped=false;
+    while(counter < wordcount && (counterLimit<limit || limit==0) && !stopped) {
+        counter++;
+        fkey = reader->readKeyword();
+        if(is32b)
+            offset = reader->readInt32BigEndian();
+        else
+            offset = reader->readInt64BigEndian();
+        len = reader->readInt32BigEndian();
+
+        if(keyword.exactMatch(fkey) ) {
+            TranslationStarDict tran(fkey, infoNote(), this);
+            int id = translations.indexOf(tran);
+            if(id == -1) {
+                tran.add(offset, len);
+                translations.push_front(tran);
+            } else
+                translations[id].add(offset, len);
+            counterLimit++;
         }
-        this->thread()->yieldCurrentThread();
     }
-    stopped=false;
-    dictionaryFile.close();
-    return translations.toList();
+    QList<Translation*> ret;
+    QListIterator<TranslationStarDict> it(translations);
+    while(it.hasNext())
+        ret.push_back(new TranslationStarDict(it.next()));
+    return ret;
 }
 
 
-QString StarDictPlugin::search(QString key) {
-    return searchFile(key);
+QByteArray StarDictPlugin::read(QByteArray::iterator it,
+        QByteArray::iterator end, int bytes) {
+    QByteArray ret;
+
+    if(bytes == 0 && it != end){
+        while(*it != '\0' && it != end)
+            ret.append(*it++);
+    }
+    else
+        for(int i = 0; i < bytes && it != end; i++)
+            ret.append(*it++);
+    return ret;
 }
 
 
+QString StarDictPlugin::interpret(QByteArray::iterator it,
+        QByteArray::iterator end, QChar mode,QString key, bool) {
+    QString result;
+    if(mode == 'm'
+            || mode == 'l'
+            || mode == 'g'
+            || mode == 't'
+            || mode == 'y'
+            || mode == 'k'
+            || mode == 'w'
+            || mode == 'h'
+            || mode == 'r'){
+        result += "<key>" + key + "</key>";
+        result += "<t>" + QString::fromUtf8(read(it++, end)) + "</t>";
+    }
 
-QString StarDictPlugin::searchFile(QString key) {
-    QFile dictionaryFile(_settings->value("path"));
-    QString resultString("");
-    key = key.toLower();
+    if(mode ==  'g'){
+        /* delete "small" tag  from g translation*/
+        int indexOfSmall=result.indexOf("<small>");
+        while(indexOfSmall!=-1){
+            int indexOfEndSmall= result.indexOf("</small>");
+            if(indexOfEndSmall!=-1)
+                result.remove(indexOfSmall,indexOfEndSmall-indexOfSmall+8);
+            indexOfSmall=result.indexOf("<small>");
+        }
+    }
+    if(mode == 'x'){
+        result += QString::fromUtf8(read(it++, end));
+        result.replace("</k>","</key><t>");
+        result.replace("<k>","</t><key>");
+        int pos=result.indexOf("</t>");
+        if(pos!=-1)
+            result.remove(pos,4);
+        if(result.contains("<t>"))
+            result+="</t>";
+    }
 
-    /*check xdxf file exist*/
-    if(!QFile::exists(_settings->value("path"))
-                || !dictionaryFile.open(QFile::ReadOnly | QFile::Text)) {
-        Q_EMIT notify(Notify::Warning,
-                QString(tr("XDXF file cannot be read for %1").arg(name())));
-        qDebug()<<"Error: could not open file";
-        return "";
+// W & P Dont know whether mDictionary would ever handle binary stardict format
+// to be honest dont see any kind of adventages (can't find any binary dict)
+ /*
     }
+    else if(mode == 'W') {
+        result += "<key>" + key + "</key>";
+        if(!last) {
+            QByteArray tmp ;
+            tmp.append(*(it++));
+            tmp.append(*(it++));
+            tmp.append(*(it++));
+            tmp.append(*(it));
+            result += read(it++, end, (qint32)qFromBigEndian(*(qint32*)tmp.data()));
+        } else
+            result += read(it++, end);
+    } else if(mode == 'P') {
+        result += "<key>" + key + "</key>";
+        if(!last) {
+            QByteArray tmp ;
+            tmp.append(*(it++));
+            tmp.append(*(it++));
+            tmp.append(*(it++));
+            tmp.append(*(it));
+            result += read(it++, end, (qint32)qFromBigEndian(*(qint32*)tmp.data()));
+        } else
+            result += read(it++, end);
+    } */
+    return result;
+}
 
-    QXmlStreamReader reader(&dictionaryFile);
-    QString readKey;
-    bool match =false;
-    stopped = false;
 
-    /*search translations for word*/
-    while (!reader.atEnd()&& !stopped) {
-        reader.readNext();
-        if(reader.tokenType() == QXmlStreamReader::StartElement) {
-            if(reader.name()=="k") {
-                readKey = reader.readElementText();
-                if(readKey.toLower()==key.toLower())
-                    match = true;
-            }
+QString StarDictPlugin::format(QByteArray raw, QString mode,QString key) {
+    QString result;
+    if(mode == "") {
+        for(QByteArray::iterator it = raw.begin(); it != raw.end(); it++) {
+            char tmp = *(++it);
+            result += interpret(--it, raw.end(), tmp, key);
         }
-        if(match) {
-            QString temp("");
-            while(reader.name()!="ar" && !reader.atEnd()) {
-                if(reader.name()!="" && reader.name()!="k") {
-                    if(reader.tokenType()==QXmlStreamReader::EndElement)
-                        temp+="</";
-                    if(reader.tokenType()==QXmlStreamReader::StartElement)
-                        temp+="<";
-                    temp+=reader.name().toString();
-                    if(reader.name().toString()=="c" &&
-                            reader.tokenType()==QXmlStreamReader::StartElement)
-                       temp= temp + " c=\"" + reader.attributes().
-                               value("c").toString() + "\"";
-                    temp+=">";
-                }
-                temp+= reader.text().toString().replace("<","&lt;").
-                        replace(">","&gt;");
-                reader.readNext();
-            }
-            if(temp.at(0)==QChar('\n'))
-                temp.remove(0,1);
-            resultString+="<key>" + readKey +"</key>";
-            resultString+="<t>" + temp + "</t>";
-            match=false;
+    } else {
+        QByteArray::iterator it = raw.begin();
+        foreach(QChar tmp, mode) {
+            result += interpret(it, raw.end(), tmp, key);
         }
-        this->thread()->yieldCurrentThread();
     }
-    stopped=false;
-    dictionaryFile.close();
-    return resultString;
+    return result;
+}
+
+
+QString StarDictPlugin::search(QString key, qint64 offset, qint32 len) {
+    QString dictPath = settings()->value("dictFileName");
+    StarDictReader *reader = StarDictReaderFactory::createReader(dictPath);
+    QByteArray raw = reader->readString(offset, len);
+    QString result= format(raw, settings()->value("sametypesequence"),key);
+
+    delete reader;
+    return result;
 }
 
 
 void StarDictPlugin::stop() {
-   //qDebug()<<"stop";
     stopped=true;
 }
 
@@ -236,19 +276,18 @@ CommonDictInterface* StarDictPlugin::getNew(const Settings *settings) const {
     connect(plugin, SIGNAL(notify(Notify::NotifyType,QString)),
             this, SIGNAL(notify(Notify::NotifyType,QString)));
 
-    ((StarDictDialog*)plugin->dictDialog())->setLastDialogParent(_dictDialog->lastDialogParent());
-
-
+    ((StarDictDialog*)plugin->dictDialog())->
+            setLastDialogParent(_dictDialog->lastDialogParent());
 
     if(settings && plugin->setSettings(settings)) {
-
-        disconnect(plugin, SIGNAL(notify(Notify::NotifyType,QString)),
-                this, SIGNAL(notify(Notify::NotifyType,QString)));
+        disconnect( plugin, SIGNAL(notify(Notify::NotifyType,QString)),
+                    this, SIGNAL(notify(Notify::NotifyType,QString)));
+        plugin->getDictionaryInfo();
         return plugin;
     }
     else {
-        disconnect(plugin, SIGNAL(notify(Notify::NotifyType,QString)),
-                this, SIGNAL(notify(Notify::NotifyType,QString)));
+        disconnect( plugin, SIGNAL(notify(Notify::NotifyType,QString)),
+                    this, SIGNAL(notify(Notify::NotifyType,QString)));
         delete plugin;
         return 0;
     }
@@ -265,59 +304,12 @@ Settings* StarDictPlugin::settings() {
 }
 
 
-bool StarDictPlugin::isCached() {
-    if(_settings->value("cached") == "true")
-        return true;
-    return false;
-}
-
-
-bool StarDictPlugin::setSettings(const Settings *settings) {
-    if(settings) {
-        bool isPathChange=false;
-        QString oldPath = _settings->value("path");
-        Settings *oldSettings =  new Settings ;
-
-        if(oldPath != settings->value("path")) {
-            if(oldPath!="" && _settings->value("cache_path")!="")
-                clean();
-            isPathChange=true;
-        }
-
-        foreach(QString key, _settings->keys())
-            oldSettings->setValue(key, _settings->value(key));
-
-        foreach(QString key, settings->keys()) {
-           if(key != "generateCache")
-               _settings->setValue(key, settings->value(key));
-        }
+bool StarDictPlugin::setSettings(const Settings *sett) {
+    if(sett) {
+        foreach(QString key, sett->keys())
+            _settings->setValue(key, sett->value(key));
 
-        if(!getDictionaryInfo()) {
-            Q_EMIT notify(Notify::Warning,
-                QString(tr("XDXF file is in wrong format")));
-            qDebug()<<"Error: xdxf file is in wrong format";
-            delete _settings;
-            _settings=oldSettings;
-            return false;
-        }
-
-        if(isPathChange) {
-            _wordsCount=0;
-            if(oldPath!="")
-                _settings->setValue("cached","false");
-        }
-
-        if((_settings->value("cached") == "false" ||
-            _settings->value("cached").isEmpty()) &&
-            settings->value("generateCache") == "true") {
-            clean();
-        }
-
-        else if (settings->value("generateCache") == "false") {
-            _settings->setValue("cached", "false");
-        }
-    }
-    else
+    } else
         return false;
     Q_EMIT settingsChanged();
     return true;
@@ -325,43 +317,24 @@ bool StarDictPlugin::setSettings(const Settings *settings) {
 
 
 bool StarDictPlugin::getDictionaryInfo() {
-    QFile dictionaryFile(_settings->value("path"));
-    if(!QFile::exists(_settings->value("path"))
-                || !dictionaryFile.open(QFile::ReadOnly | QFile::Text)) {
-       Q_EMIT notify(Notify::Warning,
-               QString(tr("XDXF dictionary cannot be read from file")));
-        qDebug()<<"Error: could not open file";
+    QFile file(settings()->value("ifoFileName"));
+    if(!QFile::exists(_settings->value("ifoFileName"))
+                || !file.open(QFile::ReadOnly | QFile::Text)) {
+        Q_EMIT notify(Notify::Warning,
+               QString(tr("StarDict dictionary cannot be read from file")));
+        qDebug()<<"Error: could not open the file";
         return false;
     }
-
-    bool okFormat=false;
-    QXmlStreamReader reader(&dictionaryFile);
-    reader.readNextStartElement();
-    if(reader.name()=="xdxf") {
-        okFormat=true;
-        if(reader.attributes().hasAttribute("lang_from"))
-            _langFrom = reader.attributes().value("lang_from").toString();
-        if(reader.attributes().hasAttribute("lang_to"))
-            _langTo = reader.attributes().value("lang_to").toString();
+    QTextStream in(&file);
+    while (!in.atEnd()) {
+        QString line = in.readLine();
+        QStringList list = line.split("=");
+        if(list.size() == 2) {
+            settings()->setValue(list.at(0),list.at(1));
+        }
     }
-    reader.readNextStartElement();
-    if(reader.name()=="full_name")
-        _name=reader.readElementText();
-    else
-        qDebug()<<"no full_name";
-    reader.readNextStartElement();
-    if(reader.name()=="description")
-        _infoNote=reader.readElementText();
-    else
-        qDebug()<<"no description";
-
-    _dictionaryInfo= _name + " [" + _langFrom + "-"
-                + _langTo + "]";
-
-    dictionaryFile.close();
-    if(okFormat)
-        return true;
-    return false;
+    _name = settings()->value("bookname");
+    return true;
 }
 
 
@@ -369,41 +342,8 @@ QIcon* StarDictPlugin::icon() {
     return &_icon;
 }
 
-
-int StarDictPlugin::countWords() {
-    if(_wordsCount>0)
-        return _wordsCount;
-    QFile dictionaryFile(_settings->value("path"));
-    if(!QFile::exists(_settings->value("path"))
-                || !dictionaryFile.open(QFile::ReadOnly | QFile::Text)) {
-        Q_EMIT notify(Notify::Warning,
-                QString(tr("XDXF file cannot be read for %1 dictionary")
-                .arg(name())));
-        qDebug()<<"Error: could not open file";
-        return -1;
-    }
-
-    dictionaryFile.seek(0);
-
-    long wordsCount = 0;
-
-    QString line;
-    while(!dictionaryFile.atEnd()) {
-        line = dictionaryFile.readLine();
-        if(line.contains("<k>")) {
-            wordsCount++;
-        }
-    }
-    _wordsCount = wordsCount;
-    dictionaryFile.close();
-    return wordsCount;
+QString StarDictPlugin::iconPath(){
+    return _iconPath;
 }
 
-
-
-void StarDictPlugin::clean() {
-
-}
-
-
 Q_EXPORT_PLUGIN2(stardict, StarDictPlugin)