1 /*******************************************************************************
3 This file is part of mDictionary.
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.
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.
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/>.
18 Copyright 2010 Comarch S.A.
20 *******************************************************************************/
22 /*! \file xdxfplugin.cpp
23 \author Jakub Jaszczynski <j.j.jaszczynski@gmail.com>
26 #include "xdxfplugin.h"
28 #include "../../include/Notify.h"
29 #include "DownloadDict.h"
30 #include "XdxfDictDownloader.h"
32 XdxfDictDownloader XdxfPlugin::dictDownloader;
34 XdxfPlugin::XdxfPlugin(QObject *parent) : CommonDictInterface(parent),
35 _langFrom(""), _langTo(""),_name(""), _infoNote("") {
37 //DownloadDict a("<tr><td><img src=\"buf/comn_sdict05_bulg_comp/icon16.png\" alt=\"icon\" /></td><td align=\"center\">English-Bulgarian computer dictionary</td><td align=\"center\"><a href=\"http://downloads.sourceforge.net/xdxf/comn_sdict05_bulg_comp.tar.bz2\" target=\"_blank\">comn_sdict05_bulg_comp.tar.bz2</a></td><td align=\"right\">13,889</td><td align=\"right\">55,094</td><td align=\"right\">523</td><td align=\"center\">English</td><td align=\"center\">Bulgarian</td><td align=\"center\"><a href=\"http://xdxf.revdanica.com/\">Common XDXF</a></td><td align=\"center\">2006-04-23 23:34:40</td></tr>");
38 //dictDownloader.download(0);
41 _settings = new Settings();
42 _dictDialog = new XdxfDictDialog(this, this);
44 connect(_dictDialog, SIGNAL(notify(Notify::NotifyType,QString)),
45 this, SIGNAL(notify(Notify::NotifyType,QString)));
48 _settings->setValue("type","xdxf");
49 _icon = QIcon("/usr/share/mdictionary/xdxf.png");
56 void XdxfPlugin::retranslate() {
57 QString locale = QLocale::system().name();
59 QTranslator *translator = new QTranslator(this);
61 if(!translator->load(":/xdxf/translations/" + locale)) {
62 translator->load(":/xdxf/translations/en_US");
64 QCoreApplication::installTranslator(translator);
68 XdxfPlugin::~XdxfPlugin() {
74 QString XdxfPlugin::langFrom() const {
79 QString XdxfPlugin::langTo() const {
84 QString XdxfPlugin::name() const {
89 QString XdxfPlugin::type() const {
90 return QString("xdxf");
94 QString XdxfPlugin::infoNote() const {
99 QList<Translation*> XdxfPlugin::searchWordList(QString word, int limit) {
100 if( word.indexOf("*")==-1 && word.indexOf("?")==-1 &&
101 word.indexOf("_")==-1 && word.indexOf("%")==-1)
105 return searchWordListCache(word,limit);
106 return searchWordListFile(word, limit);
110 QList<Translation*> XdxfPlugin::searchWordListCache(QString word, int limit) {
111 QSet<Translation*> translations;
112 QString cacheFilePath = _settings->value("cache_path");
114 db.setDatabaseName(cacheFilePath);
115 if(!QFile::exists(cacheFilePath) || !db.open()) {
116 qDebug() << "Database error" << db.lastError().text() << endl;
117 Q_EMIT notify(Notify::Warning, QString(tr("Cache database cannot be "
118 "opened for %1 dictionary. Searching in XDXF file. "
119 "You may want to recache.").arg(name())));
120 _settings->setValue("cached","false");
121 return searchWordListFile(word, limit);
124 word = word.toLower();
125 word = word.replace("*", "%");
126 word = word.replace("?", "_");
130 cur.prepare("select word from dict where word like ? or normalized "
133 cur.prepare("select word from dict where word like ? or normalized "
135 cur.addBindValue(word);
136 cur.addBindValue(word);
138 cur.addBindValue(limit);
141 while(cur.next() && (translations.size()<limit || limit==0)) {
142 translations.insert(new TranslationXdxf(
143 cur.value(0).toString(),
144 _dictionaryInfo, this));
147 return translations.toList();
151 QList<Translation*> XdxfPlugin::searchWordListFile(QString word, int limit) {
152 QSet<Translation*> translations;
153 QFile dictionaryFile(_settings->value("path"));
154 word = word.toLower();
157 QRegExp regWord(word);
158 regWord.setCaseSensitivity(Qt::CaseInsensitive);
159 regWord.setPatternSyntax(QRegExp::Wildcard);
161 /*check xdxf file exist*/
162 if(!QFile::exists(_settings->value("path"))
163 || !dictionaryFile.open(QFile::ReadOnly | QFile::Text)) {
164 qDebug()<<"Error: could not open file";
165 Q_EMIT notify(Notify::Warning,
166 QString(tr("XDXF file cannot be read for %1").arg(name())));
167 return translations.toList();
170 QXmlStreamReader reader(&dictionaryFile);
174 /*search words list*/
175 while(!reader.atEnd() && !stopped){
176 reader.readNextStartElement();
177 if(reader.name()=="ar") {
178 while(reader.name()!="k" && !reader.atEnd())
179 reader.readNextStartElement();
181 readKey = reader.readElementText();
182 if((regWord.exactMatch(readKey)
183 || regWord.exactMatch(removeAccents(readKey)))
184 && (i<limit || limit==0) && !reader.atEnd()) {
185 // qDebug()<<readKey;
186 translations<<(new TranslationXdxf(readKey.toLower(),
187 _dictionaryInfo,this));
188 if(translations.size()==limit && limit!=0)
192 this->thread()->yieldCurrentThread();
195 dictionaryFile.close();
196 return translations.toList();
200 QString XdxfPlugin::search(QString key) {
202 return searchCache(key);
203 return searchFile(key);
207 QString XdxfPlugin::searchCache(QString key) {
209 QString cacheFilePath = _settings->value("cache_path");
210 db.setDatabaseName(cacheFilePath);
213 if(!QFile::exists(cacheFilePath) || !db.open()) {
214 qDebug() << "Database error" << db.lastError().text() << endl;
215 Q_EMIT notify(Notify::Warning, QString(tr("Cache database cannot be "
216 "opened for %1 dictionary. Searching in XDXF file. "
217 "You may want to recache.").arg(name())));
218 _settings->setValue("cached","false");
219 return searchFile(key);
224 cur.prepare("select translation from dict where word like ?");
225 cur.addBindValue(key);
228 result += cur.value(0).toString();
237 QString XdxfPlugin::searchFile(QString key) {
238 QFile dictionaryFile(_settings->value("path"));
239 QString resultString("");
242 /*check xdxf file exist*/
243 if(!QFile::exists(_settings->value("path"))
244 || !dictionaryFile.open(QFile::ReadOnly | QFile::Text)) {
245 Q_EMIT notify(Notify::Warning,
246 QString(tr("XDXF file cannot be read for %1").arg(name())));
247 qDebug()<<"Error: could not open file";
251 QXmlStreamReader reader(&dictionaryFile);
256 /*search translations for word*/
257 while (!reader.atEnd()&& !stopped) {
259 if(reader.tokenType() == QXmlStreamReader::StartElement) {
260 if(reader.name()=="k") {
261 readKey = reader.readElementText();
262 if(readKey.toLower()==key.toLower())
268 while(reader.name()!="ar" && !reader.atEnd()) {
269 if(reader.name()!="" && reader.name()!="k") {
270 if(reader.tokenType()==QXmlStreamReader::EndElement)
272 if(reader.tokenType()==QXmlStreamReader::StartElement)
274 temp+=reader.name().toString();
275 if(reader.name().toString()=="c" &&
276 reader.tokenType()==QXmlStreamReader::StartElement)
277 temp= temp + " c=\"" + reader.attributes().
278 value("c").toString() + "\"";
281 temp+= reader.text().toString().replace("<","<").
285 if(temp.at(0)==QChar('\n'))
287 resultString+="<key>" + readKey +"</key>";
288 resultString+="<t>" + temp + "</t>";
291 this->thread()->yieldCurrentThread();
294 dictionaryFile.close();
299 void XdxfPlugin::stop() {
305 DictDialog* XdxfPlugin::dictDialog() {
310 CommonDictInterface* XdxfPlugin::getNew(const Settings *settings) const {
311 XdxfPlugin *plugin = new XdxfPlugin();
313 connect(plugin, SIGNAL(notify(Notify::NotifyType,QString)),
314 this, SIGNAL(notify(Notify::NotifyType,QString)));
316 ((XdxfDictDialog*)plugin->dictDialog())->setLastDialogParent(_dictDialog->lastDialogParent());
320 if(settings && plugin->setSettings(settings)) {
322 disconnect(plugin, SIGNAL(notify(Notify::NotifyType,QString)),
323 this, SIGNAL(notify(Notify::NotifyType,QString)));
327 disconnect(plugin, SIGNAL(notify(Notify::NotifyType,QString)),
328 this, SIGNAL(notify(Notify::NotifyType,QString)));
335 bool XdxfPlugin::isAvailable() const {
340 Settings* XdxfPlugin::settings() {
345 bool XdxfPlugin::isCached() {
346 if(_settings->value("cached") == "true")
352 bool XdxfPlugin::setSettings(const Settings *settings) {
354 bool isPathChange=false;
355 QString oldPath = _settings->value("path");
356 Settings *oldSettings = new Settings ;
358 if(oldPath != settings->value("path")) {
359 if(oldPath!="" && _settings->value("cache_path")!="")
364 foreach(QString key, _settings->keys())
365 oldSettings->setValue(key, _settings->value(key));
367 foreach(QString key, settings->keys()) {
368 if(key != "generateCache")
369 _settings->setValue(key, settings->value(key));
372 if(!getDictionaryInfo()) {
373 Q_EMIT notify(Notify::Warning,
374 QString(tr("XDXF file is in wrong format")));
375 qDebug()<<"Error: xdxf file is in wrong format";
377 _settings=oldSettings;
384 _settings->setValue("cached","false");
385 if(_settings->value("cached")=="true"
386 && _settings->value("cache_path")!="") {
387 db_name = _settings->value("type")
388 + _settings->value("cache_path");
389 db = QSqlDatabase::addDatabase("QSQLITE",db_name);
393 if((_settings->value("cached") == "false" ||
394 _settings->value("cached").isEmpty()) &&
395 settings->value("generateCache") == "true") {
400 else if (settings->value("generateCache") == "false") {
401 _settings->setValue("cached", "false");
406 Q_EMIT settingsChanged();
411 bool XdxfPlugin::getDictionaryInfo() {
412 QFile dictionaryFile(_settings->value("path"));
413 if(!QFile::exists(_settings->value("path"))
414 || !dictionaryFile.open(QFile::ReadOnly | QFile::Text)) {
415 Q_EMIT notify(Notify::Warning,
416 QString(tr("XDXF dictionary cannot be read from file")));
417 qDebug()<<"Error: could not open file";
422 QXmlStreamReader reader(&dictionaryFile);
423 reader.readNextStartElement();
424 if(reader.name()=="xdxf") {
426 if(reader.attributes().hasAttribute("lang_from"))
427 _langFrom = reader.attributes().value("lang_from").toString();
428 if(reader.attributes().hasAttribute("lang_to"))
429 _langTo = reader.attributes().value("lang_to").toString();
431 reader.readNextStartElement();
432 if(reader.name()=="full_name")
433 _name=reader.readElementText();
435 qDebug()<<"no full_name";
436 reader.readNextStartElement();
437 if(reader.name()=="description")
438 _infoNote=reader.readElementText();
440 qDebug()<<"no description";
442 _dictionaryInfo= _name + " [" + _langFrom + "-"
445 dictionaryFile.close();
452 QIcon* XdxfPlugin::icon() {
457 int XdxfPlugin::countWords() {
460 QFile dictionaryFile(_settings->value("path"));
461 if(!QFile::exists(_settings->value("path"))
462 || !dictionaryFile.open(QFile::ReadOnly | QFile::Text)) {
463 Q_EMIT notify(Notify::Warning,
464 QString(tr("XDXF file cannot be read for %1 dictionary")
466 qDebug()<<"Error: could not open file";
470 dictionaryFile.seek(0);
475 while(!dictionaryFile.atEnd()) {
476 line = dictionaryFile.readLine();
477 if(line.contains("<k>")) {
481 _wordsCount = wordsCount;
482 dictionaryFile.close();
487 bool XdxfPlugin::makeCache(QString) {
489 XdxfCachingDialog d(_dictDialog->lastDialogParent());
491 // qDebug()<<_dictDialog->lastDialogParent();
493 connect(&d, SIGNAL(cancelCaching()),
495 connect(this, SIGNAL(updateCachingProgress(int,int)),
496 &d, SLOT(updateCachingProgress(int,int)));
500 QCoreApplication::processEvents();
501 QFileInfo dictFileN(_settings->value("path"));
505 /*create cache file name*/
508 cachePathN = QDir::homePath() + "/.mdictionary/"
509 + dictFileN.completeBaseName()+"."
510 +QString::number(i) + ".cache";
512 } while(QFile::exists(cachePathN));
514 db_name = _settings->value("type") + cachePathN;
515 db = QSqlDatabase::addDatabase("QSQLITE",db_name);
517 /*checke errors (File open and db open)*/
518 QFile dictionaryFile(dictFileN.filePath());
519 if (!QFile::exists(_settings->value("path"))
520 || !dictionaryFile.open(QFile::ReadOnly | QFile::Text)) {
521 Q_EMIT updateCachingProgress(100, 0);
522 Q_EMIT notify(Notify::Warning,
523 QString(tr("XDXF file cannot be read for %1 dictionary")
527 QXmlStreamReader reader(&dictionaryFile);
528 db.setDatabaseName(cachePathN);
530 qDebug() << "Database error" << db.lastError().text() << endl;
531 Q_EMIT updateCachingProgress(100, 0);
532 Q_EMIT notify(Notify::Warning, QString(tr("Cache database cannot be "
533 "opened for %1 dictionary. Searching in XDXF file. "
534 "You may want to recache.").arg(name())));
539 QCoreApplication::processEvents();
541 cur.exec("PRAGMA synchronous = 0");
542 cur.exec("drop table dict");
543 QCoreApplication::processEvents();
544 cur.exec("create table dict(word text, normalized text ,translation text)");
554 _settings->setValue("strip_accents", "true");
557 /*add all words to db*/
558 while (!reader.atEnd() && !stopped) {
560 QCoreApplication::processEvents();
562 if(reader.tokenType() == QXmlStreamReader::StartElement) {
563 if(reader.name()=="k"){
564 readKey = reader.readElementText();
570 while(reader.name()!="ar" && !reader.atEnd()) {
571 if(reader.name()!="" && reader.name()!="k") {
572 if(reader.tokenType()==QXmlStreamReader::EndElement)
574 if(reader.tokenType()==QXmlStreamReader::StartElement)
576 temp+=reader.name().toString();
577 if(reader.name().toString()=="c"
578 && reader.tokenType()==QXmlStreamReader::StartElement) {
580 + reader.attributes().value("c").toString()
585 temp+= reader.text().toString().replace("<","<").replace(">"
589 if(temp.at(0)==QChar('\n'))
591 temp="<key>" + readKey + "</key>" + "<t>" + temp+ "</t>";
593 cur.prepare("insert into dict values(?,?,?)");
594 cur.addBindValue(readKey.toLower());
595 cur.addBindValue(removeAccents(readKey).toLower());
596 cur.addBindValue(temp);
599 int prog = counter*100/_wordsCount;
600 if(prog % 2 == 0 && lastProg != prog) {
601 Q_EMIT updateCachingProgress(prog,timer.restart());
607 cur.exec("select count(*) from dict");
609 /*checke errors (wrong number of added words)*/
611 if(!cur.next() || countWords() != cur.value(0).toInt()) {
612 Q_EMIT updateCachingProgress(100, timer.restart());
613 Q_EMIT notify(Notify::Warning,
614 QString(tr("Database caching error, please try again.")));
616 _settings->setValue("cache_path", cachePathN);
619 _settings->setValue("cache_path","");
623 _settings->setValue("cache_path", cachePathN);
624 _settings->setValue("cached", "true");
626 disconnect(&d, SIGNAL(cancelCaching()),
628 disconnect(this, SIGNAL(updateCachingProgress(int,int)),
629 &d, SLOT(updateCachingProgress(int,int)));
634 void XdxfPlugin::clean() {
635 if(QFile::exists(_settings->value("cache_path"))) {
636 QFile(_settings->value("cache_path")).remove();
637 QSqlDatabase::removeDatabase(db_name);
642 Q_EXPORT_PLUGIN2(xdxf, XdxfPlugin)