dictengine.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * Copyright (C) 2008 Nick Shaforostoff <shaforostoff@kde.ru>
  3. *
  4. * based on work by:
  5. * Copyright (C) 2007 Thomas Georgiou <TAGeorgiou@gmail.com> and Jeff Cooper <weirdsox11@gmail.com>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include "dictengine.h"
  21. #include "dictplugin.h"
  22. #include "config.h"
  23. #include <QPluginLoader>
  24. #include <QPointer>
  25. #include <QMap>
  26. #include <QTimer>
  27. #include <QTime>
  28. #include <QSettings>
  29. #include <KDebug>
  30. // #include <KLocale>
  31. #include <Plasma/DataContainer>
  32. #define MEMORYFREE_DELAY 60000
  33. /**
  34. * This class represents a dictionary provided by a plugin
  35. */
  36. class Dictionary
  37. {
  38. public:
  39. Dictionary(const QString &plugin, const QString &name)
  40. : m_plugin(plugin)
  41. , m_name(name)
  42. {}
  43. Dictionary()
  44. {}
  45. const QString &plugin() const {return m_plugin;}
  46. const QString &name() const {return m_name;}
  47. void setPlugin(const QString &plugin) {m_plugin=plugin;}
  48. void setName(const QString &name) {m_name=name;}
  49. bool operator == (const Dictionary &dict) {return m_name==dict.m_name && m_plugin==dict.m_plugin;}
  50. private:
  51. QString m_plugin;
  52. QString m_name;
  53. };
  54. struct QStarDictEngine::Private
  55. {
  56. QString currentWord;
  57. QTimer timer;
  58. QHash<QString, QPointer<QPluginLoader> > plugins; //name to pointer
  59. // QList<Dictionary> dicts;
  60. // QHash<QString, QString> dictToPlugin; //name to metastructure
  61. QHash<QString, Dictionary> dicts; //name to metastructure
  62. };
  63. QStarDictEngine::QStarDictEngine(QObject* parent, const QVariantList& args)
  64. : Plasma::DataEngine(parent, args)
  65. , d(new Private)
  66. {
  67. Q_UNUSED(args)
  68. // QTime a;a.start();
  69. #ifdef Q_OS_WIN
  70. QFileInfoList files = QDir(QSTARDICT_PLUGINS_DIR).entryInfoList(QStringList("*0.dll"),QDir::Files|QDir::NoDotAndDotDot);
  71. for (QFileInfoList::const_iterator i = files.begin(); i != files.end(); ++i)
  72. d->plugins[i->fileName().left(i->fileName().length()-5))]=0;
  73. #else
  74. qWarning()<<QSTARDICT_PLUGINS_DIR;
  75. QFileInfoList files = QDir(QSTARDICT_PLUGINS_DIR).entryInfoList(QStringList("lib*.so"),QDir::Files|QDir::NoDotAndDotDot);
  76. for (QFileInfoList::const_iterator i = files.begin(); i != files.end(); ++i)
  77. d->plugins[i->fileName().mid(3, i->fileName().length()-6)]=0;
  78. #endif
  79. // use cache to not load redudant plugins? 16->10 ms
  80. // QSettings settings("qstardict","qstardict");
  81. // m_dictDirs = settings.value("Multitran/dictDirs", m_dictDirs).toStringList();
  82. d->timer.setInterval(MEMORYFREE_DELAY);
  83. d->timer.setSingleShot(true);
  84. connect(&d->timer, SIGNAL(timeout()), this, SLOT(unloadPlugins()));
  85. QList<QString> plugins=d->plugins.keys();
  86. for (QList<QString>::const_iterator i = plugins.constBegin(); i != plugins.constEnd(); ++i)
  87. {
  88. // QStringList dicts = settings.value(*i+"/dicts", QStringList()).toStringList();
  89. // if (!dicts.isEmpty())
  90. // {
  91. QStarDict::DictPlugin* plugin = dictPlugin(*i);
  92. if (!plugin)
  93. continue;
  94. QStringList dicts=plugin->availableDicts();
  95. // settings.setValue(*i+"/dicts", QVariant(dicts));
  96. // plugin->setdicts(dicts);
  97. // }
  98. for (QStringList::const_iterator j = dicts.constBegin(); j != dicts.constEnd(); ++j)
  99. d->dicts[*j]=Dictionary(*i, *j);
  100. // d->dicts<<Dictionary(*i, *j);
  101. }
  102. // qWarning()<<a.elapsed();
  103. }
  104. QStarDictEngine::~QStarDictEngine()
  105. {
  106. unloadPlugins();
  107. delete d;
  108. }
  109. QStarDict::DictPlugin* QStarDictEngine::dictPlugin(const QString &name)
  110. {
  111. if (! d->plugins.contains(name) )
  112. return 0;
  113. if (! d->plugins.value(name) )
  114. {
  115. #ifdef Q_OS_WIN
  116. QString pluginFilename = QSTARDICT_PLUGINS_DIR "/" + name + "0.dll";
  117. #else
  118. QString pluginFilename = QSTARDICT_PLUGINS_DIR "/" "lib" + name + ".so";
  119. #endif
  120. QPluginLoader* plugin = new QPluginLoader(pluginFilename);
  121. if (! plugin->load())
  122. {
  123. kWarning() << plugin->errorString();
  124. delete plugin;
  125. return 0;
  126. }
  127. d->plugins[name]=plugin;
  128. }
  129. return qobject_cast<QStarDict::DictPlugin*>(d->plugins.value(name)->instance());
  130. }
  131. void QStarDictEngine::unloadPlugins()
  132. {
  133. for (QHash<QString, QPointer<QPluginLoader> >::iterator i = d->plugins.begin(); i != d->plugins.end(); ++i)
  134. {
  135. if (*i)
  136. {
  137. (*i)->instance()->deleteLater();
  138. (*i)->deleteLater();
  139. }
  140. }
  141. }
  142. bool QStarDictEngine::sourceRequestEvent(const QString &word)
  143. {
  144. qWarning()<<"sourceRequestEvent"<<word;
  145. d->timer.start();//delay freeing resources / activate delayed resources freeing
  146. if (word=="list-dictionaries")
  147. {
  148. QStringList result;
  149. int i=d->plugins.keys().size();
  150. while (--i>=0)
  151. {
  152. QStarDict::DictPlugin* plugin = dictPlugin(d->plugins.keys().at(i));
  153. if (!plugin)
  154. continue;
  155. result << plugin->availableDicts();
  156. }
  157. setData("list-dictionaries", "dictionaries", result);
  158. qWarning()<<result;
  159. return true;
  160. }
  161. QString simplifiedWord;
  162. QStringList queriedDicts;
  163. int pos=word.indexOf(':');
  164. if (pos!=-1)
  165. {
  166. queriedDicts=word.left(pos).split(',');
  167. simplifiedWord=word.mid(pos+1).simplified();
  168. }
  169. else
  170. simplifiedWord=word.simplified();
  171. qWarning()<<"simplifiedWord"<<simplifiedWord;
  172. qWarning()<<"queriedDicts"<<queriedDicts;
  173. if (queriedDicts.isEmpty())
  174. for (QHash<QString,Dictionary>::const_iterator i = d->dicts.constBegin(); i != d->dicts.constEnd(); ++i)
  175. queriedDicts<<i->name();
  176. d->currentWord = word;
  177. QString result;
  178. if (simplifiedWord.length() == 0)
  179. {
  180. setData(d->currentWord, "text", QString());
  181. return true;
  182. }
  183. for (QStringList::const_iterator i = queriedDicts.constBegin(); i != queriedDicts.constEnd(); ++i)
  184. {
  185. if (!d->dicts.contains(*i))
  186. continue;
  187. QStarDict::DictPlugin* plugin = dictPlugin(d->dicts.value(*i).plugin());
  188. if (!plugin)
  189. continue;
  190. QStringList ld=plugin->loadedDicts();
  191. if (!ld.contains(*i))
  192. plugin->setLoadedDicts(ld<<*i);
  193. if ( !plugin->isTranslatable(*i, simplifiedWord))
  194. continue;
  195. QStarDict::DictPlugin::Translation translation = plugin->translate(*i, simplifiedWord);
  196. if (translation.translation().isEmpty())
  197. continue;
  198. result += "<p>\n"
  199. "<font class=\"dict_name\">" + translation.dictName() + "</font><br>\n"
  200. "<font class=\"title\">" + translation.title() + "</font><br>\n"
  201. + translation.translation() + "</p>\n";
  202. }
  203. setData(d->currentWord, "text", result);
  204. return true;
  205. }
  206. #include "dictengine.moc"