Clean and order documentation in source files. Source ready to beta 2 release
[mdictionary] / src / plugins / stardict / StarDictPlugin.cpp
1 /*******************************************************************************
2
3     This file is part of mDictionary.
4
5     mDictionary is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9
10     mDictionary is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with mDictionary.  If not, see <http://www.gnu.org/licenses/>.
17
18     Copyright 2010 Comarch S.A.
19
20 *******************************************************************************/
21 /*!
22      \file StarDictPlugin.cpp
23      \brief Implementation of stardict plugin's main class.
24
25      \author Jakub Jaszczynski
26 */
27
28 #include "StarDictPlugin.h"
29
30 /**/
31 uint qHash(const TranslationStarDict &key) {
32    return qHash(key.key());
33 }
34
35
36 StarDictPlugin::StarDictPlugin(QObject *parent) : CommonDictInterface(parent),
37                     _langFrom(""), _langTo(""),_name(""), _infoNote("") {
38     _settings = new Settings();
39     _dictDialog = new StarDictDialog(this, this);
40
41     connect(_dictDialog, SIGNAL(notify(Notify::NotifyType,QString)),
42             this, SIGNAL(notify(Notify::NotifyType,QString)));
43
44     _settings->setValue("type","stardict");
45     _icon = QIcon("/usr/share/mdictionary/stardict.png");
46     stopped = false;
47
48     _settings->setValue("strip_accents","true");
49
50     initAccents();
51
52 }
53
54
55 void StarDictPlugin::retranslate() {
56     QString locale = QLocale::system().name();
57     QTranslator *translator = new QTranslator(this);
58
59     if(!translator->load(":/stardict/translations/" + locale)) {
60         translator->load(":/stardict/translations/en_US");
61     }
62     QCoreApplication::installTranslator(translator);
63 }
64
65
66 StarDictPlugin::~StarDictPlugin() {
67     delete _settings;
68     delete _dictDialog;
69 }
70
71
72 QString StarDictPlugin::langFrom() const {
73     return _langFrom;
74 }
75
76
77 QString StarDictPlugin::langTo() const {
78     return  _langTo;
79 }
80
81
82 QString StarDictPlugin::name() const {
83     return  _name;
84 }
85
86
87 QString StarDictPlugin::type() const {
88     return QString("stardict");
89 }
90
91
92 QString StarDictPlugin::infoNote() const {
93     return _name;
94 }
95
96
97 QList<Translation*> StarDictPlugin::searchWordList(QString word, int limit) {
98     QList<TranslationStarDict> translations;
99     bool is32b = false;
100     bool err = 0;
101     int wordcount = settings()->value("wordcount").toInt(&err);
102     int counter = 0;
103     int counterLimit = 0;
104     QString idxPath = settings()->value("idxFileName");
105     StarDictReader * reader = StarDictReaderFactory::createReader(idxPath);
106     QString fkey;
107     qint64 offset = 0,
108     len = 0;
109
110     if( word.indexOf("*")==-1 && word.indexOf("?")==-1 &&
111         word.indexOf("_")==-1 && word.indexOf("%")==-1)
112         word+="*";
113     QRegExp keyword(word, Qt::CaseInsensitive, QRegExp::Wildcard);
114
115     if((settings()->value("idxoffsetbits") == "32") ||
116                          (settings()->value("idxoffsetbits") == ""))
117         is32b = true;
118
119     if(!err)
120         return QList<Translation*>();
121
122     stopped=false;
123     while(counter < wordcount && (counterLimit<limit || limit==0) && !stopped) {
124         counter++;
125         fkey = reader->readKeyword();
126         if(is32b)
127             offset = reader->readInt32BigEndian();
128         else
129             offset = reader->readInt64BigEndian();
130         len = reader->readInt32BigEndian();
131
132         if(keyword.exactMatch(fkey) ) {
133             TranslationStarDict tran(fkey, infoNote(), this);
134   //        qDebug() << "off/len" << offset << len;
135             int id = translations.indexOf(tran);
136             if(id == -1) {
137                 tran.add(offset, len);
138                 translations.push_front(tran);
139             } else
140                 translations[id].add(offset, len);
141             counterLimit++;
142         }
143     }
144     QList<Translation*> ret;
145     QListIterator<TranslationStarDict> it(translations);
146     while(it.hasNext())
147         ret.push_back(new TranslationStarDict(it.next()));
148     return ret;
149 }
150
151
152 QByteArray StarDictPlugin::read(QByteArray::iterator it,
153         QByteArray::iterator end, int bytes) {
154     QByteArray ret;
155
156     if(bytes == 0 && it != end){
157         while(*it != '\0' && it != end)
158             ret.append(*it++);
159     }
160     else
161         for(int i = 0; i < bytes && it != end; i++)
162             ret.append(*it++);
163     return ret;
164 }
165
166
167 QString StarDictPlugin::interpret(QByteArray::iterator it,
168         QByteArray::iterator end, QChar mode,QString key, bool) {
169     QString result;
170 //    qDebug()<<"****** mode:     "<<mode;
171     if(mode == 'm'
172             || mode == 'l'
173             || mode == 'g'
174             || mode == 't'
175             || mode == 'y'
176             || mode == 'k'
177             || mode == 'w'
178             || mode == 'h'
179             || mode == 'r'){
180         result += "<key>" + key + "</key>";
181         result += "<t>" + QString::fromUtf8(read(it++, end)) + "</t>";
182     }
183
184     if(mode ==  'g'){
185         /* delete "small" tag  from g translation*/
186         int indexOfSmall=result.indexOf("<small>");
187         while(indexOfSmall!=-1){
188             int indexOfEndSmall= result.indexOf("</small>");
189             if(indexOfEndSmall!=-1)
190                 result.remove(indexOfSmall,indexOfEndSmall-indexOfSmall+8);
191             indexOfSmall=result.indexOf("<small>");
192         }
193     }
194     if(mode == 'x'){
195         result += QString::fromUtf8(read(it++, end));
196         result.replace("</k>","</key><t>");
197         result.replace("<k>","</t><key>");
198         int pos=result.indexOf("</t>");
199         if(pos!=-1)
200             result.remove(pos,4);
201         if(result.contains("<t>"))
202             result+="</t>";
203     }
204
205 // W & P Dont know whether mDictionary would ever handle binary stardict format
206 // to be honest dont see any kind of adventages (can't find any binary dict)
207  /*
208     }
209     else if(mode == 'W') {
210         result += "<key>" + key + "</key>";
211         if(!last) {
212             QByteArray tmp ;
213             tmp.append(*(it++));
214             tmp.append(*(it++));
215             tmp.append(*(it++));
216             tmp.append(*(it));
217             result += read(it++, end, (qint32)qFromBigEndian(*(qint32*)tmp.data()));
218         } else
219             result += read(it++, end);
220     } else if(mode == 'P') {
221         result += "<key>" + key + "</key>";
222         if(!last) {
223             QByteArray tmp ;
224             tmp.append(*(it++));
225             tmp.append(*(it++));
226             tmp.append(*(it++));
227             tmp.append(*(it));
228             result += read(it++, end, (qint32)qFromBigEndian(*(qint32*)tmp.data()));
229         } else
230             result += read(it++, end);
231     } */
232     return result;
233 }
234
235
236 QString StarDictPlugin::format(QByteArray raw, QString mode,QString key) {
237     QString result;
238     if(mode == "") {
239         for(QByteArray::iterator it = raw.begin(); it != raw.end(); it++) {
240             char tmp = *(++it);
241             result += interpret(--it, raw.end(), tmp, key);
242         }
243     } else {
244         QByteArray::iterator it = raw.begin();
245         foreach(QChar tmp, mode) {
246             result += interpret(it, raw.end(), tmp, key);
247         }
248     }
249     return result;
250 }
251
252
253 QString StarDictPlugin::search(QString key, qint64 offset, qint32 len) {
254     QString dictPath = settings()->value("dictFileName");
255     StarDictReader *reader = StarDictReaderFactory::createReader(dictPath);
256     QByteArray raw = reader->readString(offset, len);
257     QString result= format(raw, settings()->value("sametypesequence"),key);
258
259     delete reader;
260     return result;
261 }
262
263
264 void StarDictPlugin::stop() {
265     stopped=true;
266 }
267
268
269 DictDialog* StarDictPlugin::dictDialog() {
270      return _dictDialog;
271 }
272
273
274 CommonDictInterface* StarDictPlugin::getNew(const Settings *settings) const {
275     StarDictPlugin *plugin = new StarDictPlugin();
276
277     connect(plugin, SIGNAL(notify(Notify::NotifyType,QString)),
278             this, SIGNAL(notify(Notify::NotifyType,QString)));
279
280     ((StarDictDialog*)plugin->dictDialog())->
281             setLastDialogParent(_dictDialog->lastDialogParent());
282
283     if(settings && plugin->setSettings(settings)) {
284         disconnect( plugin, SIGNAL(notify(Notify::NotifyType,QString)),
285                     this, SIGNAL(notify(Notify::NotifyType,QString)));
286         plugin->getDictionaryInfo();
287         return plugin;
288     }
289     else {
290         disconnect( plugin, SIGNAL(notify(Notify::NotifyType,QString)),
291                     this, SIGNAL(notify(Notify::NotifyType,QString)));
292         delete plugin;
293         return 0;
294     }
295 }
296
297
298 bool StarDictPlugin::isAvailable() const {
299     return true;
300 }
301
302
303 Settings* StarDictPlugin::settings() {
304     return _settings;
305 }
306
307
308 bool StarDictPlugin::setSettings(const Settings *sett) {
309     if(sett) {
310         foreach(QString key, sett->keys())
311             _settings->setValue(key, sett->value(key));
312
313     } else
314         return false;
315     Q_EMIT settingsChanged();
316     return true;
317 }
318
319
320 bool StarDictPlugin::getDictionaryInfo() {
321     QFile file(settings()->value("ifoFileName"));
322     if(!QFile::exists(_settings->value("ifoFileName"))
323                 || !file.open(QFile::ReadOnly | QFile::Text)) {
324         Q_EMIT notify(Notify::Warning,
325                QString(tr("StarDict dictionary cannot be read from file")));
326         qDebug()<<"Error: could not open the file";
327         return false;
328     }
329     QTextStream in(&file);
330     while (!in.atEnd()) {
331         QString line = in.readLine();
332         QStringList list = line.split("=");
333         if(list.size() == 2) {
334             settings()->setValue(list.at(0),list.at(1));
335         }
336     }
337     _name = settings()->value("bookname");
338     return true;
339 }
340
341
342 QIcon* StarDictPlugin::icon() {
343     return &_icon;
344 }
345
346 Q_EXPORT_PLUGIN2(stardict, StarDictPlugin)