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