From 86361af2d5d6be4e30910da8e2a1d8d26bb3d753 Mon Sep 17 00:00:00 2001 From: Andrea Diamantini Date: Wed, 29 Sep 2010 21:29:44 +0200 Subject: search --> opensearch dir --- src/opensearch/opensearchengine.cpp | 274 +++++++++++++++++++++++++++++++++++ src/opensearch/opensearchengine.h | 110 ++++++++++++++ src/opensearch/opensearchmanager.cpp | 234 ++++++++++++++++++++++++++++++ src/opensearch/opensearchmanager.h | 112 ++++++++++++++ src/opensearch/opensearchreader.cpp | 174 ++++++++++++++++++++++ src/opensearch/opensearchreader.h | 55 +++++++ src/opensearch/opensearchwriter.cpp | 134 +++++++++++++++++ src/opensearch/opensearchwriter.h | 56 +++++++ src/opensearch/searchengine.cpp | 157 ++++++++++++++++++++ src/opensearch/searchengine.h | 59 ++++++++ 10 files changed, 1365 insertions(+) create mode 100644 src/opensearch/opensearchengine.cpp create mode 100644 src/opensearch/opensearchengine.h create mode 100644 src/opensearch/opensearchmanager.cpp create mode 100644 src/opensearch/opensearchmanager.h create mode 100644 src/opensearch/opensearchreader.cpp create mode 100644 src/opensearch/opensearchreader.h create mode 100644 src/opensearch/opensearchwriter.cpp create mode 100644 src/opensearch/opensearchwriter.h create mode 100644 src/opensearch/searchengine.cpp create mode 100644 src/opensearch/searchengine.h (limited to 'src/opensearch') diff --git a/src/opensearch/opensearchengine.cpp b/src/opensearch/opensearchengine.cpp new file mode 100644 index 00000000..78e50980 --- /dev/null +++ b/src/opensearch/opensearchengine.cpp @@ -0,0 +1,274 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Jakub Wieczorek +* Copyright (C) 2009 by Christian Franke +* Copyright (C) 2009 by Fredy Yanardi +* Copyright (C) 2010 by Lionel Chauvin +* Copyright (C) 2010 by Andrea Diamantini +* +* +* 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 . +* +* ============================================================ */ + + +// Self Includes +#include "opensearchengine.h" + +// Qt Includes +#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(QL1S("{count}"), QL1S("20")); + result.replace(QL1S("{startIndex}"), QL1S("0")); + result.replace(QL1S("{startPage}"), QL1S("0")); + // TODO - get setting from KDE + result.replace(QL1S("{language}"), QL1S("en-US")); + result.replace(QL1S("{inputEncoding}"), QL1S("UTF-8")); + result.replace(QL1S("{outputEncoding}"), QL1S("UTF-8")); + result.replace(QL1S("{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 i; + for ( i = m_searchParameters.constBegin(); i != m_searchParameters.constEnd(); ++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 i; + for( i = m_suggestionsParameters.constBegin(); i != m_suggestionsParameters.constEnd(); ++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 = QString::fromLocal8Bit(resp); + response = response.trimmed(); + + if (response.isEmpty()) + { + return QStringList(); + } + + if ( !response.startsWith(QL1C('[')) + || !response.endsWith(QL1C(']')) + ) + { + 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/opensearch/opensearchengine.h b/src/opensearch/opensearchengine.h new file mode 100644 index 00000000..f2329624 --- /dev/null +++ b/src/opensearch/opensearchengine.h @@ -0,0 +1,110 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Jakub Wieczorek +* Copyright (C) 2009 by Christian Franke +* Copyright (C) 2010 by Lionel Chauvin +* Copyright (C) 2010 by Andrea Diamantini +* +* +* 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 OPENSEARCHENGINE_H +#define OPENSEARCHENGINE_H + + +// Rekonq Includes +#include "rekonq_defines.h" + +// KDE Includes +#include + +// Qt Includes +#include +#include + +// Forward Declarations +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/opensearch/opensearchmanager.cpp b/src/opensearch/opensearchmanager.cpp new file mode 100644 index 00000000..8e024951 --- /dev/null +++ b/src/opensearch/opensearchmanager.cpp @@ -0,0 +1,234 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Fredy Yanardi +* Copyright (C) 2010 by Lionel Chauvin +* Copyright (C) 2010 by Andrea Diamantini +* +* +* 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 . +* +* ============================================================ */ + + +// Self Includes +#include "opensearchmanager.h" +#include "opensearchmanager.moc" + +// Local Includes +#include "opensearchengine.h" +#include "opensearchreader.h" +#include "opensearchwriter.h" + +// KDE Includes +#include +#include +#include +#include +#include + +// Qt Includes +#include + + +OpenSearchManager::OpenSearchManager(QObject *parent) + : QObject(parent) + , m_activeEngine(0) + , m_currentJob(0) +{ + m_state = IDLE; +} + + +OpenSearchManager::~OpenSearchManager() +{ + qDeleteAll(m_enginesMap.values()); + m_enginesMap.clear(); + + if(m_currentJob) + m_currentJob->kill(); +} + + +void OpenSearchManager::setSearchProvider(const QString &searchProvider) +{ + m_activeEngine = 0; + + if (!m_enginesMap.contains(searchProvider)) + { + const QString fileName = KGlobal::dirs()->findResource("data", "rekonq/opensearch/" + searchProvider + ".xml"); + kDebug() << searchProvider << " file name path: " << fileName; + if (fileName.isEmpty()) + { + kDebug() << "OpenSearch file name empty"; + return; + } + QFile file(fileName); + + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + kDebug() << "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); + + if (m_currentJob) + { + disconnect(m_currentJob); + m_currentJob->kill(); + delete m_currentJob; + } + + m_jobData.clear(); + + if (m_state != IDLE) + { + // TODO: cancel job + } + + m_state = REQ_DESCRIPTION; + m_currentJob = KIO::get(url, KIO::NoReload, KIO::HideProgressInfo); + 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) + return; + + if (m_state != IDLE) + { + // TODO: cancel job + } + m_state = REQ_SUGGESTION; + + _typedText = searchText; + + KUrl url = m_activeEngine->suggestionsUrl(searchText); + kDebug() << "Requesting for suggestions: " << url.url(); + + if (m_currentJob) + { + disconnect(m_currentJob); + m_currentJob->kill(); + } + m_jobData.clear(); + + m_currentJob = KIO::get(url, KIO::NoReload, KIO::HideProgressInfo); + 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::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() << "Received suggestions in "<< _typedText << " from " << m_activeEngine->name() << ": " << suggestionsList; + + m_currentJob = NULL; + emit suggestionReceived(_typedText, suggestionsList); + return; + } + + 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", "rekonq/opensearch/"); + QString fileName = trimmedEngineName(engine->name()); + QFile file(path + fileName + ".xml"); + OpenSearchWriter writer; + writer.write(&file, engine); + + QString searchUrl = OpenSearchEngine::parseTemplate("\\{@}", engine->searchUrlTemplate()); + m_currentJob = NULL; + 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; +} diff --git a/src/opensearch/opensearchmanager.h b/src/opensearch/opensearchmanager.h new file mode 100644 index 00000000..224ada08 --- /dev/null +++ b/src/opensearch/opensearchmanager.h @@ -0,0 +1,112 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Fredy Yanardi +* Copyright (C) 2010 by Lionel Chauvin +* Copyright (C) 2010 by Andrea Diamantini +* +* +* 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 OPENSEARCHMANAGER_H +#define OPENSEARCHMANAGER_H + + +// Rekonq Includes +#include "rekonq_defines.h" + +// KDE Includes +#include + +// Qt Includes +#include + +// Forward Declarations +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 searchText the text to be queried to the suggestion service + */ + void requestSuggestion(const QString &searchText); + +private slots: + void dataReceived(KIO::Job *job, const QByteArray &data); + void jobFinished(KJob *job); + +signals: + void suggestionReceived(const QString &text, 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; + + KIO::TransferJob *m_currentJob; + + QString _typedText; +}; + +#endif // OPENSEARCHMANAGER_H diff --git a/src/opensearch/opensearchreader.cpp b/src/opensearch/opensearchreader.cpp new file mode 100644 index 00000000..5b7ece2c --- /dev/null +++ b/src/opensearch/opensearchreader.cpp @@ -0,0 +1,174 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Jakub Wieczorek +* Copyright (C) 2009 by Fredy Yanardi +* Copyright (C) 2010 by Lionel Chauvin +* Copyright (C) 2010 by Andrea Diamantini +* +* +* 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 . +* +* ============================================================ */ + + +// Self Includes +#include "opensearchreader.h" + +// Local Includes +#include "opensearchengine.h" + +// Qt Includes +#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() != QL1S("OpenSearchDescription") + || namespaceUri() != QL1S("http://a9.com/-/spec/opensearch/1.1/") + ) + { + raiseError(QObject::tr("The file is not an OpenSearch 1.1 file.")); + return engine; + } + + while (!(isEndElement() && name() == QL1S("OpenSearchDescription")) && !atEnd()) + { + readNext(); + + if (!isStartElement()) + continue; + + // ShortName + if (name() == QL1S("ShortName")) + { + engine->setName(readElementText()); + continue; + } + + // Description + if (name() == QL1S("Description")) + { + engine->setDescription(readElementText()); + continue; + } + + // Url + if (name() == QL1S("Url")) + { + QString type = attributes().value(QL1S("type")).toString(); + QString url = attributes().value(QL1S("template")).toString(); + + if (url.isEmpty()) + continue; + + QList parameters; + + readNext(); + + while (!(isEndElement() && name() == QL1S("Url"))) + { + if (!isStartElement() || (name() != QL1S("Param") && name() != QL1S("Parameter"))) { + readNext(); + continue; + } + + QString key = attributes().value(QL1S("name")).toString(); + QString value = attributes().value(QL1S("value")).toString(); + + if (!key.isEmpty() && !value.isEmpty()) + { + parameters.append(OpenSearchEngine::Parameter(key, value)); + } + + while (!isEndElement()) + { + readNext(); + } + } + + if (type == QL1S("application/x-suggestions+json")) + { + engine->setSuggestionsUrlTemplate(url); + engine->setSuggestionsParameters(parameters); + } + else + { + engine->setSearchUrlTemplate(url); + engine->setSearchParameters(parameters); + } + + continue; + } + + // Image + if (name() == QL1S("Image")) + { + engine->setImageUrl(readElementText()); + continue; + } + + // Engine check + if ( !engine->name().isEmpty() + && !engine->description().isEmpty() + && !engine->suggestionsUrlTemplate().isEmpty() + && !engine->searchUrlTemplate().isEmpty() + && !engine->imageUrl().isEmpty() + ) + { + break; + } + } + + return engine; +} diff --git a/src/opensearch/opensearchreader.h b/src/opensearch/opensearchreader.h new file mode 100644 index 00000000..4e2444e0 --- /dev/null +++ b/src/opensearch/opensearchreader.h @@ -0,0 +1,55 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Jakub Wieczorek +* Copyright (C) 2010 by Lionel Chauvin +* Copyright (C) 2010 by Andrea Diamantini +* +* +* 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 OPENSEARCHREADER_H +#define OPENSEARCHREADER_H + + +// Rekonq Includes +#include "rekonq_defines.h" + +// Qt Includes +#include + +// Forward Declarations +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/opensearch/opensearchwriter.cpp b/src/opensearch/opensearchwriter.cpp new file mode 100644 index 00000000..81ce022c --- /dev/null +++ b/src/opensearch/opensearchwriter.cpp @@ -0,0 +1,134 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Jakub Wieczorek +* Copyright (C) 2010 by Lionel Chauvin +* Copyright (C) 2010 by Andrea Diamantini +* +* +* 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 . +* +* ============================================================ */ + + +// Self Includes +#include "opensearchwriter.h" + +// Local Includes +#include "opensearchengine.h" + +// KDE Includes +#include + +// Qt Includes +#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(QL1S("OpenSearchDescription")); + writeDefaultNamespace(QL1S("http://a9.com/-/spec/opensearch/1.1/")); + + if (!engine->name().isEmpty()) + { + writeTextElement(QL1S("ShortName"), engine->name()); + } + + if (!engine->description().isEmpty()) + { + writeTextElement(QL1S("Description"), engine->description()); + } + + if (!engine->searchUrlTemplate().isEmpty()) + { + writeStartElement(QL1S("Url")); + writeAttribute(QL1S("method"), QL1S("get")); + writeAttribute(QL1S("template"), engine->searchUrlTemplate()); + + if (!engine->searchParameters().empty()) + { + writeNamespace(QL1S("http://a9.com/-/spec/opensearch/extensions/parameters/1.0/"), QL1S("p")); + + QList::const_iterator end = engine->searchParameters().constEnd(); + QList::const_iterator i = engine->searchParameters().constBegin(); + for (; i != end; ++i) + { + writeStartElement(QL1S("p:Parameter")); + writeAttribute(QL1S("name"), i->first); + writeAttribute(QL1S("value"), i->second); + writeEndElement(); + } + } + + writeEndElement(); + } + + if (!engine->suggestionsUrlTemplate().isEmpty()) + { + writeStartElement(QL1S("Url")); + writeAttribute(QL1S("method"), QL1S("get")); + writeAttribute(QL1S("type"), QL1S("application/x-suggestions+json")); + writeAttribute(QL1S("template"), engine->suggestionsUrlTemplate()); + + if (!engine->suggestionsParameters().empty()) + { + writeNamespace(QL1S("http://a9.com/-/spec/opensearch/extensions/parameters/1.0/"), QL1S("p")); + + QList::const_iterator end = engine->suggestionsParameters().constEnd(); + QList::const_iterator i = engine->suggestionsParameters().constBegin(); + for (; i != end; ++i) + { + writeStartElement(QL1S("p:Parameter")); + writeAttribute(QL1S("name"), i->first); + writeAttribute(QL1S("value"), i->second); + writeEndElement(); + } + } + + writeEndElement(); + } + + if (!engine->imageUrl().isEmpty()) + writeTextElement(QL1S("Image"), engine->imageUrl()); + + writeEndElement(); + writeEndDocument(); +} diff --git a/src/opensearch/opensearchwriter.h b/src/opensearch/opensearchwriter.h new file mode 100644 index 00000000..6a2e0d11 --- /dev/null +++ b/src/opensearch/opensearchwriter.h @@ -0,0 +1,56 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Jakub Wieczorek +* Copyright (C) 2010 by Lionel Chauvin +* Copyright (C) 2010 by Andrea Diamantini +* +* +* 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 OPENSEARCHWRITER_H +#define OPENSEARCHWRITER_H + + +// Rekonq Includes +#include "rekonq_defines.h" + +// Qt Includes +#include + +// Forward Declarations +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/opensearch/searchengine.cpp b/src/opensearch/searchengine.cpp new file mode 100644 index 00000000..89e62dee --- /dev/null +++ b/src/opensearch/searchengine.cpp @@ -0,0 +1,157 @@ +/* ============================================================ +* +* 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" +#include "application.h" +#include "iconmanager.h" + +// Auto Includes +#include "rekonq.h" + +//KDE includes +#include +#include + + +bool SearchEngine::m_loaded = false; +QString SearchEngine::m_delimiter = ""; +KService::List SearchEngine::m_favorites; +KService::Ptr SearchEngine::m_defaultEngine; + + +void SearchEngine::reload() +{ + KConfig config("kuriikwsfilterrc"); //Shared with konqueror + KConfigGroup cg = config.group("General"); + + //load delimiter + m_delimiter = cg.readEntry("KeywordDelimiter", ":"); + + //load favorite engines + QStringList favoriteEngines; + 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) + { + QUrl url = service->property("Query").toUrl(); + kDebug() << "ENGINE URL: " << url; + Application::iconManager()->downloadIconFromUrl(url); + + favorites << service; + } + } + m_favorites = favorites; + + //load default engine + QString d = cg.readEntry("DefaultSearchEngine"); + m_defaultEngine = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(d)); + if (!m_defaultEngine) + { + d = QL1S("google"); + m_defaultEngine = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(d)); + } + + m_loaded = true; +} + + +QString SearchEngine::delimiter() +{ + if (!m_loaded) + reload(); + + return m_delimiter; +} + + +KService::List SearchEngine::favorites() +{ + if (!m_loaded) + reload(); + + return m_favorites; +} + + +KService::Ptr SearchEngine::defaultEngine() +{ + if (!m_loaded) + reload(); + + return m_defaultEngine; +} + + +KService::Ptr SearchEngine::fromString(const 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::extractQuery(const QString &text) +{ + QString query = text; + KService::Ptr engine = SearchEngine::fromString(text); + if (engine) + { + query = query.remove(0, text.indexOf(SearchEngine::delimiter()) + 1); + } + + return query; +} + + +QString SearchEngine::buildQuery(KService::Ptr engine, const QString &text) +{ + QString query = engine->property("Query").toString(); + query = query.replace("\\{@}", KUrl::toPercentEncoding(text)); + return query; +} diff --git a/src/opensearch/searchengine.h b/src/opensearch/searchengine.h new file mode 100644 index 00000000..d813666b --- /dev/null +++ b/src/opensearch/searchengine.h @@ -0,0 +1,59 @@ +/* ============================================================ +* +* 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 void reload(); + static QString delimiter(); + static KService::Ptr defaultEngine(); + static KService::List favorites(); + static KService::Ptr fromString(const QString &text); + static QString buildQuery(KService::Ptr engine, const QString &text); + static QString extractQuery(const QString &text); + +private: + static bool m_loaded; + static QString m_delimiter; + static KService::List m_favorites; + static KService::Ptr m_defaultEngine; +}; + +#endif -- cgit v1.2.1