diff options
author | Andrea Diamantini <adjam7@gmail.com> | 2010-12-21 21:59:23 +0100 |
---|---|---|
committer | Andrea Diamantini <adjam7@gmail.com> | 2010-12-21 21:59:23 +0100 |
commit | 925725bfcf0f3ffba5107949bc8424e1fd6d1902 (patch) | |
tree | ee10e2c10e3ec63b0977661cfbc0ef69ad98002a /src/opensearch | |
parent | Adding a tab list menu entry showing all open tabs. (diff) | |
download | rekonq-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.cpp | 6 | ||||
-rw-r--r-- | src/opensearch/opensearchmanager.cpp | 166 | ||||
-rw-r--r-- | src/opensearch/opensearchmanager.h | 20 | ||||
-rw-r--r-- | src/opensearch/suggestionparser.cpp | 25 |
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; } |