From e9d099f4c5efa41fafd16408f13400cb37616f18 Mon Sep 17 00:00:00 2001 From: lionelc Date: Thu, 12 Aug 2010 18:31:16 +0200 Subject: introduce a new SuggestionListItem introduce an opensearch engine --- src/search/opensearchengine.cpp | 229 +++++++++++++++++++++++++++++++++++++++ src/search/opensearchengine.h | 93 ++++++++++++++++ src/search/opensearchmanager.cpp | 175 ++++++++++++++++++++++++++++++ src/search/opensearchmanager.h | 88 +++++++++++++++ src/search/opensearchreader.cpp | 133 +++++++++++++++++++++++ src/search/opensearchreader.h | 39 +++++++ src/search/opensearchwriter.cpp | 110 +++++++++++++++++++ src/search/opensearchwriter.h | 41 +++++++ src/search/searchengine.cpp | 153 ++++++++++++++++++++++++++ src/search/searchengine.h | 62 +++++++++++ 10 files changed, 1123 insertions(+) create mode 100644 src/search/opensearchengine.cpp create mode 100644 src/search/opensearchengine.h create mode 100644 src/search/opensearchmanager.cpp create mode 100644 src/search/opensearchmanager.h create mode 100644 src/search/opensearchreader.cpp create mode 100644 src/search/opensearchreader.h create mode 100644 src/search/opensearchwriter.cpp create mode 100644 src/search/opensearchwriter.h create mode 100644 src/search/searchengine.cpp create mode 100644 src/search/searchengine.h (limited to 'src/search') diff --git a/src/search/opensearchengine.cpp b/src/search/opensearchengine.cpp new file mode 100644 index 00000000..a7bcf11e --- /dev/null +++ b/src/search/opensearchengine.cpp @@ -0,0 +1,229 @@ +/* + * Copyright 2009 Jakub Wieczorek + * Copyright 2009 Christian Franke + * Copyright 2009 Fredy Yanardi + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "opensearchengine.h" + +#include +#include +#include +#include + +OpenSearchEngine::OpenSearchEngine(QObject *) + : m_scriptEngine(0) +{ +} + +OpenSearchEngine::~OpenSearchEngine() +{ + if (m_scriptEngine) { + delete m_scriptEngine; + } +} + +QString OpenSearchEngine::parseTemplate(const QString &searchTerm, const QString &searchTemplate) +{ + QString result = searchTemplate; + result.replace(QLatin1String("{count}"), QLatin1String("20")); + result.replace(QLatin1String("{startIndex}"), QLatin1String("0")); + result.replace(QLatin1String("{startPage}"), QLatin1String("0")); + // TODO - get setting from KDE + result.replace(QLatin1String("{language}"), QLatin1String("en-US")); + result.replace(QLatin1String("{inputEncoding}"), QLatin1String("UTF-8")); + result.replace(QLatin1String("{outputEncoding}"), QLatin1String("UTF-8")); + result.replace(QLatin1String("{searchTerms}"), searchTerm); + + return result; +} + +QString OpenSearchEngine::name() const +{ + return m_name; +} + +void OpenSearchEngine::setName(const QString &name) +{ + m_name = name; +} + +QString OpenSearchEngine::description() const +{ + return m_description; +} + +void OpenSearchEngine::setDescription(const QString &description) +{ + m_description = description; +} + +QString OpenSearchEngine::searchUrlTemplate() const +{ + return m_searchUrlTemplate; +} + +void OpenSearchEngine::setSearchUrlTemplate(const QString &searchUrlTemplate) +{ + m_searchUrlTemplate = searchUrlTemplate; +} + +KUrl OpenSearchEngine::searchUrl(const QString &searchTerm) const +{ + if (m_searchUrlTemplate.isEmpty()) { + return KUrl(); + } + + KUrl retVal = KUrl::fromEncoded(parseTemplate(searchTerm, m_searchUrlTemplate).toUtf8()); + + QList::const_iterator end = m_searchParameters.constEnd(); + QList::const_iterator i = m_searchParameters.constBegin(); + for (; i != end; ++i) { + retVal.addQueryItem(i->first, parseTemplate(searchTerm, i->second)); + } + + return retVal; +} + +bool OpenSearchEngine::providesSuggestions() const +{ + return !m_suggestionsUrlTemplate.isEmpty(); +} + +QString OpenSearchEngine::suggestionsUrlTemplate() const +{ + return m_suggestionsUrlTemplate; +} + +void OpenSearchEngine::setSuggestionsUrlTemplate(const QString &suggestionsUrlTemplate) +{ + m_suggestionsUrlTemplate = suggestionsUrlTemplate; +} + +KUrl OpenSearchEngine::suggestionsUrl(const QString &searchTerm) const +{ + if (m_suggestionsUrlTemplate.isEmpty()) { + return KUrl(); + } + + KUrl retVal = KUrl::fromEncoded(parseTemplate(searchTerm, m_suggestionsUrlTemplate).toUtf8()); + + QList::const_iterator end = m_suggestionsParameters.constEnd(); + QList::const_iterator i = m_suggestionsParameters.constBegin(); + for (; i != end; ++i) { + retVal.addQueryItem(i->first, parseTemplate(searchTerm, i->second)); + } + + return retVal; +} + +QList OpenSearchEngine::searchParameters() const +{ + return m_searchParameters; +} + +void OpenSearchEngine::setSearchParameters(const QList &searchParameters) +{ + m_searchParameters = searchParameters; +} + +QList OpenSearchEngine::suggestionsParameters() const +{ + return m_suggestionsParameters; +} + +void OpenSearchEngine::setSuggestionsParameters(const QList &suggestionsParameters) +{ + m_suggestionsParameters = suggestionsParameters; +} + +QString OpenSearchEngine::imageUrl() const +{ + return m_imageUrl; +} + +void OpenSearchEngine::setImageUrl(const QString &imageUrl) +{ + m_imageUrl = imageUrl; +} + +QImage OpenSearchEngine::image() const +{ + return m_image; +} + +void OpenSearchEngine::setImage(const QImage &image) +{ + m_image = image; +} + +bool OpenSearchEngine::isValid() const +{ + return (!m_name.isEmpty() && !m_searchUrlTemplate.isEmpty()); +} + +bool OpenSearchEngine::operator==(const OpenSearchEngine &other) const +{ + return (m_name == other.m_name + && m_description == other.m_description + && m_imageUrl == other.m_imageUrl + && m_searchUrlTemplate == other.m_searchUrlTemplate + && m_suggestionsUrlTemplate == other.m_suggestionsUrlTemplate + && m_searchParameters == other.m_searchParameters + && m_suggestionsParameters == other.m_suggestionsParameters); +} + +bool OpenSearchEngine::operator<(const OpenSearchEngine &other) const +{ + return (m_name < other.m_name); +} + +QStringList OpenSearchEngine::parseSuggestion(const QByteArray &resp) +{ + QString response(resp); + response = response.trimmed(); + + if (response.isEmpty()) { + return QStringList(); + } + + if (!response.startsWith(QLatin1Char('[')) || !response.endsWith(QLatin1Char(']'))) { + return QStringList(); + } + + if (!m_scriptEngine) { + m_scriptEngine = new QScriptEngine(); + } + + // Evaluate the JSON response using QtScript. + if (!m_scriptEngine->canEvaluate(response)) { + return QStringList(); + } + + QScriptValue responseParts = m_scriptEngine->evaluate(response); + + if (!responseParts.property(1).isArray()) { + return QStringList(); + } + + QStringList suggestionsList; + qScriptValueToSequence(responseParts.property(1), suggestionsList); + + return suggestionsList; +} + diff --git a/src/search/opensearchengine.h b/src/search/opensearchengine.h new file mode 100644 index 00000000..c981f443 --- /dev/null +++ b/src/search/opensearchengine.h @@ -0,0 +1,93 @@ +/* + * Copyright 2009 Jakub Wieczorek + * Copyright 2009 Christian Franke + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef OPENSEARCHENGINE_H +#define OPENSEARCHENGINE_H + +#include +#include + +#include + +class QNetworkAccessManager; +class QNetworkReply; +class QScriptEngine; + +class OpenSearchEngine +{ +public: + typedef QPair Parameter; + + OpenSearchEngine(QObject *parent = 0); + ~OpenSearchEngine(); + + QString name() const; + void setName(const QString &name); + + QString description() const; + void setDescription(const QString &description); + + QString searchUrlTemplate() const; + void setSearchUrlTemplate(const QString &searchUrl); + KUrl searchUrl(const QString &searchTerm) const; + + bool providesSuggestions() const; + + QString suggestionsUrlTemplate() const; + void setSuggestionsUrlTemplate(const QString &suggestionsUrl); + KUrl suggestionsUrl(const QString &searchTerm) const; + + QList searchParameters() const; + void setSearchParameters(const QList &searchParameters); + + QList suggestionsParameters() const; + void setSuggestionsParameters(const QList &suggestionsParameters); + + QString imageUrl() const; + void setImageUrl(const QString &url); + + QImage image() const; + void setImage(const QImage &image); + + bool isValid() const; + + bool operator==(const OpenSearchEngine &other) const; + bool operator<(const OpenSearchEngine &other) const; + + QStringList parseSuggestion(const QByteArray &response); + + static QString parseTemplate(const QString &searchTerm, const QString &searchTemplate); + +private: + QString m_name; + QString m_description; + + QString m_imageUrl; + QImage m_image; + + QString m_searchUrlTemplate; + QString m_suggestionsUrlTemplate; + QList m_searchParameters; + QList m_suggestionsParameters; + + QScriptEngine *m_scriptEngine; +}; + +#endif // OPENSEARCHENGINE_H diff --git a/src/search/opensearchmanager.cpp b/src/search/opensearchmanager.cpp new file mode 100644 index 00000000..6e37db77 --- /dev/null +++ b/src/search/opensearchmanager.cpp @@ -0,0 +1,175 @@ +/* This file is part of the KDE project + * Copyright (C) 2009 Fredy Yanardi + * + * This library 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 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 "opensearchmanager.h" + +#include + +#include +#include +#include +#include +#include + +#include "opensearchengine.h" +#include "opensearchreader.h" +#include "opensearchwriter.h" + +OpenSearchManager::OpenSearchManager(QObject *parent) + : QObject(parent) + , m_activeEngine(0) +{ + m_state = IDLE; +} + +OpenSearchManager::~OpenSearchManager() { + qDeleteAll(m_enginesMap.values()); + m_enginesMap.clear(); +} + +void OpenSearchManager::setSearchProvider(const QString &searchProvider) +{ + m_activeEngine = 0; + + if (!m_enginesMap.contains(searchProvider)) { + const QString fileName = KGlobal::dirs()->findResource("data", "konqueror/opensearch/" + searchProvider + ".xml"); + if (fileName.isEmpty()) { + return; + } + QFile file(fileName); + + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + kWarning(1202) << "Cannot open opensearch description file: " + fileName; + return; + } + + OpenSearchReader reader; + OpenSearchEngine *engine = reader.read(&file); + + if (engine) { + m_enginesMap.insert(searchProvider, engine); + } + else { + return; + } + } + + m_activeEngine = m_enginesMap.value(searchProvider); +} + +bool OpenSearchManager::isSuggestionAvailable() +{ + return m_activeEngine != 0; +} + +void OpenSearchManager::addOpenSearchEngine(const KUrl &url, const QString &title) +{ + Q_UNUSED(title); + + m_jobData.clear(); + + if (m_state != IDLE) { + // TODO: cancel job + } + + m_state = REQ_DESCRIPTION; + KIO::TransferJob *job = KIO::get(url, KIO::NoReload, KIO::HideProgressInfo); + connect(job, SIGNAL(data(KIO::Job *, const QByteArray &)), + this, SLOT(dataReceived(KIO::Job *, const QByteArray &))); + connect(job, SIGNAL(result(KJob *)), SLOT(jobFinished(KJob *))); +} + +void OpenSearchManager::requestSuggestion(const QString &searchText) +{ + if (!m_activeEngine) { + return; + } + + if (m_state != IDLE) { + // TODO: cancel job + } + m_state = REQ_SUGGESTION; + + KUrl url = m_activeEngine->suggestionsUrl(searchText); + kDebug(1202) << "Requesting for suggestions: " << url.url(); + m_jobData.clear(); + KIO::TransferJob *job = KIO::get(url, KIO::NoReload, KIO::HideProgressInfo); + connect(job, SIGNAL(data(KIO::Job *, const QByteArray &)), + this, SLOT(dataReceived(KIO::Job *, const QByteArray &))); + connect(job, SIGNAL(result(KJob *)), SLOT(jobFinished(KJob *))); +} + +void OpenSearchManager::dataReceived(KIO::Job *job, const QByteArray &data) +{ + Q_UNUSED(job); + m_jobData.append(data); +} + +void OpenSearchManager::jobFinished(KJob *job) +{ + if (job->error()) { + return; // just silently return + } + + if (m_state == REQ_SUGGESTION) { + const QStringList suggestionsList = m_activeEngine->parseSuggestion(m_jobData); + kDebug(1202) << "Received suggestion from " << m_activeEngine->name() << ": " << suggestionsList; + + emit suggestionReceived(suggestionsList); + } + else if (m_state == REQ_DESCRIPTION) { + OpenSearchReader reader; + OpenSearchEngine *engine = reader.read(m_jobData); + if (engine) { + m_enginesMap.insert(engine->name(), engine); + QString path = KGlobal::dirs()->findResource("data", "konqueror/opensearch/"); + QString fileName = trimmedEngineName(engine->name()); + QFile file(path + fileName + ".xml"); + OpenSearchWriter writer; + writer.write(&file, engine); + + QString searchUrl = OpenSearchEngine::parseTemplate("\\{@}", engine->searchUrlTemplate()); + emit openSearchEngineAdded(engine->name(), searchUrl, fileName); + } + else { + kFatal() << "Error while adding new open search engine"; + } + } +} + +QString OpenSearchManager::trimmedEngineName(const QString &engineName) const +{ + QString trimmed; + QString::ConstIterator constIter = engineName.constBegin(); + while (constIter != engineName.constEnd()) { + if (constIter->isSpace()) { + trimmed.append('-'); + } + else if (*constIter != '.') { + trimmed.append(constIter->toLower()); + } + constIter++; + } + + return trimmed; +} + +#include "opensearchmanager.moc" + + diff --git a/src/search/opensearchmanager.h b/src/search/opensearchmanager.h new file mode 100644 index 00000000..59e7e6b2 --- /dev/null +++ b/src/search/opensearchmanager.h @@ -0,0 +1,88 @@ +/* This file is part of the KDE project + * Copyright (C) 2009 Fredy Yanardi + * + * This library 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 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 OPENSEARCHMANAGER_H +#define OPENSEARCHMANAGER_H + +#include +#include + +class SuggestionEngine; + +class OpenSearchEngine; + +/** + * This class acts as a proxy between the SearchBar plugin and the individual suggestion engine. + * This class has a map of all available engines, and route the suggestion request to the correct engine + */ +class OpenSearchManager : public QObject +{ + Q_OBJECT + + enum STATE { + REQ_SUGGESTION, + REQ_DESCRIPTION, + IDLE + }; +public: + /** + * Constructor + */ + explicit OpenSearchManager(QObject *parent = 0); + + virtual ~OpenSearchManager(); + + void setSearchProvider(const QString &searchProvider); + + /** + * Check whether a search suggestion engine is available for the given search provider + * @param searchProvider the queried search provider + */ + bool isSuggestionAvailable(); + + void addOpenSearchEngine(const KUrl &url, const QString &title); + +public slots: + /** + * Ask the specific suggestion engine to request for suggestion for the search text + * @param searchProvider the search provider that provides the suggestion service + * @param searchText the text to be queried to the suggestion service + */ + void requestSuggestion(const QString &searchProvider); + +private slots: + void dataReceived(KIO::Job *job, const QByteArray &data); + void jobFinished(KJob *job); + +signals: + void suggestionReceived(const QStringList &suggestion); + void openSearchEngineAdded(const QString &name, const QString &searchUrl, const QString &fileName); + +private: + QString trimmedEngineName(const QString &engineName) const; + + // QString substitutueSearchText(const QString &searchText, const QString &requestURL) const; + QByteArray m_jobData; + QMap m_enginesMap; + OpenSearchEngine *m_activeEngine; + STATE m_state; +}; + +#endif // OPENSEARCHMANAGER_H + diff --git a/src/search/opensearchreader.cpp b/src/search/opensearchreader.cpp new file mode 100644 index 00000000..0aa0f91f --- /dev/null +++ b/src/search/opensearchreader.cpp @@ -0,0 +1,133 @@ +/* + * Copyright 2009 Jakub Wieczorek + * Copyright 2009 Fredy Yanardi + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "opensearchreader.h" + +#include "opensearchengine.h" + +#include + +OpenSearchReader::OpenSearchReader() + : QXmlStreamReader() +{ +} + +OpenSearchEngine *OpenSearchReader::read(const QByteArray &data) +{ + clear(); + + addData(data); + + return read(); +} + +OpenSearchEngine *OpenSearchReader::read(QIODevice *device) +{ + clear(); + + if (!device->isOpen()) { + device->open(QIODevice::ReadOnly); + } + + setDevice(device); + return read(); +} + +OpenSearchEngine *OpenSearchReader::read() +{ + OpenSearchEngine *engine = new OpenSearchEngine(); + + while (!isStartElement() && !atEnd()) { + readNext(); + } + + if (name() != QLatin1String("OpenSearchDescription") + || namespaceUri() != QLatin1String("http://a9.com/-/spec/opensearch/1.1/")) { + raiseError(QObject::tr("The file is not an OpenSearch 1.1 file.")); + return engine; + } + + while (!(isEndElement() && name() == QLatin1String("OpenSearchDescription")) && !atEnd()) { + readNext(); + + if (!isStartElement()) { + continue; + } + + if (name() == QLatin1String("ShortName")) { + engine->setName(readElementText()); + } + else if (name() == QLatin1String("Description")) { + engine->setDescription(readElementText()); + } + else if (name() == QLatin1String("Url")) { + QString type = attributes().value(QLatin1String("type")).toString(); + QString url = attributes().value(QLatin1String("template")).toString(); + + if (url.isEmpty()) + continue; + + QList parameters; + + readNext(); + + while (!(isEndElement() && name() == QLatin1String("Url"))) { + if (!isStartElement() || (name() != QLatin1String("Param") && name() != QLatin1String("Parameter"))) { + readNext(); + continue; + } + + QString key = attributes().value(QLatin1String("name")).toString(); + QString value = attributes().value(QLatin1String("value")).toString(); + + if (!key.isEmpty() && !value.isEmpty()) { + parameters.append(OpenSearchEngine::Parameter(key, value)); + } + + while (!isEndElement()) { + readNext(); + } + } + + if (type == QLatin1String("application/x-suggestions+json")) { + engine->setSuggestionsUrlTemplate(url); + engine->setSuggestionsParameters(parameters); + } + else { + engine->setSearchUrlTemplate(url); + engine->setSearchParameters(parameters); + } + } + else if (name() == QLatin1String("Image")) { + engine->setImageUrl(readElementText()); + } + + if (!engine->name().isEmpty() + && !engine->description().isEmpty() + && !engine->suggestionsUrlTemplate().isEmpty() + && !engine->searchUrlTemplate().isEmpty() + && !engine->imageUrl().isEmpty()) { + break; + } + } + + return engine; +} + diff --git a/src/search/opensearchreader.h b/src/search/opensearchreader.h new file mode 100644 index 00000000..5481881a --- /dev/null +++ b/src/search/opensearchreader.h @@ -0,0 +1,39 @@ +/* + * Copyright 2009 Jakub Wieczorek + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef OPENSEARCHREADER_H +#define OPENSEARCHREADER_H + +#include + +class OpenSearchEngine; + +class OpenSearchReader : public QXmlStreamReader +{ +public: + OpenSearchReader(); + + OpenSearchEngine *read(const QByteArray &data); + OpenSearchEngine *read(QIODevice *device); + +private: + OpenSearchEngine *read(); +}; + +#endif // OPENSEARCHREADER_H diff --git a/src/search/opensearchwriter.cpp b/src/search/opensearchwriter.cpp new file mode 100644 index 00000000..a18ce0e2 --- /dev/null +++ b/src/search/opensearchwriter.cpp @@ -0,0 +1,110 @@ +/* + * Copyright 2009 Jakub Wieczorek + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "opensearchwriter.h" + +#include "opensearchengine.h" + +#include + +#include + +OpenSearchWriter::OpenSearchWriter() + : QXmlStreamWriter() +{ + setAutoFormatting(true); +} + +bool OpenSearchWriter::write(QIODevice *device, OpenSearchEngine *engine) +{ + if (!engine) + return false; + + if (!device->isOpen()) + device->open(QIODevice::WriteOnly); + + setDevice(device); + write(engine); + return true; +} + +void OpenSearchWriter::write(OpenSearchEngine *engine) +{ + writeStartDocument(); + writeStartElement(QLatin1String("OpenSearchDescription")); + writeDefaultNamespace(QLatin1String("http://a9.com/-/spec/opensearch/1.1/")); + + if (!engine->name().isEmpty()) { + writeTextElement(QLatin1String("ShortName"), engine->name()); + } + + if (!engine->description().isEmpty()) { + writeTextElement(QLatin1String("Description"), engine->description()); + } + + if (!engine->searchUrlTemplate().isEmpty()) { + writeStartElement(QLatin1String("Url")); + writeAttribute(QLatin1String("method"), QLatin1String("get")); + writeAttribute(QLatin1String("template"), engine->searchUrlTemplate()); + + if (!engine->searchParameters().empty()) { + writeNamespace(QLatin1String("http://a9.com/-/spec/opensearch/extensions/parameters/1.0/"), QLatin1String("p")); + + QList::const_iterator end = engine->searchParameters().constEnd(); + QList::const_iterator i = engine->searchParameters().constBegin(); + for (; i != end; ++i) { + writeStartElement(QLatin1String("p:Parameter")); + writeAttribute(QLatin1String("name"), i->first); + writeAttribute(QLatin1String("value"), i->second); + writeEndElement(); + } + } + + writeEndElement(); + } + + if (!engine->suggestionsUrlTemplate().isEmpty()) { + writeStartElement(QLatin1String("Url")); + writeAttribute(QLatin1String("method"), QLatin1String("get")); + writeAttribute(QLatin1String("type"), QLatin1String("application/x-suggestions+json")); + writeAttribute(QLatin1String("template"), engine->suggestionsUrlTemplate()); + + if (!engine->suggestionsParameters().empty()) { + writeNamespace(QLatin1String("http://a9.com/-/spec/opensearch/extensions/parameters/1.0/"), QLatin1String("p")); + + QList::const_iterator end = engine->suggestionsParameters().constEnd(); + QList::const_iterator i = engine->suggestionsParameters().constBegin(); + for (; i != end; ++i) { + writeStartElement(QLatin1String("p:Parameter")); + writeAttribute(QLatin1String("name"), i->first); + writeAttribute(QLatin1String("value"), i->second); + writeEndElement(); + } + } + + writeEndElement(); + } + + if (!engine->imageUrl().isEmpty()) + writeTextElement(QLatin1String("Image"), engine->imageUrl()); + + writeEndElement(); + writeEndDocument(); +} + diff --git a/src/search/opensearchwriter.h b/src/search/opensearchwriter.h new file mode 100644 index 00000000..b089c4bb --- /dev/null +++ b/src/search/opensearchwriter.h @@ -0,0 +1,41 @@ +/* + * Copyright 2009 Jakub Wieczorek + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef OPENSEARCHWRITER_H +#define OPENSEARCHWRITER_H + +#include + +class QIODevice; + +class OpenSearchEngine; + +class OpenSearchWriter : public QXmlStreamWriter +{ +public: + OpenSearchWriter(); + + bool write(QIODevice *device, OpenSearchEngine *engine); + +private: + void write(OpenSearchEngine *engine); +}; + +#endif + diff --git a/src/search/searchengine.cpp b/src/search/searchengine.cpp new file mode 100644 index 00000000..0a66bb64 --- /dev/null +++ b/src/search/searchengine.cpp @@ -0,0 +1,153 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2008-2010 by Andrea Diamantini +* Copyright (C) 2009-2010 by Lionel Chauvin +* +* +* 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) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* 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 . +* +* ============================================================ */ + + +//local includes +#include "searchengine.h" + +// Auto Includes +#include "rekonq.h" + +//KDE includes +#include +#include + + +QString SearchEngine::m_delimiter = ""; + + +QString SearchEngine::delimiter() +{ + if (m_delimiter == "") loadDelimiter(); + return m_delimiter; +} + + +void SearchEngine::loadDelimiter() +{ + KConfig config("kuriikwsfilterrc"); //Share with konqueror + KConfigGroup cg = config.group("General"); + m_delimiter = cg.readEntry("KeywordDelimiter", ":"); +} + + +KService::Ptr SearchEngine::m_defaultWS; + + +KService::Ptr SearchEngine::defaultWS() +{ + if (!m_defaultWS) loadDefaultWS(); + return m_defaultWS; +} + + +void SearchEngine::loadDefaultWS() +{ + KConfig config("kuriikwsfilterrc"); //Share with konqueror + KConfigGroup cg = config.group("General"); + QString d = cg.readEntry("DefaultSearchEngine", "google"); + m_defaultWS = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(d)); +} + + +KService::Ptr SearchEngine::fromString(QString text) +{ + KService::List providers = KServiceTypeTrader::self()->query("SearchProvider"); + int i = 0; + bool found = false; + KService::Ptr service; + while (!found && i < providers.size()) + { + QStringList list = providers.at(i)->property("Keys").toStringList(); + foreach(const QString &key, list) + { + const QString searchPrefix = key + delimiter(); + if (text.startsWith(searchPrefix)) + { + service = providers.at(i); + found = true; + } + } + i++; + } + + return service; +} + + +QString SearchEngine::buildQuery(KService::Ptr engine, QString text) +{ + QString query = engine->property("Query").toString(); + query = query.replace("\\{@}", KUrl::toPercentEncoding(text)); + return query; +} + + +KService::List SearchEngine::m_favorites; + + +KService::List SearchEngine::favorites() +{ + if (m_favorites.isEmpty()) loadFavorites(); + return m_favorites; +} + +void SearchEngine::loadFavorites() +{ + KConfig config("kuriikwsfilterrc"); //Share with konqueror + KConfigGroup cg = config.group("General"); + QStringList favoriteEngines; + favoriteEngines << "google"; //defaults + favoriteEngines = cg.readEntry("FavoriteSearchEngines", favoriteEngines); + + KService::List favorites; + KService::Ptr service; + foreach(const QString &engine, favoriteEngines) + { + service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(engine)); + if (service) + favorites << service; + } + + m_favorites = favorites; +} + + +KService::Ptr SearchEngine::defaultEngine() +{ + KConfig config("kuriikwsfilterrc"); //Share with konqueror + KConfigGroup cg = config.group("General"); + QString d = cg.readEntry("DefaultSearchEngine"); + KService::Ptr service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(d)); + if (!service) + { + d = QL1S("google"); + service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(d)); + } + + return service; + +} diff --git a/src/search/searchengine.h b/src/search/searchengine.h new file mode 100644 index 00000000..2e30e056 --- /dev/null +++ b/src/search/searchengine.h @@ -0,0 +1,62 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2008-2010 by Andrea Diamantini +* Copyright (C) 2009-2010 by Lionel Chauvin +* +* +* 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) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* 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 . +* +* ============================================================ */ + +#ifndef SEARCHENGINE_H +#define SEARCHENGINE_H + + +// Rekonq Includes +#include "rekonq_defines.h" + +// KDE Includes +#include + +//Qt Includes +#include + + +class SearchEngine +{ +public: + + static QString delimiter(); + static KService::Ptr defaultEngine(); + static KService::List favorites(); + static KService::Ptr fromString(QString text); + static QString buildQuery(KService::Ptr engine, QString text); + static KService::Ptr defaultWS(); + + static void loadDelimiter(); + static void loadFavorites(); + static void loadDefaultWS(); + +private: + static QString m_delimiter; + static KService::List m_favorites; + static KService::Ptr m_defaultWS; +}; + +#endif -- cgit v1.2.1