change comment's and fix bug (xslt transform)
[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     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(":/stardict/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,
103     len = 0;
104
105     if( word.indexOf("*")==-1 && word.indexOf("?")==-1 &&
106         word.indexOf("_")==-1 && word.indexOf("%")==-1)
107         word+="*";
108     QRegExp keyword(word, Qt::CaseInsensitive, QRegExp::Wildcard);
109
110     if((settings()->value("idxoffsetbits") == "32") ||
111                          (settings()->value("idxoffsetbits") == ""))
112         is32b = true;
113
114     if(!err)
115         return QList<Translation*>();
116
117     stopped=false;
118     while(counter < wordcount && (counterLimit<limit || limit==0) && !stopped) {
119         counter++;
120         fkey = reader->readKeyword();
121         if(is32b)
122             offset = reader->readInt32BigEndian();
123         else
124             offset = reader->readInt64BigEndian();
125         len = reader->readInt32BigEndian();
126
127         if(keyword.exactMatch(fkey)) {
128             TranslationStarDict tran(fkey, infoNote(), this);
129   //          qDebug() << "off/len" << offset << len;
130             int id = translations.indexOf(tran);
131             if(id == -1) {
132                 tran.add(offset, len);
133                 translations.push_front(tran);
134             } else
135                 translations[id].add(offset, len);
136             counterLimit++;
137         }
138     }
139     QList<Translation*> ret;
140     QListIterator<TranslationStarDict> it(translations);
141     while(it.hasNext())
142         ret.push_back(new TranslationStarDict(it.next()));
143     return ret;
144 }
145
146
147 QByteArray StarDictPlugin::read(QByteArray::iterator it,
148         QByteArray::iterator end, int bytes) {
149     QByteArray ret;
150
151     if(bytes == 0 && it != end){
152         while(*it != '\0' && it != end)
153             ret.append(*it++);
154     }
155     else
156         for(int i = 0; i < bytes && it != end; i++)
157             ret.append(*it++);
158     return ret;
159 }
160
161
162 QString StarDictPlugin::interpret(QByteArray::iterator it,
163         QByteArray::iterator end, QChar mode,QString key, bool last) {
164     QString result;
165 //    qDebug()<<"****** mode:     "<<mode;
166     if(mode == 'm' ||
167             mode == 'l' ||
168             mode == 'g' ||
169             mode == 't' ||
170             mode == 'y' ||
171             mode == 'k' ||
172             mode == 'w' ||
173             mode == 'h' ||
174             mode == 'r' ){
175         result += "<key>" + key + "</key>";
176         result += "<t>" + QString::fromUtf8(read(it++, end)) + "</t>";
177     }
178
179     if(mode ==  'g'){
180         /* delete "small" tag  from g translation*/
181         int indexOfSmall=result.indexOf("<small>");
182         while(indexOfSmall!=-1){
183             int indexOfEndSmall= result.indexOf("</small>");
184             if(indexOfEndSmall!=-1)
185                 result.remove(indexOfSmall,indexOfEndSmall-indexOfSmall+8);
186             indexOfSmall=result.indexOf("<small>");
187         }
188     }
189     if(mode == 'x'){
190         result += QString::fromUtf8(read(it++, end));
191         result.replace("</k>","</key><t>");
192         result.replace("<k>","</t><key>");
193         int pos=result.indexOf("</t>");
194         if(pos!=-1)
195             result.remove(pos,4);
196         if(result.contains("<t>"))
197             result+="</t>";
198     }
199
200 // W & P Dont know whether mDictionary would ever handle binary stardict format
201 // to be honest dont see any kind of adventages (can't find any binary dict)
202  /*
203     }
204     else if(mode == 'W') {
205         result += "<key>" + key + "</key>";
206         if(!last) {
207             QByteArray tmp ;
208             tmp.append(*(it++));
209             tmp.append(*(it++));
210             tmp.append(*(it++));
211             tmp.append(*(it));
212             result += read(it++, end, (qint32)qFromBigEndian(*(qint32*)tmp.data()));
213         } else
214             result += read(it++, end);
215     } else if(mode == 'P') {
216         result += "<key>" + key + "</key>";
217         if(!last) {
218             QByteArray tmp ;
219             tmp.append(*(it++));
220             tmp.append(*(it++));
221             tmp.append(*(it++));
222             tmp.append(*(it));
223             result += read(it++, end, (qint32)qFromBigEndian(*(qint32*)tmp.data()));
224         } else
225             result += read(it++, end);
226     } */
227     return result;
228 }
229
230
231 QString StarDictPlugin::format(QByteArray raw, QString mode,QString key) {
232     QString result;
233     if(mode == "") {
234         for(QByteArray::iterator it = raw.begin(); it != raw.end(); it++) {
235             char tmp = *(++it);
236             result += interpret(--it, raw.end(), tmp, key);
237         }
238     } else {
239         QByteArray::iterator it = raw.begin();
240         foreach(QChar tmp, mode) {
241             result += interpret(it, raw.end(), tmp, key);
242         }
243     }
244     return result;
245 }
246
247
248 QString StarDictPlugin::search(QString key, qint64 offset, qint32 len) {
249     QString dictPath = settings()->value("dictFileName");
250     StarDictReader *reader = StarDictReaderFactory::createReader(dictPath);
251     QByteArray raw = reader->readString(offset, len);
252     QString result= format(raw, settings()->value("sametypesequence"),key);
253
254     delete reader;
255     return result;
256 }
257
258
259 void StarDictPlugin::stop() {
260     stopped=true;
261 }
262
263
264 DictDialog* StarDictPlugin::dictDialog() {
265      return _dictDialog;
266 }
267
268
269 CommonDictInterface* StarDictPlugin::getNew(const Settings *settings) const {
270     StarDictPlugin *plugin = new StarDictPlugin();
271
272     connect(plugin, SIGNAL(notify(Notify::NotifyType,QString)),
273             this, SIGNAL(notify(Notify::NotifyType,QString)));
274
275     ((StarDictDialog*)plugin->dictDialog())->
276             setLastDialogParent(_dictDialog->lastDialogParent());
277
278     if(settings && plugin->setSettings(settings)) {
279         disconnect( plugin, SIGNAL(notify(Notify::NotifyType,QString)),
280                     this, SIGNAL(notify(Notify::NotifyType,QString)));
281         plugin->getDictionaryInfo();
282         return plugin;
283     }
284     else {
285         disconnect( plugin, SIGNAL(notify(Notify::NotifyType,QString)),
286                     this, SIGNAL(notify(Notify::NotifyType,QString)));
287         delete plugin;
288         return 0;
289     }
290 }
291
292
293 bool StarDictPlugin::isAvailable() const {
294     return true;
295 }
296
297
298 Settings* StarDictPlugin::settings() {
299     return _settings;
300 }
301
302
303 bool StarDictPlugin::setSettings(const Settings *sett) {
304     if(sett) {
305         foreach(QString key, sett->keys())
306             _settings->setValue(key, sett->value(key));
307
308     } else
309         return false;
310     Q_EMIT settingsChanged();
311     return true;
312 }
313
314
315 bool StarDictPlugin::getDictionaryInfo() {
316     QFile file(settings()->value("ifoFileName"));
317     if(!QFile::exists(_settings->value("ifoFileName"))
318                 || !file.open(QFile::ReadOnly | QFile::Text)) {
319         Q_EMIT notify(Notify::Warning,
320                QString(tr("StarDict dictionary cannot be read from file")));
321         qDebug()<<"Error: could not open the file";
322         return false;
323     }
324     QTextStream in(&file);
325     while (!in.atEnd()) {
326         QString line = in.readLine();
327         QStringList list = line.split("=");
328         if(list.size() == 2) {
329             settings()->setValue(list.at(0),list.at(1));
330         }
331     }
332     _name = settings()->value("bookname");
333     return true;
334 }
335
336
337 QIcon* StarDictPlugin::icon() {
338     return &_icon;
339 }
340
341 Q_EXPORT_PLUGIN2(stardict, StarDictPlugin)