init
[qstardict] / kdeplasma / dataengine / dictengine.cpp
diff --git a/kdeplasma/dataengine/dictengine.cpp b/kdeplasma/dataengine/dictengine.cpp
new file mode 100644 (file)
index 0000000..2e9afb5
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ *   Copyright (C) 2008 Nick Shaforostoff <shaforostoff@kde.ru>
+ *
+ *   based on work by:
+ *   Copyright (C) 2007 Thomas Georgiou <TAGeorgiou@gmail.com> and Jeff Cooper <weirdsox11@gmail.com>
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License as
+ *   published by the Free Software Foundation; either version 2 of 
+ *   the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "dictengine.h"
+#include "dictplugin.h"
+#include "config.h"
+
+#include <QPluginLoader>
+#include <QPointer>
+#include <QMap>
+#include <QTimer>
+#include <QTime>
+#include <QSettings>
+#include <KDebug>
+// #include <KLocale>
+
+#include <Plasma/DataContainer>
+
+#define MEMORYFREE_DELAY 60000
+
+
+/**
+ * This class represents a dictionary provided by a plugin
+ */
+class Dictionary
+{
+    public:
+        Dictionary(const QString &plugin, const QString &name)
+            : m_plugin(plugin)
+            , m_name(name)
+        {}
+        Dictionary()
+        {}
+
+        const QString &plugin() const {return m_plugin;}
+        const QString &name() const {return m_name;}
+        void setPlugin(const QString &plugin) {m_plugin=plugin;}
+        void setName(const QString &name) {m_name=name;}
+        bool operator == (const Dictionary &dict) {return m_name==dict.m_name && m_plugin==dict.m_plugin;}
+
+    private:
+        QString m_plugin;
+        QString m_name;
+};
+
+
+struct QStarDictEngine::Private
+{
+    QString currentWord;
+    QTimer timer;
+
+    QHash<QString, QPointer<QPluginLoader> > plugins; //name to pointer
+//     QList<Dictionary> dicts;
+//     QHash<QString, QString> dictToPlugin; //name to metastructure
+    QHash<QString, Dictionary> dicts; //name to metastructure
+
+};
+
+
+
+
+
+
+QStarDictEngine::QStarDictEngine(QObject* parent, const QVariantList& args)
+    : Plasma::DataEngine(parent, args)
+    , d(new Private)
+{
+    Q_UNUSED(args)
+//     QTime a;a.start();
+#ifdef Q_OS_WIN
+    QFileInfoList files = QDir(QSTARDICT_PLUGINS_DIR).entryInfoList(QStringList("*0.dll"),QDir::Files|QDir::NoDotAndDotDot);
+    for (QFileInfoList::const_iterator i = files.begin(); i != files.end(); ++i)
+        d->plugins[i->fileName().left(i->fileName().length()-5))]=0;
+#else
+    qWarning()<<QSTARDICT_PLUGINS_DIR;
+    QFileInfoList files = QDir(QSTARDICT_PLUGINS_DIR).entryInfoList(QStringList("lib*.so"),QDir::Files|QDir::NoDotAndDotDot);
+    for (QFileInfoList::const_iterator i = files.begin(); i != files.end(); ++i)
+        d->plugins[i->fileName().mid(3, i->fileName().length()-6)]=0;
+#endif
+
+
+
+    // use cache to not load redudant plugins? 16->10 ms
+//     QSettings settings("qstardict","qstardict");
+//     m_dictDirs = settings.value("Multitran/dictDirs", m_dictDirs).toStringList();
+
+    d->timer.setInterval(MEMORYFREE_DELAY);
+    d->timer.setSingleShot(true);
+    connect(&d->timer, SIGNAL(timeout()), this, SLOT(unloadPlugins()));
+
+
+    QList<QString> plugins=d->plugins.keys();
+    for (QList<QString>::const_iterator i = plugins.constBegin(); i != plugins.constEnd(); ++i)
+    {
+//         QStringList dicts = settings.value(*i+"/dicts", QStringList()).toStringList();
+//         if (!dicts.isEmpty())
+//         {
+            QStarDict::DictPlugin* plugin = dictPlugin(*i);
+            if (!plugin)
+                continue;
+            QStringList dicts=plugin->availableDicts();
+//             settings.setValue(*i+"/dicts", QVariant(dicts));
+//            plugin->setdicts(dicts);
+//         }
+        for (QStringList::const_iterator j = dicts.constBegin(); j != dicts.constEnd(); ++j)
+            d->dicts[*j]=Dictionary(*i, *j);
+//             d->dicts<<Dictionary(*i, *j);
+    }
+//     qWarning()<<a.elapsed();
+
+}
+
+QStarDictEngine::~QStarDictEngine()
+{
+    unloadPlugins();
+    delete d;
+}
+
+
+
+QStarDict::DictPlugin* QStarDictEngine::dictPlugin(const QString &name)
+{
+    if (! d->plugins.contains(name) )
+        return 0;
+    if (! d->plugins.value(name) )
+    {
+#ifdef Q_OS_WIN
+        QString pluginFilename = QSTARDICT_PLUGINS_DIR "/" + name + "0.dll";
+#else 
+        QString pluginFilename = QSTARDICT_PLUGINS_DIR "/" "lib" + name + ".so";
+#endif
+        QPluginLoader* plugin = new QPluginLoader(pluginFilename);
+        if (! plugin->load())
+        {
+            kWarning() << plugin->errorString();
+            delete plugin;
+            return 0;
+        }
+        d->plugins[name]=plugin;
+    }
+
+    return qobject_cast<QStarDict::DictPlugin*>(d->plugins.value(name)->instance());
+}
+
+void QStarDictEngine::unloadPlugins()
+{
+    for (QHash<QString, QPointer<QPluginLoader> >::iterator i = d->plugins.begin(); i != d->plugins.end(); ++i)
+    {
+        if (*i)
+        {
+            (*i)->instance()->deleteLater();
+            (*i)->deleteLater();
+        }
+    }
+
+}
+
+bool QStarDictEngine::sourceRequestEvent(const QString &word)
+{
+    qWarning()<<"sourceRequestEvent"<<word;
+    d->timer.start();//delay freeing resources / activate delayed resources freeing
+
+    if (word=="list-dictionaries")
+    {
+        QStringList result;
+        int i=d->plugins.keys().size();
+        while (--i>=0)
+        {
+            QStarDict::DictPlugin* plugin = dictPlugin(d->plugins.keys().at(i));
+            if (!plugin)
+                continue;
+            result << plugin->availableDicts();
+        }
+        setData("list-dictionaries", "dictionaries", result);
+        qWarning()<<result;
+        return true;
+    }
+
+    QString simplifiedWord;
+    QStringList queriedDicts;
+    int pos=word.indexOf(':');
+    if (pos!=-1)
+    {
+        queriedDicts=word.left(pos).split(',');
+        simplifiedWord=word.mid(pos+1).simplified();
+    }
+    else
+        simplifiedWord=word.simplified();
+    qWarning()<<"simplifiedWord"<<simplifiedWord;
+    qWarning()<<"queriedDicts"<<queriedDicts;
+
+    if (queriedDicts.isEmpty())
+        for (QHash<QString,Dictionary>::const_iterator i = d->dicts.constBegin(); i != d->dicts.constEnd(); ++i)
+            queriedDicts<<i->name();
+
+    d->currentWord = word;
+    QString result;
+
+    if (simplifiedWord.length() == 0)
+    {
+        setData(d->currentWord, "text", QString());
+        return true;
+    }
+
+    for (QStringList::const_iterator i = queriedDicts.constBegin(); i != queriedDicts.constEnd(); ++i)
+    {
+        if (!d->dicts.contains(*i))
+            continue;
+        QStarDict::DictPlugin* plugin = dictPlugin(d->dicts.value(*i).plugin());
+        if (!plugin)
+            continue;
+        QStringList ld=plugin->loadedDicts();
+        if (!ld.contains(*i))
+            plugin->setLoadedDicts(ld<<*i);
+        if ( !plugin->isTranslatable(*i, simplifiedWord))
+            continue;
+        QStarDict::DictPlugin::Translation translation = plugin->translate(*i, simplifiedWord);
+        if (translation.translation().isEmpty())
+            continue;
+        result += "<p>\n"
+            "<font class=\"dict_name\">" + translation.dictName() + "</font><br>\n"
+            "<font class=\"title\">" + translation.title() + "</font><br>\n"
+            + translation.translation() + "</p>\n";
+    }
+
+    setData(d->currentWord, "text", result);
+    return true;
+}
+
+
+
+
+
+#include "dictengine.moc"