summaryrefslogtreecommitdiff
path: root/src/opensearch
diff options
context:
space:
mode:
authorAndrea Diamantini <adjam7@gmail.com>2010-12-21 21:59:23 +0100
committerAndrea Diamantini <adjam7@gmail.com>2010-12-21 21:59:23 +0100
commit925725bfcf0f3ffba5107949bc8424e1fd6d1902 (patch)
treeee10e2c10e3ec63b0977661cfbc0ef69ad98002a /src/opensearch
parentAdding a tab list menu entry showing all open tabs. (diff)
downloadrekonq-925725bfcf0f3ffba5107949bc8424e1fd6d1902.tar.xz
Icon at the right of the urlbar that allows to add an opensearch engine
introduce search icon description file downloaded after validation, not before icons updated when engine added add opensearch xml description files sync desktop file => fix add webshortcut use db_opensearch.json file to track opensearch engines create an opensearch description only when the engine support suggestions remove opensearch description when an engine is deleted in the webshortcut setting dialog popup: disable ok button when webshortcut is already used Lionel Chauvin is the man having done this big, big, big work!! I'm just merging ;)
Diffstat (limited to 'src/opensearch')
-rw-r--r--src/opensearch/opensearchengine.cpp6
-rw-r--r--src/opensearch/opensearchmanager.cpp166
-rw-r--r--src/opensearch/opensearchmanager.h20
-rw-r--r--src/opensearch/suggestionparser.cpp25
4 files changed, 175 insertions, 42 deletions
diff --git a/src/opensearch/opensearchengine.cpp b/src/opensearch/opensearchengine.cpp
index 9d5e866f..37685fb5 100644
--- a/src/opensearch/opensearchengine.cpp
+++ b/src/opensearch/opensearchengine.cpp
@@ -57,12 +57,18 @@ QString OpenSearchEngine::parseTemplate(const QString &searchTerm, const QString
QString language = QLocale().name();
// Simple conversion to RFC 3066.
language = language.replace(QL1C('_'), QL1C('-'));
+ QString country = language;
+ country = (country.replace(0, country.indexOf("-")+1, "")).toLower();
+ const int firstDashPosition = country.indexOf(QL1C('-'));
+ if (firstDashPosition >= 0)
+ country = country.mid(firstDashPosition+1);
QString result = searchTemplate;
result.replace(QL1S("{count}"), QL1S("20"));
result.replace(QL1S("{startIndex}"), QL1S("0"));
result.replace(QL1S("{startPage}"), QL1S("0"));
result.replace(QL1S("{language}"), language);
+ result.replace(QL1S("{country}"), country.toLower());
result.replace(QL1S("{inputEncoding}"), QL1S("UTF-8"));
result.replace(QL1S("{outputEncoding}"), QL1S("UTF-8"));
result.replace(QL1S("{searchTerms}"), searchTerm);
diff --git a/src/opensearch/opensearchmanager.cpp b/src/opensearch/opensearchmanager.cpp
index e5afc144..4ee1de33 100644
--- a/src/opensearch/opensearchmanager.cpp
+++ b/src/opensearch/opensearchmanager.cpp
@@ -34,6 +34,7 @@
#include "opensearchengine.h"
#include "opensearchreader.h"
#include "opensearchwriter.h"
+#include "application.h"
// KDE Includes
#include <KDebug>
@@ -41,10 +42,17 @@
#include <KStandardDirs>
#include <KUrl>
#include <kio/scheduler.h>
+#include <KService>
+#include <KStandardDirs>
+#include <KDE/KMessageBox>
+#include <KUriFilterData>
+#include <KConfigGroup>
// Qt Includes
#include <QtCore/QFile>
-
+#include <QtCore/QFileInfo>
+#include <QDBusMessage>
+#include <QDBusConnection>
OpenSearchManager::OpenSearchManager(QObject *parent)
: QObject(parent)
@@ -52,13 +60,15 @@ OpenSearchManager::OpenSearchManager(QObject *parent)
, m_currentJob(0)
{
m_state = IDLE;
+ loadEngines();
}
OpenSearchManager::~OpenSearchManager()
{
- qDeleteAll(m_enginesMap.values());
- m_enginesMap.clear();
+ qDeleteAll(m_engineCache.values());
+ m_engineCache.clear();
+ m_engines.clear();
}
@@ -66,10 +76,10 @@ void OpenSearchManager::setSearchProvider(const QString &searchProvider)
{
m_activeEngine = 0;
- if (!m_enginesMap.contains(searchProvider))
+ if (!m_engineCache.contains(searchProvider))
{
- const QString fileName = KGlobal::dirs()->findResource("data", "rekonq/opensearch/" + searchProvider + ".xml");
- kDebug() << searchProvider << " file name path: " << fileName;
+ const QString fileName = KGlobal::dirs()->findResource("data", "rekonq/opensearch/" + trimmedEngineName(searchProvider) + ".xml");
+ kDebug() << searchProvider << " trimmed name: " << trimmedEngineName(searchProvider) << " file name path: " << fileName;
if (fileName.isEmpty())
{
kDebug() << "OpenSearch file name empty";
@@ -88,7 +98,7 @@ void OpenSearchManager::setSearchProvider(const QString &searchProvider)
if (engine)
{
- m_enginesMap.insert(searchProvider, engine);
+ m_engineCache.insert(searchProvider, engine);
}
else
{
@@ -96,7 +106,7 @@ void OpenSearchManager::setSearchProvider(const QString &searchProvider)
}
}
- m_activeEngine = m_enginesMap.value(searchProvider);
+ m_activeEngine = m_engineCache.value(searchProvider);
}
@@ -106,22 +116,24 @@ bool OpenSearchManager::isSuggestionAvailable()
}
-void OpenSearchManager::addOpenSearchEngine(const KUrl &url, const QString &title)
+void OpenSearchManager::addOpenSearchEngine(const KUrl &url, const QString &title, const QString &shortcut)
{
Q_UNUSED(title);
+ m_shortcut = shortcut;
+
if (m_state != IDLE)
{
idleJob();
}
m_currentJob = KIO::get(url, KIO::NoReload, KIO::HideProgressInfo);
+ m_jobUrl = url;
m_state = REQ_DESCRIPTION;
connect(m_currentJob, SIGNAL(data(KIO::Job *, const QByteArray &)), this, SLOT(dataReceived(KIO::Job *, const QByteArray &)));
connect(m_currentJob, SIGNAL(result(KJob *)), this, SLOT(jobFinished(KJob *)));
}
-
void OpenSearchManager::requestSuggestion(const QString &searchText)
{
if (!m_activeEngine)
@@ -135,7 +147,7 @@ void OpenSearchManager::requestSuggestion(const QString &searchText)
// if we want in any case lets it finish its previous job we can just return here.
idleJob();
}
-
+
_typedText = searchText;
KUrl url = m_activeEngine->suggestionsUrl(searchText);
@@ -163,7 +175,7 @@ void OpenSearchManager::jobFinished(KJob *job)
m_state = IDLE;
return; // just silently return
}
-
+
if (m_state == REQ_SUGGESTION)
{
const ResponseList suggestionsList = m_activeEngine->parseSuggestion(m_jobData);
@@ -184,40 +196,144 @@ void OpenSearchManager::jobFinished(KJob *job)
OpenSearchEngine *engine = reader.read(m_jobData);
if (engine)
{
- m_enginesMap.insert(engine->name(), engine);
- QString path = KGlobal::dirs()->findResource("data", "rekonq/opensearch/");
- QString fileName = trimmedEngineName(engine->name());
- QFile file(path + fileName + ".xml");
- OpenSearchWriter writer;
- writer.write(&file, engine);
+ m_engineCache.insert(engine->name(), engine);
+ m_engines.insert(m_jobUrl, trimmedEngineName(engine->name()));
+ saveEngines();
+
+ QString path;
+ if (engine->providesSuggestions()) //save opensearch description only if it provides suggestions
+ {
+ OpenSearchWriter writer;
+ path = KGlobal::dirs()->findResource("data", "rekonq/opensearch/");
+ QFile file(path + trimmedEngineName(engine->name()) + ".xml");
+ writer.write(&file, engine);
+ }
QString searchUrl = OpenSearchEngine::parseTemplate("\\{@}", engine->searchUrlTemplate());
m_currentJob = NULL;
- emit openSearchEngineAdded(engine->name(), searchUrl, fileName);
+
+ path = KGlobal::mainComponent().dirs()->saveLocation("services", "searchproviders/");
+ KConfig _service(path + trimmedEngineName(engine->name()) + ".desktop", KConfig::SimpleConfig);
+ KConfigGroup service(&_service, "Desktop Entry");
+ service.writeEntry("Type", "Service");
+ service.writeEntry("ServiceTypes", "SearchProvider");
+ service.writeEntry("Name", engine->name());
+ service.writeEntry("Query", searchUrl);
+ service.writeEntry("Keys", m_shortcut);
+ // TODO charset
+ service.writeEntry("Charset", "" /* provider->charset() */);
+ // we might be overwriting a hidden entry
+ service.writeEntry("Hidden", false);
+ service.sync();
+
+ // Update filters in running applications...
+ QDBusMessage msg = QDBusMessage::createSignal("/", "org.kde.KUriFilterPlugin", "configure");
+ QDBusConnection::sessionBus().send(msg);
+
+ emit openSearchEngineAdded(engine->name(), searchUrl, m_shortcut);
}
else
{
kFatal() << "Error while adding new open search engine";
}
-
+
idleJob();
}
}
+void OpenSearchManager::loadEngines()
+{
+ QFile file(KStandardDirs::locate("appdata", "opensearch/db_opensearch.json"));
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ {
+ kDebug() << "opensearch db cannot be read";
+ return;
+ }
+
+ QString fileContent = QString::fromUtf8(file.readAll());
+ QScriptEngine reader;
+ if (!reader.canEvaluate(fileContent))
+ {
+ kDebug() << "opensearch db cannot be read";
+ return;
+ }
+
+ QScriptValue responseParts = reader.evaluate(fileContent);
+ QVariantList list;
+ qScriptValueToSequence(responseParts, list);
+ QStringList l;
+ Q_FOREACH(const QVariant &e, list)
+ {
+ l=e.toStringList();
+ m_engines.insert(KUrl(l.first()),l.last());
+ }
+ file.close();
+}
+
+
+void OpenSearchManager::saveEngines()
+{
+ QFile file(KStandardDirs::locate("appdata", "opensearch/db_opensearch.json"));
+ if (!file.open(QIODevice::WriteOnly))
+ {
+ kDebug() << "opensearch db cannot be writen";
+ return;
+ }
+ QTextStream out(&file);
+ out << "[";
+ int i=0;
+ QList<KUrl> urls = m_engines.keys();
+ Q_FOREACH(const KUrl &url, urls)
+ {
+ out << "[\"" << url.url() << "\",\"" << m_engines.value(url) << "\"]";
+ i++;
+ if (i != urls.size())
+ {
+ out << ",\n";
+ }
+ }
+ out << "]\n";
+ file.close();
+}
+
+
+void OpenSearchManager::removeDeletedEngines()
+{
+ KService::Ptr service;
+ Q_FOREACH(const KUrl &url, m_engines.keys())
+ {
+ service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(m_engines.value(url)));
+ if (!service)
+ {
+ QString path = KStandardDirs::locate("appdata", "opensearch/" + trimmedEngineName(m_engines.value(url)) + ".xml");
+ QFile::remove(path + trimmedEngineName(m_engines.value(url)) + ".xml");
+ m_engines.remove(url);
+ }
+ }
+ saveEngines();
+}
+
+
+bool OpenSearchManager::engineExists(const KUrl &url)
+{
+ return m_engines.contains(url);
+}
+
+
QString OpenSearchManager::trimmedEngineName(const QString &engineName) const
{
QString trimmed;
QString::ConstIterator constIter = engineName.constBegin();
- while (constIter != engineName.constEnd())
+ while (constIter != engineName.constEnd())
{
- if (constIter->isSpace())
+ if (constIter->isSpace())
{
- trimmed.append('-');
+ trimmed.append('_');
}
- else
+ else
{
- if (*constIter != '.')
+ if (*constIter != '.')
{
trimmed.append(constIter->toLower());
}
diff --git a/src/opensearch/opensearchmanager.h b/src/opensearch/opensearchmanager.h
index 4f42b4a8..df8e5367 100644
--- a/src/opensearch/opensearchmanager.h
+++ b/src/opensearch/opensearchmanager.h
@@ -39,6 +39,7 @@
// Qt Includes
#include <QtCore/QObject>
+#include <QFile>
// Forward Declarations
class OpenSearchEngine;
@@ -59,7 +60,7 @@ class OpenSearchManager : public QObject
REQ_DESCRIPTION,
IDLE
};
-
+
public:
/**
* Constructor
@@ -76,7 +77,7 @@ public:
*/
bool isSuggestionAvailable();
- void addOpenSearchEngine(const KUrl &url, const QString &title);
+ bool engineExists(const KUrl &url);
public Q_SLOTS:
/**
@@ -85,6 +86,8 @@ public Q_SLOTS:
* @param searchText the text to be queried to the suggestion service
*/
void requestSuggestion(const QString &searchText);
+ void addOpenSearchEngine(const KUrl &url, const QString &title, const QString &shortcut);
+ void removeDeletedEngines();
private Q_SLOTS:
void dataReceived(KIO::Job *job, const QByteArray &data);
@@ -96,18 +99,23 @@ Q_SIGNALS:
private:
QString trimmedEngineName(const QString &engineName) const;
-
+ void loadEngines();
+ void saveEngines();
void idleJob();
-
+
// QString substitutueSearchText(const QString &searchText, const QString &requestURL) const;
QByteArray m_jobData;
- QMap<QString, OpenSearchEngine*> m_enginesMap;
+ QMap<QString, OpenSearchEngine*> m_engineCache;
+ QMap<KUrl, QString> m_engines;
+
OpenSearchEngine *m_activeEngine;
STATE m_state;
-
+
KIO::TransferJob *m_currentJob;
+ KUrl m_jobUrl;
QString _typedText;
+ QString m_shortcut;
};
#endif // OPENSEARCHMANAGER_H
diff --git a/src/opensearch/suggestionparser.cpp b/src/opensearch/suggestionparser.cpp
index 4ed13e16..b2ecd009 100644
--- a/src/opensearch/suggestionparser.cpp
+++ b/src/opensearch/suggestionparser.cpp
@@ -35,7 +35,7 @@
ResponseList SuggestionParser::parse(const QByteArray &)
{
- return ResponseList();
+ return ResponseList();
}
@@ -47,7 +47,7 @@ SuggestionParser::~SuggestionParser()
ResponseList XMLParser::parse(const QByteArray &resp)
{
ResponseList rlist;
-
+
m_reader.clear();
m_reader.addData(resp);
@@ -73,16 +73,19 @@ ResponseList XMLParser::parse(const QByteArray &resp)
{
if(m_reader.isStartElement())
{
+
if (m_reader.name() == QL1S("Text"))
title = m_reader.readElementText();
if (m_reader.name() == QL1S("Url"))
url = m_reader.readElementText();
+
if (m_reader.name() == QL1S("Image"))
{
image = m_reader.attributes().value("source").toString();
image_width = m_reader.attributes().value("width").toString().toInt();
image_height = m_reader.attributes().value("height").toString().toInt();
}
+
if (m_reader.name() == QL1S("Description"))
description = m_reader.readElementText();
}
@@ -94,7 +97,7 @@ ResponseList XMLParser::parse(const QByteArray &resp)
m_reader.readNext();
}
-
+
return rlist;
}
@@ -103,23 +106,23 @@ ResponseList JSONParser::parse(const QByteArray &resp)
{
QString response = QString::fromLocal8Bit(resp);
response = response.trimmed();
-
- if (response.isEmpty())
+
+ if (response.isEmpty())
{
kDebug() << "RESPONSE IS EMPTY";
return ResponseList();
}
-
- if (!response.startsWith(QL1C('['))
+
+ if (!response.startsWith(QL1C('['))
|| !response.endsWith(QL1C(']'))
- )
+ )
{
kDebug() << "RESPONSE is NOT well FORMED";
return ResponseList();
}
// Evaluate the JSON response using QtScript.
- if (!m_reader.canEvaluate(response))
+ if (!m_reader.canEvaluate(response))
{
kDebug() << "m_reader cannot evaluate the response";
return ResponseList();
@@ -127,7 +130,7 @@ ResponseList JSONParser::parse(const QByteArray &resp)
QScriptValue responseParts = m_reader.evaluate(response);
- if (!responseParts.property(1).isArray())
+ if (!responseParts.property(1).isArray())
{
kDebug() << "RESPONSE is not an array";
return ResponseList();
@@ -141,6 +144,6 @@ ResponseList JSONParser::parse(const QByteArray &resp)
{
rlist << Response(s);
}
-
+
return rlist;
}