From e99bdd51d6d6f310cdd8a46fb0888f0342bc489a Mon Sep 17 00:00:00 2001
From: Ivailo Monev
Date: Mon, 21 Feb 2022 08:33:28 +0200
Subject: [PATCH] plasma: reimplement dictionary data engine
requires:
https://github.com/fluxer/katie/commit/808d94b266f649949b0524e111201e4fb4f6856f
works like a charm:
https://ibb.co/j4Czypq
Signed-off-by: Ivailo Monev
---
plasma/dataengines/dict/dictengine.cpp | 285 ++++++++++-----------------------
plasma/dataengines/dict/dictengine.h | 55 +++----
2 files changed, 104 insertions(+), 236 deletions(-)
diff --git a/plasma/dataengines/dict/dictengine.cpp b/plasma/dataengines/dict/dictengine.cpp
index 73944a90..8447be16 100644
--- a/plasma/dataengines/dict/dictengine.cpp
+++ b/plasma/dataengines/dict/dictengine.cpp
@@ -1,239 +1,116 @@
-/*
- * Copyright (C) 2007 Thomas Georgiou and Jeff Cooper
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License version 2 as
- * published by the Free Software Foundation
- *
- * 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 Library General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
+/* This file is part of the KDE project
+ Copyright (C) 2022 Ivailo Monev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2, as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
#include "dictengine.h"
-#include
#include
#include
-
-#include
+#include
+#include
DictEngine::DictEngine(QObject* parent, const QVariantList& args)
: Plasma::DataEngine(parent, args)
- , m_tcpSocket(0)
{
- Q_UNUSED(args)
- m_serverName = "dict.org"; //In case we need to switch it later
- m_dictName = "wn"; //Default, good dictionary
}
DictEngine::~DictEngine()
{
}
-void DictEngine::setDict(const QString &dict)
-{
- m_dictName = dict;
-}
-
-void DictEngine::setServer(const QString &server)
+bool DictEngine::sourceRequestEvent(const QString &query)
{
- m_serverName = server;
-}
+ // qDebug() << Q_FUNC_INFO << query;
-static QString wnToHtml(const QString &word, QByteArray &text)
-{
- Q_UNUSED(word)
- QList splitText = text.split('\n');
- QString def;
- def += "\n";
- QRegExp linkRx("\\{(.*)\\}");
- linkRx.setMinimal(true);
-
- bool isFirst=true;
- while (!splitText.empty()) {
- //150 n definitions retrieved - definitions follow
- //151 word database name - text follows
- //250 ok (optional timing information here)
- //552 No match
- QString currentLine = splitText.takeFirst();
- if (currentLine.startsWith(QLatin1String("151"))) {
- isFirst = true;
- continue;
- }
-
- if (currentLine.startsWith('.')) {
- def += "";
- continue;
- }
-
- if (!(currentLine.startsWith(QLatin1String("150"))
- || currentLine.startsWith(QLatin1String("151"))
- || currentLine.startsWith(QLatin1String("250"))
- || currentLine.startsWith(QLatin1String("552")))) {
- currentLine.replace(linkRx,"\\1");
-
- if (isFirst) {
- def += "- " + currentLine + "
\n- ";
- isFirst = false;
- continue;
- } else {
- if (currentLine.contains(QRegExp("([1-9]{1,2}:)"))) {
- def += "\n
\n";
- }
- currentLine.replace(QRegExp("^([\\s\\S]*[1-9]{1,2}:)"), "\\1");
- def += currentLine;
- continue;
- }
- }
+ setData(query, QString("text"), QString());
+ setData(QString("list-dictionaries"), QString("dictionaries"), QString());
+ const QStringList splitquery = query.split(QLatin1Char(':'));
+ QString queryword = query;
+ if (splitquery.size() == 2) {
+ queryword = splitquery.at(1);
}
- def += "
";
- return def;
-}
-
-void DictEngine::getDefinition()
-{
- m_tcpSocket->readAll();
- QByteArray ret;
-
- m_tcpSocket->write(QByteArray("DEFINE "));
- m_tcpSocket->write(m_dictName.toAscii());
- m_tcpSocket->write(QByteArray(" \""));
- m_tcpSocket->write(m_currentWord.toUtf8());
- m_tcpSocket->write(QByteArray("\"\n"));
- m_tcpSocket->flush();
-
- while (!ret.contains("250") && !ret.contains("552") && !ret.contains("550")) {
- m_tcpSocket->waitForReadyRead();
- ret += m_tcpSocket->readAll();
+ if (queryword.isEmpty()) {
+ return false;
+ } else if (queryword.contains(' ')) {
+ setError(query, QLatin1String("Only words can be queried"));
+ return true;
}
- connect(m_tcpSocket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
- m_tcpSocket->disconnectFromHost();
- // setData(m_currentWord, m_dictName, ret);
- // qWarning()< theHash;
- m_tcpSocket->readAll();
- QByteArray ret;
-
- m_tcpSocket->write(QByteArray("SHOW DB\n"));;
- m_tcpSocket->flush();
-
- m_tcpSocket->waitForReadyRead();
- while (!ret.contains("250")) {
- m_tcpSocket->waitForReadyRead();
- ret += m_tcpSocket->readAll();
+ m_data.clear();
+ const KUrl queryurl = QString::fromLatin1("https://api.dictionaryapi.dev/api/v2/entries/en/") + queryword;
+ KIO::TransferJob *kiojob = KIO::get(queryurl, KIO::Reload, KIO::HideProgressInfo);
+ connect(kiojob, SIGNAL(data(KIO::Job*,QByteArray)), this, SLOT(slotKIOData(KIO::Job*,QByteArray)));
+ const bool kioresult = KIO::NetAccess::synchronousRun(kiojob, nullptr);
+ if (!kioresult) {
+ kWarning() << "KIO job failed";
+ setError(query, QLatin1String("Cannot get meaning"));
+ return true;
}
- QList retLines = ret.split('\n');
- QString tmp1, tmp2;
-
- while (!retLines.empty()) {
- QString curr(retLines.takeFirst());
-
- if (curr.startsWith(QLatin1String("554"))) {
- //TODO: What happens if no DB available?
- //TODO: Eventually there will be functionality to change the server...
- break;
- }
-
- // ignore status code and empty lines
- if (curr.startsWith(QLatin1String("250")) || curr.startsWith(QLatin1String("110"))
- || curr.isEmpty()) {
- continue;
- }
-
- if (!curr.startsWith('-') && !curr.startsWith('.')) {
- curr = curr.trimmed();
- tmp1 = curr.section(' ', 0, 0);
- tmp2 = curr.section(' ', 1);
- // theHash.insert(tmp1, tmp2);
- //kDebug() << tmp1 + " " + tmp2;
- setData("list-dictionaries", tmp1, tmp2);
- }
+ const QJsonDocument jsondocument = QJsonDocument::fromJson(m_data);
+ if (jsondocument.isNull()) {
+ kWarning() << jsondocument.errorString();
+ setError(query, QLatin1String("Cannot parse JSON"));
+ return true;
}
- m_tcpSocket->disconnectFromHost();
-// setData("list-dictionaries", "dictionaries", QByteArray(theHash);
+ const QVariantList rootlist = jsondocument.toVariant().toList();
+ if (rootlist.isEmpty()) {
+ setError(query, QLatin1String("Unexpected JSON data"));
+ return true;
+ }
+ const QVariantList meaningslist = rootlist.first().toMap().value("meanings").toList();
+ if (meaningslist.isEmpty()) {
+ setError(query, QLatin1String("Unexpected meanings data"));
+ return true;
+ }
+ // qDebug() << Q_FUNC_INFO << "meanings" << meaningslist;
+ const QVariantList definitionslist = meaningslist.first().toMap().value("definitions").toList();
+ if (definitionslist.isEmpty()) {
+ setError(query, QLatin1String("Unexpected definitions data"));
+ return true;
+ }
+ // qDebug() << Q_FUNC_INFO << "definitions" << definitionslist;
+ QString meaning = "\n
Definition: ";
+ meaning.append(definitionslist.first().toMap().value("definition").toString());
+ meaning.append("\n
");
+ meaning.append("\nExample: ");
+ meaning.append(definitionslist.first().toMap().value("example").toString());
+ meaning.append("\n
\n
\n");
+ // qDebug() << Q_FUNC_INFO << "meaning" << meaning;
+
+ setData(query, QString("text"), meaning);
+ setData(QString("list-dictionaries"), QString("dictionaries"), QString("en"));
+ return true;
}
-
-
-void DictEngine::socketClosed()
+void DictEngine::slotKIOData(KIO::Job *kiojob, const QByteArray &kiodata)
{
- m_tcpSocket->deleteLater();
- m_tcpSocket = 0;
+ Q_UNUSED(kiojob);
+ m_data.append(kiodata);
}
-bool DictEngine::sourceRequestEvent(const QString &query)
+void DictEngine::setError(const QString &query, const QString &message)
{
- // FIXME: this is COMPLETELY broken .. it can only look up one query at a time!
- // a DataContainer subclass that does the look up should probably be made
- if (m_currentQuery == query) {
- return false;
- }
-
- if (m_tcpSocket) {
- m_tcpSocket->abort(); //stop if lookup is in progress and new query is requested
- m_tcpSocket->deleteLater();
- m_tcpSocket = 0;
- }
-
- QStringList queryParts = query.split(':', QString::SkipEmptyParts);
- if (queryParts.isEmpty()) {
- return false;
- }
-
- m_currentWord = queryParts.last();
- m_currentQuery = query;
-
- //asked for a dictionary?
- if (queryParts.count() > 1) {
- setDict(queryParts[queryParts.count()-2]);
- //default to wordnet
- } else {
- setDict("wn");
- }
-
- //asked for a server?
- if (queryParts.count() > 2) {
- setServer(queryParts[queryParts.count()-3]);
- //default to wordnet
- } else {
- setServer("dict.org");
- }
-
- if (m_currentWord.simplified().isEmpty()) {
- setData(m_currentWord, m_dictName, QString());
- } else {
- setData(m_currentWord, m_dictName, QString());
- m_tcpSocket = new QSslSocket(this);
- m_tcpSocket->abort();
- connect(m_tcpSocket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
-
- if (m_currentWord == "list-dictionaries") {
- connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(getDicts()));
- } else {
- connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(getDefinition()));
- }
-
- m_tcpSocket->connectToHost(m_serverName, 2628);
- }
-
- return true;
+ setData(query, QString("text"), QString::fromLatin1("\n
%1\n
").arg(message));
+ setData(QString("list-dictionaries"), QString("dictionaries"), QString("en"));
}
#include "moc_dictengine.cpp"
diff --git a/plasma/dataengines/dict/dictengine.h b/plasma/dataengines/dict/dictengine.h
index 0e550115..b7be948f 100644
--- a/plasma/dataengines/dict/dictengine.h
+++ b/plasma/dataengines/dict/dictengine.h
@@ -1,26 +1,26 @@
-/*
- * Copyright (C) 2007 Thomas Georgiou and Jeff Cooper
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License version 2 as
- * published by the Free Software Foundation
- *
- * 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 Library General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
+/* This file is part of the KDE project
+ Copyright (C) 2022 Ivailo Monev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2, as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
#ifndef DICTENGINE_H
#define DICTENGINE_H
+
#include
-#include
-#include
+#include
/**
* This class evaluates the basic expressions given in the interface.
@@ -38,22 +38,13 @@ class DictEngine: public Plasma::DataEngine
protected:
bool sourceRequestEvent(const QString &word);
- private slots:
- void getDefinition();
- void socketClosed();
- void getDicts();
+ private Q_SLOTS:
+ void slotKIOData(KIO::Job *kiojob, const QByteArray &kiodata);
private:
- void setDict(const QString &dict);
- void setServer(const QString &server);
-
- QHash m_dictNameToDictCode;
- QSslSocket *m_tcpSocket;
- QString m_currentWord;
- QString m_currentQuery;
- QString m_dictName;
- QString m_serverName;
+ void setError(const QString &query, const QString &message);
+ QByteArray m_data;
};
K_EXPORT_PLASMA_DATAENGINE(dict, DictEngine)
--
2.11.0