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