fix some bugs
[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 */
24
25 #include "StarDictPlugin.h"
26
27
28 uint qHash(const TranslationStarDict &key) {
29    return qHash(key.key());
30 }
31
32
33 StarDictPlugin::StarDictPlugin(QObject *parent) : CommonDictInterface(parent),
34                     _langFrom(""), _langTo(""),_name(""), _infoNote("") {
35     _settings = new Settings();
36     _dictDialog = new StarDictDialog(this, this);
37
38     connect(_dictDialog, SIGNAL(notify(Notify::NotifyType,QString)),
39             this, SIGNAL(notify(Notify::NotifyType,QString)));
40
41     _settings->setValue("type","stardict");
42     _icon = QIcon("/usr/share/mdictionary/stardict.png");
43     _wordsCount = -1;
44     stopped = false;
45
46     initAccents();
47 }
48
49
50 void StarDictPlugin::retranslate() {
51     QString locale = QLocale::system().name();
52     QTranslator *translator = new QTranslator(this);
53
54     if(!translator->load(":/stardict/translations/" + locale)) {
55         translator->load(":/stardicts/translations/en_US");
56     }
57     QCoreApplication::installTranslator(translator);
58 }
59
60
61 StarDictPlugin::~StarDictPlugin() {
62     delete _settings;
63     delete _dictDialog;
64 }
65
66
67 QString StarDictPlugin::langFrom() const {
68     return _langFrom;
69 }
70
71
72 QString StarDictPlugin::langTo() const {
73     return  _langTo;
74 }
75
76
77 QString StarDictPlugin::name() const {
78     return  _name;
79 }
80
81
82 QString StarDictPlugin::type() const {
83     return QString("stardict");
84 }
85
86
87 QString StarDictPlugin::infoNote() const {
88     return _name;
89 }
90
91
92 QList<Translation*> StarDictPlugin::searchWordList(QString word, int limit) {
93     QList<TranslationStarDict> translations;
94     bool is32b = false;
95     bool err = 0;
96     int wordcount = settings()->value("wordcount").toInt(&err);
97     int counter = 0;
98     int counterLimit = 0;
99     QString idxPath = settings()->value("idxFileName");
100     StarDictReader * reader = StarDictReaderFactory::createReader(idxPath);
101     QString fkey;
102     qint64 offset = 0, len = 0;
103     QRegExp keyword(word, Qt::CaseInsensitive, QRegExp::Wildcard);
104
105     if( word.indexOf("*")==-1 && word.indexOf("?")==-1 &&
106         word.indexOf("_")==-1 && word.indexOf("%")==-1)
107         word+="*";
108
109
110     if((settings()->value("idxoffsetbits") == "32") ||
111                          (settings()->value("idxoffsetbits") == ""))
112         is32b = true;
113     if(!err)
114         return QList<Translation*>();
115
116     stopped=false;
117     while(counter < wordcount && (counterLimit<limit || limit==0) && !stopped) {
118         counter++;
119         fkey = reader->readKeyword();
120         if(is32b)
121             offset = reader->readInt32BigEndian();
122         else
123             offset = reader->readInt64BigEndian();
124         len = reader->readInt32BigEndian();
125
126         if(keyword.exactMatch(fkey)) {
127             TranslationStarDict tran(fkey, infoNote(), this);
128             qDebug() << "off/len" << offset << len;
129             int id = translations.indexOf(tran);
130             if(id == -1) {
131                 tran.add(offset, len);
132                 translations.push_front(tran);
133             } else
134                 translations[id].add(offset, len);
135             counterLimit++;
136         }
137     }
138     QList<Translation*> ret;
139     QListIterator<TranslationStarDict> it(translations);
140     while(it.hasNext())
141         ret.push_back(new TranslationStarDict(it.next()));
142     return ret;
143 }
144
145
146 QByteArray StarDictPlugin::read(QByteArray::iterator it,
147         QByteArray::iterator end, int bytes) {
148     QByteArray ret;
149
150     if(bytes == 0 && it != end){
151         while(*it != '\0' && it != end)
152             ret.append(*it++);
153         if(it == end)
154             qDebug()<<"end";
155         else
156             qDebug()<<"000";
157     }
158     else
159         for(int i = 0; i < bytes && it != end; i++)
160             ret.append(*it++);
161     return ret;
162 }
163
164
165 QString StarDictPlugin::interpret(QByteArray::iterator it,
166         QByteArray::iterator end, QChar mode,QString key, bool last) {
167     QString result;
168     qDebug()<<"****** mode:     "<<mode;
169     if(mode == 'm'){
170         result += "<key>" + key + "</key>";
171         result += QString::fromUtf8(read(it++, end));
172     }
173     else if(mode == 'l'){
174         result += "<key>" + key + "</key>";
175         result += QString::fromUtf8(read(it++, end));
176     }
177     else if(mode ==  'g'){
178         result += "<key>" + key + "</key>";
179         result += QString::fromUtf8(read(it++, end));
180
181         /* delete "small" tag  from translation*/
182         int indexOfSmall=result.indexOf("<small>");
183         while(indexOfSmall!=-1){
184             int indexOfEndSmall= result.indexOf("</small>");
185             if(indexOfEndSmall!=-1)
186                 result.remove(indexOfSmall,indexOfEndSmall-indexOfSmall+8);
187             indexOfSmall=result.indexOf("<small>");
188         }
189     }
190     else if(mode == 't'){
191         result += "<key>" + key + "</key>";
192         result += QString::fromUtf8(read(it++, end));
193     }
194     else 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     else if(mode == 'y') {
205         result += "<key>" + key + "</key>";
206         result += QString::fromUtf8(read(it++, end));
207     }
208     else if(mode == 'k'){
209         result += "<key>" + key + "</key>";
210         result += QString::fromUtf8(read(it++, end));
211     }
212     else if(mode == 'w'){
213         result += "<key>" + key + "</key>";
214         result += QString::fromUtf8(read(it++, end));
215     }
216     else if(mode == 'h'){
217         result += "<key>" + key + "</key>";
218         result += QString::fromUtf8(read(it++, end));
219     }
220     else if(mode == 'r'){
221         result += "<key>" + key + "</key>";
222         result += QString::fromUtf8(read(it++, end));
223     }
224
225
226 // Dont know whether mDictionary would ever handle binary stardict format
227 // to be honest dont see any kind of adventages (can't find any binary dict)
228  /*
229     }
230     else if(mode == 'W') {
231         result += "<key>" + key + "</key>";
232         if(!last) {
233             QByteArray tmp ;
234             tmp.append(*(it++));
235             tmp.append(*(it++));
236             tmp.append(*(it++));
237             tmp.append(*(it));
238             result += read(it++, end, (qint32)qFromBigEndian(*(qint32*)tmp.data()));
239         } else
240             result += read(it++, end);
241     } else if(mode == 'P') {
242         result += "<key>" + key + "</key>";
243         if(!last) {
244             QByteArray tmp ;
245             tmp.append(*(it++));
246             tmp.append(*(it++));
247             tmp.append(*(it++));
248             tmp.append(*(it));
249             result += read(it++, end, (qint32)qFromBigEndian(*(qint32*)tmp.data()));
250         } else
251             result += read(it++, end);
252     } */
253
254     qDebug()<<"wynik  "<<result;
255     return result;
256 }
257
258
259 QString StarDictPlugin::format(QByteArray raw, QString mode,QString key) {
260     QString result;
261     if(mode == "") {
262         for(QByteArray::iterator it = raw.begin(); it != raw.end(); it++) {
263             char tmp = *(++it);
264             result += interpret(--it, raw.end(), tmp, key);
265         }
266     } else {
267         QByteArray::iterator it = raw.begin();
268         foreach(QChar tmp, mode) {
269             result += interpret(it, raw.end(), tmp, key);
270         }
271     }
272     return result;
273 }
274
275
276
277 QString StarDictPlugin::search(QString key, qint64 offset, qint32 len) {
278     QString dictPath = settings()->value("dictFileName");
279     StarDictReader *reader = StarDictReaderFactory::createReader(dictPath);
280     QByteArray raw = reader->readString(offset, len);
281     QString result= format(raw, settings()->value("sametypesequence"),key);
282
283     delete reader;
284     return result;
285 }
286
287
288 void StarDictPlugin::stop() {
289     stopped=true;
290 }
291
292
293 DictDialog* StarDictPlugin::dictDialog() {
294      return _dictDialog;
295 }
296
297
298 CommonDictInterface* StarDictPlugin::getNew(const Settings *settings) const {
299     StarDictPlugin *plugin = new StarDictPlugin();
300
301     connect(plugin, SIGNAL(notify(Notify::NotifyType,QString)),
302             this, SIGNAL(notify(Notify::NotifyType,QString)));
303
304     ((StarDictDialog*)plugin->dictDialog())->
305             setLastDialogParent(_dictDialog->lastDialogParent());
306
307     if(settings && plugin->setSettings(settings)) {
308         disconnect( plugin, SIGNAL(notify(Notify::NotifyType,QString)),
309                     this, SIGNAL(notify(Notify::NotifyType,QString)));
310         plugin->getDictionaryInfo();
311         return plugin;
312     }
313     else {
314         disconnect( plugin, SIGNAL(notify(Notify::NotifyType,QString)),
315                     this, SIGNAL(notify(Notify::NotifyType,QString)));
316         delete plugin;
317         return 0;
318     }
319 }
320
321
322 bool StarDictPlugin::isAvailable() const {
323     return true;
324 }
325
326
327 Settings* StarDictPlugin::settings() {
328     return _settings;
329 }
330
331
332 bool StarDictPlugin::isCached() {
333     return false;
334 }
335
336
337 bool StarDictPlugin::setSettings(const Settings *sett) {
338     if(sett) {
339         foreach(QString key, sett->keys())
340             _settings->setValue(key, sett->value(key));
341
342     } else
343         return false;
344     Q_EMIT settingsChanged();
345     return true;
346 }
347
348
349 bool StarDictPlugin::getDictionaryInfo() {
350     QFile file(settings()->value("ifoFileName"));
351     if(!QFile::exists(_settings->value("ifoFileName"))
352                 || !file.open(QFile::ReadOnly | QFile::Text)) {
353         Q_EMIT notify(Notify::Warning,
354                QString(tr("StarDict dictionary cannot be read from file")));
355         qDebug()<<"Error: could not open the file";
356         return false;
357     }
358     QTextStream in(&file);
359     while (!in.atEnd()) {
360         QString line = in.readLine();
361         QStringList list = line.split("=");
362         if(list.size() == 2) {
363             settings()->setValue(list.at(0),list.at(1));
364         }
365     }
366     _name = settings()->value("bookname");
367     return true;
368 }
369
370
371 QIcon* StarDictPlugin::icon() {
372     return &_icon;
373 }
374
375
376 int StarDictPlugin::countWords() {
377     return 0;
378 }
379
380
381
382 void StarDictPlugin::clean() {
383
384 }
385
386
387 Q_EXPORT_PLUGIN2(stardict, StarDictPlugin)