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