diff options
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; } |