summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Franke <nobody@nowhere.ws>2012-03-21 12:52:37 (GMT)
committerChristian Franke <nobody@nowhere.ws>2012-03-21 13:12:45 (GMT)
commit4a0c4288e7d832f8cd72eefde6afe8fc535f5e73 (patch)
tree7dea186a9bcbac75fa06e3cc121ba0c6511e3250
parent179da0310ec3df51b1e95492fca04ab273fa70ac (diff)
Use upstream opensearch code
All arora specific code has been moved from src/opensearch/ to src/ so now, src/opensearch is a direct clone of the qopensearch tree at http://gitorious.org/qopensearch/qopensearch
-rw-r--r--src/opensearch/.gitignore9
-rw-r--r--src/opensearch/build.pri7
-rw-r--r--src/opensearch/examples/examples.pro4
-rw-r--r--src/opensearch/examples/suggestions/helperobject.h34
-rw-r--r--src/opensearch/examples/suggestions/main.cpp65
-rw-r--r--src/opensearch/examples/suggestions/suggestions.pro10
-rw-r--r--src/opensearch/opensearchreader.cpp166
-rw-r--r--src/opensearch/qopensearch.pro4
-rw-r--r--src/opensearch/src/opensearch-nolib.pri16
-rw-r--r--src/opensearch/src/opensearch.pri6
-rw-r--r--src/opensearch/src/opensearch.pro (renamed from src/opensearch/opensearch.pri)21
-rw-r--r--src/opensearch/src/opensearchengine.cpp (renamed from src/opensearch/opensearchengine.cpp)230
-rw-r--r--src/opensearch/src/opensearchengine.h (renamed from src/opensearch/opensearchengine.h)33
-rw-r--r--src/opensearch/src/opensearchenginedelegate.cpp (renamed from src/opensearch/opensearchenginedelegate.cpp)0
-rw-r--r--src/opensearch/src/opensearchenginedelegate.h (renamed from src/opensearch/opensearchenginedelegate.h)0
-rw-r--r--src/opensearch/src/opensearchreader.cpp229
-rw-r--r--src/opensearch/src/opensearchreader.h (renamed from src/opensearch/opensearchreader.h)15
-rw-r--r--src/opensearch/src/opensearchwriter.cpp (renamed from src/opensearch/opensearchwriter.cpp)3
-rw-r--r--src/opensearch/src/opensearchwriter.h (renamed from src/opensearch/opensearchwriter.h)1
-rw-r--r--src/opensearch/tests/opensearchengine/.gitignore1
-rw-r--r--src/opensearch/tests/opensearchengine/opensearchengine.pro13
-rw-r--r--src/opensearch/tests/opensearchengine/opensearchengine.qrc5
-rw-r--r--src/opensearch/tests/opensearchengine/suggestions.txt1
-rw-r--r--src/opensearch/tests/opensearchengine/tst_opensearchengine.cpp910
-rw-r--r--src/opensearch/tests/opensearchreader/.gitignore1
-rw-r--r--src/opensearch/tests/opensearchreader/opensearchreader.pro11
-rw-r--r--src/opensearch/tests/opensearchreader/opensearchreader.qrc12
-rw-r--r--src/opensearch/tests/opensearchreader/testfile1.xml10
-rw-r--r--src/opensearch/tests/opensearchreader/testfile2.xml6
-rw-r--r--src/opensearch/tests/opensearchreader/testfile3.xml12
-rw-r--r--src/opensearch/tests/opensearchreader/testfile4.xml8
-rw-r--r--src/opensearch/tests/opensearchreader/testfile5.xml1
-rw-r--r--src/opensearch/tests/opensearchreader/testfile6.xml5
-rw-r--r--src/opensearch/tests/opensearchreader/testfile7.xml0
-rw-r--r--src/opensearch/tests/opensearchreader/testfile8.xml8
-rw-r--r--src/opensearch/tests/opensearchreader/tst_opensearchreader.cpp163
-rw-r--r--src/opensearch/tests/opensearchwriter/.gitignore1
-rw-r--r--src/opensearch/tests/opensearchwriter/opensearchwriter.pro11
-rw-r--r--src/opensearch/tests/opensearchwriter/opensearchwriter.qrc7
-rw-r--r--src/opensearch/tests/opensearchwriter/testfile1.xml6
-rw-r--r--src/opensearch/tests/opensearchwriter/testfile2.xml8
-rw-r--r--src/opensearch/tests/opensearchwriter/testfile3.xml12
-rw-r--r--src/opensearch/tests/opensearchwriter/tst_opensearchwriter.cpp134
-rw-r--r--src/opensearch/tests/qtry.h49
-rw-r--r--src/opensearch/tests/tests.pri12
-rw-r--r--src/opensearch/tests/tests.pro4
-rw-r--r--src/opensearchdialog.cpp (renamed from src/opensearch/opensearchdialog.cpp)0
-rw-r--r--src/opensearchdialog.h (renamed from src/opensearch/opensearchdialog.h)0
-rw-r--r--src/opensearchdialog.ui (renamed from src/opensearch/opensearchdialog.ui)0
-rw-r--r--src/opensearchengineaction.cpp (renamed from src/opensearch/opensearchengineaction.cpp)0
-rw-r--r--src/opensearchengineaction.h (renamed from src/opensearch/opensearchengineaction.h)0
-rw-r--r--src/opensearchenginemodel.cpp (renamed from src/opensearch/opensearchenginemodel.cpp)0
-rw-r--r--src/opensearchenginemodel.h (renamed from src/opensearch/opensearchenginemodel.h)0
-rw-r--r--src/opensearchmanager.cpp (renamed from src/opensearch/opensearchmanager.cpp)0
-rw-r--r--src/opensearchmanager.h (renamed from src/opensearch/opensearchmanager.h)0
-rw-r--r--src/src.pri13
56 files changed, 1978 insertions, 299 deletions
diff --git a/src/opensearch/.gitignore b/src/opensearch/.gitignore
new file mode 100644
index 0000000..45950ba
--- /dev/null
+++ b/src/opensearch/.gitignore
@@ -0,0 +1,9 @@
+build
+Makefile*
+.ui
+.moc
+.obj
+.rcc
+.qm
+.gdb_history
+*~
diff --git a/src/opensearch/build.pri b/src/opensearch/build.pri
new file mode 100644
index 0000000..d7aac97
--- /dev/null
+++ b/src/opensearch/build.pri
@@ -0,0 +1,7 @@
+BUILDDIR = $$PWD/build
+TEMPDIR = $$BUILDDIR/tmp
+
+RCC_DIR = $$TEMPDIR
+UI_DIR = $$TEMPDIR
+MOC_DIR = $$TEMPDIR
+OBJECTS_DIR = $$TEMPDIR
diff --git a/src/opensearch/examples/examples.pro b/src/opensearch/examples/examples.pro
new file mode 100644
index 0000000..7f43581
--- /dev/null
+++ b/src/opensearch/examples/examples.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+SUBDIRS = suggestions
+
+CONFIG += ordered
diff --git a/src/opensearch/examples/suggestions/helperobject.h b/src/opensearch/examples/suggestions/helperobject.h
new file mode 100644
index 0000000..69b0508
--- /dev/null
+++ b/src/opensearch/examples/suggestions/helperobject.h
@@ -0,0 +1,34 @@
+#include <qobject.h>
+
+#include <qapplication.h>
+#include <qstringlist.h>
+#include <qtextstream.h>
+#include <qtimer.h>
+
+class HelperObject : public QObject
+{
+ Q_OBJECT
+
+public:
+ HelperObject(QObject *parent, QTextStream *stream)
+ : QObject(parent)
+ , m_stream(stream)
+ {
+ }
+
+public slots:
+ void printSuggestions(const QStringList &suggestions)
+ {
+ Q_ASSERT(m_stream);
+ if (suggestions.isEmpty())
+ *m_stream << "No suggestions." << "\n";
+ else
+ *m_stream << suggestions.join("\n") << "\n";
+
+ QApplication *app = static_cast<QApplication*>(parent());
+ QTimer::singleShot(0, app, SLOT(quit()));
+ }
+
+private:
+ QTextStream *m_stream;
+};
diff --git a/src/opensearch/examples/suggestions/main.cpp b/src/opensearch/examples/suggestions/main.cpp
new file mode 100644
index 0000000..7030667
--- /dev/null
+++ b/src/opensearch/examples/suggestions/main.cpp
@@ -0,0 +1,65 @@
+#include <qapplication.h>
+
+#include "opensearchengine.h"
+#include "opensearchreader.h"
+#include "helperobject.h"
+
+#include <qfile.h>
+#include <qnetworkaccessmanager.h>
+#include <qobject.h>
+#include <qtextstream.h>
+#include <qtimer.h>
+
+#include <cstdio>
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ QStringList args = app.arguments();
+
+ QTextStream stream(stdout);
+
+ if (args.count() < 3) {
+ stream << QString("Usage: %1 filepath searchterm").arg(args.at(0)) << '\n';
+ return 1;
+ }
+
+ QString filePath = args.at(1);
+ QString searchTerm = args.at(2);
+
+ if (!QFile::exists(filePath)) {
+ stream << QString("File %1 does not exist.").arg(filePath) << '\n';
+ return 1;
+ }
+
+ QFile file(filePath);
+ file.open(QIODevice::ReadOnly);
+
+ QNetworkAccessManager manager;
+
+ OpenSearchReader reader;
+ OpenSearchEngine *engine = reader.read(&file);
+ if (reader.hasError()) {
+ stream << QString("Error: %1").arg(reader.errorString()) << '\n';
+ return 1;
+ }
+
+ if (!engine->isValid()) {
+ stream << "The OpenSearch description is invalid." << '\n';
+ return 1;
+ }
+
+ QTimer timer;
+ timer.setSingleShot(true);
+ timer.setInterval(10 * 1000);
+
+ HelperObject helper(&app, &stream);
+ engine->setNetworkAccessManager(&manager);
+ engine->requestSuggestions(searchTerm);
+ timer.start();
+ QObject::connect(engine, SIGNAL(suggestions(const QStringList &)),
+ &helper, SLOT(printSuggestions(const QStringList &)));
+ QObject::connect(&timer, SIGNAL(timeout()),
+ &app, SLOT(quit()));
+ app.exec();
+} \ No newline at end of file
diff --git a/src/opensearch/examples/suggestions/suggestions.pro b/src/opensearch/examples/suggestions/suggestions.pro
new file mode 100644
index 0000000..896a2ea
--- /dev/null
+++ b/src/opensearch/examples/suggestions/suggestions.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+
+QT += network
+
+include(../../build.pri)
+include(../../src/opensearch.pri)
+DESTDIR = $$BUILDDIR/examples
+
+SOURCES += main.cpp
+HEADERS += helperobject.h
diff --git a/src/opensearch/opensearchreader.cpp b/src/opensearch/opensearchreader.cpp
deleted file mode 100644
index 7b88578..0000000
--- a/src/opensearch/opensearchreader.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright 2009 Jakub Wieczorek <faw217@gmail.com>
- *
- * 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 <qiodevice.h>
-
-/*!
- \class OpenSearchReader
- \brief A class reading a search engine description from an external source
-
- OpenSearchReader is a class that can be used to read search engine descriptions
- formed using the OpenSearch format.
-
- It inherits QXmlStreamReader and thus provides additional functions, such as
- QXmlStreamReader::error(), QXmlStreamReader::hasError() that can be used to make sure
- the reading procedure succeeded.
-
- For more information see:
- http://www.opensearch.org/Specifications/OpenSearch/1.1/Draft_4#OpenSearch_description_document
-
- \sa OpenSearchEngine, OpenSearchWriter
-*/
-
-/*!
- Constructs a new reader.
-
- \note One instance can be used to read multiple files, one by one.
-*/
-OpenSearchReader::OpenSearchReader()
- : QXmlStreamReader()
-{
-}
-
-/*!
- Reads an OpenSearch engine from the \a device and returns an OpenSearchEngine object,
- filled in with all the data that has been retrieved from the document.
-
- If the \a device is closed, it will be opened.
-
- To make sure if the procedure succeeded, check QXmlStreamReader::error().
-
- \return a new constructed OpenSearchEngine object
-
- \note The function returns an object of the OpenSearchEngine class even if the document
- is bad formed or doesn't conform to the specification. It needs to be manually
- deleted afterwards, if intended.
- \note The lifetime of the returned OpenSearchEngine object is up to the user.
- The object should be deleted once it is not used anymore to avoid memory leaks.
-*/
-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 (!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();
- QString method = attributes().value(QLatin1String("method")).toString();
-
- if (type == QLatin1String("application/x-suggestions+json")
- && !engine->suggestionsUrlTemplate().isEmpty())
- continue;
-
- if ((type.isEmpty()
- || type == QLatin1String("text/html")
- || type == QLatin1String("application/xhtml+xml"))
- && !engine->searchUrlTemplate().isEmpty())
- continue;
-
- if (url.isEmpty())
- continue;
-
- QList<OpenSearchEngine::Parameter> 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);
- engine->setSuggestionsMethod(method);
- } else if (type.isEmpty() || type == QLatin1String("text/html") || type == QLatin1String("application/xhtml+xml")) {
- engine->setSearchUrlTemplate(url);
- engine->setSearchParameters(parameters);
- engine->setSearchMethod(method);
- }
-
- } 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/opensearch/qopensearch.pro b/src/opensearch/qopensearch.pro
new file mode 100644
index 0000000..95f3807
--- /dev/null
+++ b/src/opensearch/qopensearch.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+SUBDIRS = src/opensearch.pro tests examples
+
+CONFIG += ordered
diff --git a/src/opensearch/src/opensearch-nolib.pri b/src/opensearch/src/opensearch-nolib.pri
new file mode 100644
index 0000000..9c69a66
--- /dev/null
+++ b/src/opensearch/src/opensearch-nolib.pri
@@ -0,0 +1,16 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+QT += network script
+
+HEADERS += \
+ opensearchengine.h \
+ opensearchenginedelegate.h \
+ opensearchreader.h \
+ opensearchwriter.h
+
+SOURCES += \
+ opensearchengine.cpp \
+ opensearchenginedelegate.cpp \
+ opensearchreader.cpp \
+ opensearchwriter.cpp
diff --git a/src/opensearch/src/opensearch.pri b/src/opensearch/src/opensearch.pri
new file mode 100644
index 0000000..e9a120c
--- /dev/null
+++ b/src/opensearch/src/opensearch.pri
@@ -0,0 +1,6 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+LIBS += -L$$BUILDDIR \
+ -Wl,-rpath,$$BUILDDIR \
+ -lqopensearch
diff --git a/src/opensearch/opensearch.pri b/src/opensearch/src/opensearch.pro
index dbace74..cbd1499 100644
--- a/src/opensearch/opensearch.pri
+++ b/src/opensearch/src/opensearch.pro
@@ -1,26 +1,23 @@
+TEMPLATE = lib
+TARGET = qopensearch
+CONFIG += dll
+
+include(../build.pri)
+DESTDIR = $$BUILDDIR
+
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
+QT += network script
+
HEADERS += \
- opensearchdialog.h \
opensearchengine.h \
opensearchenginedelegate.h \
- opensearchengineaction.h \
- opensearchenginemodel.h \
- opensearchmanager.h \
opensearchreader.h \
opensearchwriter.h
SOURCES += \
- opensearchdialog.cpp \
opensearchengine.cpp \
opensearchenginedelegate.cpp \
- opensearchengineaction.cpp \
- opensearchenginemodel.cpp \
- opensearchmanager.cpp \
opensearchreader.cpp \
opensearchwriter.cpp
-
-FORMS += opensearchdialog.ui
-
-QT += script
diff --git a/src/opensearch/opensearchengine.cpp b/src/opensearch/src/opensearchengine.cpp
index 0332fc1..a0dfa6d 100644
--- a/src/opensearch/opensearchengine.cpp
+++ b/src/opensearch/src/opensearchengine.cpp
@@ -24,6 +24,7 @@
#include <qbuffer.h>
#include <qcoreapplication.h>
#include <qlocale.h>
+#include <qnetworkaccessmanager.h>
#include <qnetworkrequest.h>
#include <qnetworkreply.h>
#include <qregexp.h>
@@ -31,6 +32,45 @@
#include <qscriptvalue.h>
#include <qstringlist.h>
+class OpenSearchEnginePrivate
+{
+public:
+ OpenSearchEnginePrivate();
+
+ QString name;
+ QString description;
+
+ QString imageUrl;
+ QImage image;
+
+ QStringList tags;
+
+ QString searchUrlTemplate;
+ QString suggestionsUrlTemplate;
+ OpenSearchEngine::Parameters searchParameters;
+ OpenSearchEngine::Parameters suggestionsParameters;
+ QString searchMethod;
+ QString suggestionsMethod;
+
+ QMap<QString, QNetworkAccessManager::Operation> requestMethods;
+
+ QNetworkAccessManager *networkAccessManager;
+ QNetworkReply *suggestionsReply;
+
+ QScriptEngine *scriptEngine;
+
+ OpenSearchEngineDelegate *delegate;
+};
+
+OpenSearchEnginePrivate::OpenSearchEnginePrivate()
+ : searchMethod(QLatin1String("get"))
+ , suggestionsMethod(QLatin1String("get"))
+ , networkAccessManager(0)
+ , suggestionsReply(0)
+ , scriptEngine(0)
+ , delegate(0)
+{}
+
/*!
\class OpenSearchEngine
\brief A class representing a single search engine described in OpenSearch format
@@ -83,15 +123,10 @@
*/
OpenSearchEngine::OpenSearchEngine(QObject *parent)
: QObject(parent)
- , m_searchMethod(QLatin1String("get"))
- , m_suggestionsMethod(QLatin1String("get"))
- , m_networkAccessManager(0)
- , m_suggestionsReply(0)
- , m_scriptEngine(0)
- , m_delegate(0)
+ , d(new OpenSearchEnginePrivate())
{
- m_requestMethods.insert(QLatin1String("get"), QNetworkAccessManager::GetOperation);
- m_requestMethods.insert(QLatin1String("post"), QNetworkAccessManager::PostOperation);
+ d->requestMethods.insert(QLatin1String("get"), QNetworkAccessManager::GetOperation);
+ d->requestMethods.insert(QLatin1String("post"), QNetworkAccessManager::PostOperation);
}
/*!
@@ -99,8 +134,9 @@ OpenSearchEngine::OpenSearchEngine(QObject *parent)
*/
OpenSearchEngine::~OpenSearchEngine()
{
- if (m_scriptEngine)
- m_scriptEngine->deleteLater();
+ if (d->scriptEngine)
+ d->scriptEngine->deleteLater();
+ delete d;
}
QString OpenSearchEngine::parseTemplate(const QString &searchTerm, const QString &searchTemplate)
@@ -130,12 +166,12 @@ QString OpenSearchEngine::parseTemplate(const QString &searchTerm, const QString
*/
QString OpenSearchEngine::name() const
{
- return m_name;
+ return d->name;
}
void OpenSearchEngine::setName(const QString &name)
{
- m_name = name;
+ d->name = name;
}
/*!
@@ -146,12 +182,12 @@ void OpenSearchEngine::setName(const QString &name)
*/
QString OpenSearchEngine::description() const
{
- return m_description;
+ return d->description;
}
void OpenSearchEngine::setDescription(const QString &description)
{
- m_description = description;
+ d->description = description;
}
/*!
@@ -162,12 +198,12 @@ void OpenSearchEngine::setDescription(const QString &description)
*/
QString OpenSearchEngine::searchUrlTemplate() const
{
- return m_searchUrlTemplate;
+ return d->searchUrlTemplate;
}
void OpenSearchEngine::setSearchUrlTemplate(const QString &searchUrlTemplate)
{
- m_searchUrlTemplate = searchUrlTemplate;
+ d->searchUrlTemplate = searchUrlTemplate;
}
/*!
@@ -202,14 +238,14 @@ void OpenSearchEngine::setSearchUrlTemplate(const QString &searchUrlTemplate)
*/
QUrl OpenSearchEngine::searchUrl(const QString &searchTerm) const
{
- if (m_searchUrlTemplate.isEmpty())
+ if (d->searchUrlTemplate.isEmpty())
return QUrl();
- QUrl retVal = QUrl::fromEncoded(parseTemplate(searchTerm, m_searchUrlTemplate).toUtf8());
+ QUrl retVal = QUrl::fromEncoded(parseTemplate(searchTerm, d->searchUrlTemplate).toUtf8());
- if (m_searchMethod != QLatin1String("post")) {
- Parameters::const_iterator end = m_searchParameters.constEnd();
- Parameters::const_iterator i = m_searchParameters.constBegin();
+ if (d->searchMethod != QLatin1String("post")) {
+ Parameters::const_iterator end = d->searchParameters.constEnd();
+ Parameters::const_iterator i = d->searchParameters.constBegin();
for (; i != end; ++i)
retVal.addQueryItem(i->first, parseTemplate(searchTerm, i->second));
}
@@ -223,7 +259,7 @@ QUrl OpenSearchEngine::searchUrl(const QString &searchTerm) const
*/
bool OpenSearchEngine::providesSuggestions() const
{
- return !m_suggestionsUrlTemplate.isEmpty();
+ return !d->suggestionsUrlTemplate.isEmpty();
}
/*!
@@ -234,12 +270,12 @@ bool OpenSearchEngine::providesSuggestions() const
*/
QString OpenSearchEngine::suggestionsUrlTemplate() const
{
- return m_suggestionsUrlTemplate;
+ return d->suggestionsUrlTemplate;
}
void OpenSearchEngine::setSuggestionsUrlTemplate(const QString &suggestionsUrlTemplate)
{
- m_suggestionsUrlTemplate = suggestionsUrlTemplate;
+ d->suggestionsUrlTemplate = suggestionsUrlTemplate;
}
/*!
@@ -254,14 +290,14 @@ void OpenSearchEngine::setSuggestionsUrlTemplate(const QString &suggestionsUrlTe
*/
QUrl OpenSearchEngine::suggestionsUrl(const QString &searchTerm) const
{
- if (m_suggestionsUrlTemplate.isEmpty())
+ if (d->suggestionsUrlTemplate.isEmpty())
return QUrl();
- QUrl retVal = QUrl::fromEncoded(parseTemplate(searchTerm, m_suggestionsUrlTemplate).toUtf8());
+ QUrl retVal = QUrl::fromEncoded(parseTemplate(searchTerm, d->suggestionsUrlTemplate).toUtf8());
- if (m_suggestionsMethod != QLatin1String("post")) {
- Parameters::const_iterator end = m_suggestionsParameters.constEnd();
- Parameters::const_iterator i = m_suggestionsParameters.constBegin();
+ if (d->suggestionsMethod != QLatin1String("post")) {
+ Parameters::const_iterator end = d->suggestionsParameters.constEnd();
+ Parameters::const_iterator i = d->suggestionsParameters.constBegin();
for (; i != end; ++i)
retVal.addQueryItem(i->first, parseTemplate(searchTerm, i->second));
}
@@ -278,12 +314,12 @@ QUrl OpenSearchEngine::suggestionsUrl(const QString &searchTerm) const
*/
OpenSearchEngine::Parameters OpenSearchEngine::searchParameters() const
{
- return m_searchParameters;
+ return d->searchParameters;
}
void OpenSearchEngine::setSearchParameters(const Parameters &searchParameters)
{
- m_searchParameters = searchParameters;
+ d->searchParameters = searchParameters;
}
/*!
@@ -295,12 +331,12 @@ void OpenSearchEngine::setSearchParameters(const Parameters &searchParameters)
*/
OpenSearchEngine::Parameters OpenSearchEngine::suggestionsParameters() const
{
- return m_suggestionsParameters;
+ return d->suggestionsParameters;
}
void OpenSearchEngine::setSuggestionsParameters(const Parameters &suggestionsParameters)
{
- m_suggestionsParameters = suggestionsParameters;
+ d->suggestionsParameters = suggestionsParameters;
}
/*!
@@ -309,16 +345,16 @@ void OpenSearchEngine::setSuggestionsParameters(const Parameters &suggestionsPar
*/
QString OpenSearchEngine::searchMethod() const
{
- return m_searchMethod;
+ return d->searchMethod;
}
void OpenSearchEngine::setSearchMethod(const QString &method)
{
QString requestMethod = method.toLower();
- if (!m_requestMethods.contains(requestMethod))
+ if (!d->requestMethods.contains(requestMethod))
return;
- m_searchMethod = requestMethod;
+ d->searchMethod = requestMethod;
}
/*!
@@ -327,16 +363,16 @@ void OpenSearchEngine::setSearchMethod(const QString &method)
*/
QString OpenSearchEngine::suggestionsMethod() const
{
- return m_suggestionsMethod;
+ return d->suggestionsMethod;
}
void OpenSearchEngine::setSuggestionsMethod(const QString &method)
{
QString requestMethod = method.toLower();
- if (!m_requestMethods.contains(requestMethod))
+ if (!d->requestMethods.contains(requestMethod))
return;
- m_suggestionsMethod = requestMethod;
+ d->suggestionsMethod = requestMethod;
}
/*!
@@ -353,20 +389,20 @@ void OpenSearchEngine::setSuggestionsMethod(const QString &method)
*/
QString OpenSearchEngine::imageUrl() const
{
- return m_imageUrl;
+ return d->imageUrl;
}
void OpenSearchEngine::setImageUrl(const QString &imageUrl)
{
- m_imageUrl = imageUrl;
+ d->imageUrl = imageUrl;
}
void OpenSearchEngine::loadImage() const
{
- if (!m_networkAccessManager || m_imageUrl.isEmpty())
+ if (!d->networkAccessManager || d->imageUrl.isEmpty())
return;
- QNetworkReply *reply = m_networkAccessManager->get(QNetworkRequest(QUrl::fromEncoded(m_imageUrl.toUtf8())));
+ QNetworkReply *reply = d->networkAccessManager->get(QNetworkRequest(QUrl::fromEncoded(d->imageUrl.toUtf8())));
connect(reply, SIGNAL(finished()), this, SLOT(imageObtained()));
}
@@ -385,7 +421,7 @@ void OpenSearchEngine::imageObtained()
if (response.isEmpty())
return;
- m_image.loadFromData(response);
+ d->image.loadFromData(response);
emit imageChanged();
}
@@ -400,49 +436,63 @@ void OpenSearchEngine::imageObtained()
*/
QImage OpenSearchEngine::image() const
{
- if (m_image.isNull())
+ if (d->image.isNull())
loadImage();
- return m_image;
+ return d->image;
}
void OpenSearchEngine::setImage(const QImage &image)
{
- if (m_imageUrl.isEmpty()) {
+ if (d->imageUrl.isEmpty()) {
QBuffer imageBuffer;
imageBuffer.open(QBuffer::ReadWrite);
if (image.save(&imageBuffer, "PNG")) {
- m_imageUrl = QString(QLatin1String("data:image/png;base64,%1"))
+ d->imageUrl = QString(QLatin1String("data:image/png;base64,%1"))
.arg(QLatin1String(imageBuffer.buffer().toBase64()));
}
}
- m_image = image;
+ d->image = image;
emit imageChanged();
}
/*!
+ \property tags
+ \brief a set of words that are used as keywords to identify and categorize this search content
+*/
+QStringList OpenSearchEngine::tags() const
+{
+ return d->tags;
+}
+
+void OpenSearchEngine::setTags(const QStringList &tags)
+{
+ d->tags = tags;
+}
+
+/*!
\property valid
\brief indicates whether the engine is valid i.e. the description was properly formed and included all necessary information
*/
bool OpenSearchEngine::isValid() const
{
- return (!m_name.isEmpty() && !m_searchUrlTemplate.isEmpty());
+ return (!d->name.isEmpty() && !d->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);
+ return (d->name == other.d->name
+ && d->description == other.d->description
+ && d->imageUrl == other.d->imageUrl
+ && d->searchUrlTemplate == other.d->searchUrlTemplate
+ && d->suggestionsUrlTemplate == other.d->suggestionsUrlTemplate
+ && d->searchParameters == other.d->searchParameters
+ && d->suggestionsParameters == other.d->suggestionsParameters);
}
bool OpenSearchEngine::operator<(const OpenSearchEngine &other) const
{
- return (m_name < other.m_name);
+ return (d->name < other.d->name);
}
/*!
@@ -460,33 +510,33 @@ void OpenSearchEngine::requestSuggestions(const QString &searchTerm)
if (searchTerm.isEmpty() || !providesSuggestions())
return;
- Q_ASSERT(m_networkAccessManager);
+ Q_ASSERT(d->networkAccessManager);
- if (!m_networkAccessManager)
+ if (!d->networkAccessManager)
return;
- if (m_suggestionsReply) {
- m_suggestionsReply->disconnect(this);
- m_suggestionsReply->abort();
- m_suggestionsReply->deleteLater();
- m_suggestionsReply = 0;
+ if (d->suggestionsReply) {
+ d->suggestionsReply->disconnect(this);
+ d->suggestionsReply->abort();
+ d->suggestionsReply->deleteLater();
+ d->suggestionsReply = 0;
}
- Q_ASSERT(m_requestMethods.contains(m_suggestionsMethod));
- if (m_suggestionsMethod == QLatin1String("get")) {
- m_suggestionsReply = m_networkAccessManager->get(QNetworkRequest(suggestionsUrl(searchTerm)));
+ Q_ASSERT(d->requestMethods.contains(d->suggestionsMethod));
+ if (d->suggestionsMethod == QLatin1String("get")) {
+ d->suggestionsReply = d->networkAccessManager->get(QNetworkRequest(suggestionsUrl(searchTerm)));
} else {
QStringList parameters;
- Parameters::const_iterator end = m_suggestionsParameters.constEnd();
- Parameters::const_iterator i = m_suggestionsParameters.constBegin();
+ Parameters::const_iterator end = d->suggestionsParameters.constEnd();
+ Parameters::const_iterator i = d->suggestionsParameters.constBegin();
for (; i != end; ++i)
parameters.append(i->first + QLatin1String("=") + i->second);
QByteArray data = parameters.join(QLatin1String("&")).toUtf8();
- m_suggestionsReply = m_networkAccessManager->post(QNetworkRequest(suggestionsUrl(searchTerm)), data);
+ d->suggestionsReply = d->networkAccessManager->post(QNetworkRequest(suggestionsUrl(searchTerm)), data);
}
- connect(m_suggestionsReply, SIGNAL(finished()), this, SLOT(suggestionsObtained()));
+ connect(d->suggestionsReply, SIGNAL(finished()), this, SLOT(suggestionsObtained()));
}
/*!
@@ -501,36 +551,36 @@ void OpenSearchEngine::requestSuggestions(const QString &searchTerm)
*/
void OpenSearchEngine::requestSearchResults(const QString &searchTerm)
{
- if (!m_delegate || searchTerm.isEmpty())
+ if (!d->delegate || searchTerm.isEmpty())
return;
- Q_ASSERT(m_requestMethods.contains(m_searchMethod));
+ Q_ASSERT(d->requestMethods.contains(d->searchMethod));
QNetworkRequest request(QUrl(searchUrl(searchTerm)));
QByteArray data;
- QNetworkAccessManager::Operation operation = m_requestMethods.value(m_searchMethod);
+ QNetworkAccessManager::Operation operation = d->requestMethods.value(d->searchMethod);
if (operation == QNetworkAccessManager::PostOperation) {
QStringList parameters;
- Parameters::const_iterator end = m_searchParameters.constEnd();
- Parameters::const_iterator i = m_searchParameters.constBegin();
+ Parameters::const_iterator end = d->searchParameters.constEnd();
+ Parameters::const_iterator i = d->searchParameters.constBegin();
for (; i != end; ++i)
parameters.append(i->first + QLatin1String("=") + i->second);
data = parameters.join(QLatin1String("&")).toUtf8();
}
- m_delegate->performSearchRequest(request, operation, data);
+ d->delegate->performSearchRequest(request, operation, data);
}
void OpenSearchEngine::suggestionsObtained()
{
- QString response(QString::fromUtf8(m_suggestionsReply->readAll()));
+ QString response(QString::fromUtf8(d->suggestionsReply->readAll()));
response = response.trimmed();
- m_suggestionsReply->close();
- m_suggestionsReply->deleteLater();
- m_suggestionsReply = 0;
+ d->suggestionsReply->close();
+ d->suggestionsReply->deleteLater();
+ d->suggestionsReply = 0;
if (response.isEmpty())
return;
@@ -538,14 +588,14 @@ void OpenSearchEngine::suggestionsObtained()
if (!response.startsWith(QLatin1Char('[')) || !response.endsWith(QLatin1Char(']')))
return;
- if (!m_scriptEngine)
- m_scriptEngine = new QScriptEngine();
+ if (!d->scriptEngine)
+ d->scriptEngine = new QScriptEngine();
// Evaluate the JSON response using QtScript.
- if (!m_scriptEngine->canEvaluate(response))
+ if (!d->scriptEngine->canEvaluate(response))
return;
- QScriptValue responseParts = m_scriptEngine->evaluate(response);
+ QScriptValue responseParts = d->scriptEngine->evaluate(response);
if (!responseParts.property(1).isArray())
return;
@@ -565,12 +615,12 @@ void OpenSearchEngine::suggestionsObtained()
*/
QNetworkAccessManager *OpenSearchEngine::networkAccessManager() const
{
- return m_networkAccessManager;
+ return d->networkAccessManager;
}
void OpenSearchEngine::setNetworkAccessManager(QNetworkAccessManager *networkAccessManager)
{
- m_networkAccessManager = networkAccessManager;
+ d->networkAccessManager = networkAccessManager;
}
/*!
@@ -582,12 +632,12 @@ void OpenSearchEngine::setNetworkAccessManager(QNetworkAccessManager *networkAcc
*/
OpenSearchEngineDelegate *OpenSearchEngine::delegate() const
{
- return m_delegate;
+ return d->delegate;
}
void OpenSearchEngine::setDelegate(OpenSearchEngineDelegate *delegate)
{
- m_delegate = delegate;
+ d->delegate = delegate;
}
/*!
diff --git a/src/opensearch/opensearchengine.h b/src/opensearch/src/opensearchengine.h
index 3ec63d2..6197f38 100644
--- a/src/opensearch/opensearchengine.h
+++ b/src/opensearch/src/opensearchengine.h
@@ -23,14 +23,16 @@
#include <qpair.h>
#include <qimage.h>
#include <qmap.h>
-#include <qnetworkaccessmanager.h>
#include <qstring.h>
+#include <qstringlist.h>
#include <qurl.h>
+class QNetworkAccessManager;
class QNetworkReply;
class QScriptEngine;
class OpenSearchEngineDelegate;
+class OpenSearchEnginePrivate;
class OpenSearchEngine : public QObject
{
Q_OBJECT
@@ -53,8 +55,9 @@ public:
Q_PROPERTY(QString suggestionsMethod READ suggestionsMethod WRITE setSuggestionsMethod)
Q_PROPERTY(bool providesSuggestions READ providesSuggestions)
Q_PROPERTY(QString imageUrl READ imageUrl WRITE setImageUrl)
+ Q_PROPERTY(QStringList tags READ tags WRITE setTags)
Q_PROPERTY(bool valid READ isValid)
- Q_PROPERTY(QNetworkAccessManager *networkAccessManager READ networkAccessManager WRITE setNetworkAccessManager)
+ Q_PROPERTY(QNetworkAccessManager* networkAccessManager READ networkAccessManager WRITE setNetworkAccessManager)
OpenSearchEngine(QObject *parent = 0);
~OpenSearchEngine();
@@ -93,6 +96,9 @@ public:
QImage image() const;
void setImage(const QImage &image);
+ QStringList tags() const;
+ void setTags(const QStringList &tags);
+
bool isValid() const;
QNetworkAccessManager *networkAccessManager() const;
@@ -117,28 +123,7 @@ private slots:
void suggestionsObtained();
private:
- QString m_name;
- QString m_description;
-
- QString m_imageUrl;
- QImage m_image;
-
- QString m_searchUrlTemplate;
- QString m_suggestionsUrlTemplate;
- Parameters m_searchParameters;
- Parameters m_suggestionsParameters;
- QString m_searchMethod;
- QString m_suggestionsMethod;
-
- QMap<QString, QNetworkAccessManager::Operation> m_requestMethods;
-
- QNetworkAccessManager *m_networkAccessManager;
- QNetworkReply *m_suggestionsReply;
-
- QScriptEngine *m_scriptEngine;
-
- OpenSearchEngineDelegate *m_delegate;
+ OpenSearchEnginePrivate *d;
};
#endif // OPENSEARCHENGINE_H
-
diff --git a/src/opensearch/opensearchenginedelegate.cpp b/src/opensearch/src/opensearchenginedelegate.cpp
index d31569a..d31569a 100644
--- a/src/opensearch/opensearchenginedelegate.cpp
+++ b/src/opensearch/src/opensearchenginedelegate.cpp
diff --git a/src/opensearch/opensearchenginedelegate.h b/src/opensearch/src/opensearchenginedelegate.h
index 5de3c59..5de3c59 100644
--- a/src/opensearch/opensearchenginedelegate.h
+++ b/src/opensearch/src/opensearchenginedelegate.h
diff --git a/src/opensearch/src/opensearchreader.cpp b/src/opensearch/src/opensearchreader.cpp
new file mode 100644
index 0000000..c758434
--- /dev/null
+++ b/src/opensearch/src/opensearchreader.cpp
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2009 Jakub Wieczorek <faw217@gmail.com>
+ *
+ * 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 <qiodevice.h>
+
+/*!
+ \class OpenSearchReader
+ \brief A class reading a search engine description from an external source
+
+ OpenSearchReader is a class that can be used to read search engine descriptions
+ formed using the OpenSearch format.
+
+ It inherits QXmlStreamReader and thus provides additional functions, such as
+ QXmlStreamReader::error(), QXmlStreamReader::hasError() that can be used to make sure
+ the reading procedure succeeded.
+
+ For more information see:
+ http://www.opensearch.org/Specifications/OpenSearch/1.1/Draft_4#OpenSearch_description_document
+
+ \sa OpenSearchEngine, OpenSearchWriter
+*/
+
+/*!
+ Constructs a new reader.
+
+ \note One instance can be used to read multiple files, one by one.
+*/
+OpenSearchReader::OpenSearchReader()
+ : QXmlStreamReader()
+ , m_engine(0)
+{
+}
+
+/*!
+ Reads an OpenSearch engine from the \a device and returns an OpenSearchEngine object,
+ filled in with all the data that has been retrieved from the document.
+
+ If the \a device is closed, it will be opened.
+
+ To make sure if the procedure succeeded, check QXmlStreamReader::error().
+
+ \return a new constructed OpenSearchEngine object
+
+ \note The function returns an object of the OpenSearchEngine class even if the document
+ is bad formed or doesn't conform to the specification. It needs to be manually
+ deleted afterwards, if intended.
+ \note The lifetime of the returned OpenSearchEngine object is up to the user.
+ The object should be deleted once it is not used anymore to avoid memory leaks.
+*/
+OpenSearchEngine *OpenSearchReader::read(QIODevice *device)
+{
+ m_engine = 0;
+ clear();
+
+ if (!device->isOpen())
+ device->open(QIODevice::ReadOnly);
+
+ setDevice(device);
+ readDocument();
+ return m_engine;
+}
+
+#include <qdebug.h>
+
+void OpenSearchReader::readDocument()
+{
+ m_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;
+ }
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (!isStartElement())
+ continue;
+
+ if (name() == QLatin1String("ShortName"))
+ readName();
+ else if (name() == QLatin1String("Description"))
+ readDescription();
+ else if (name() == QLatin1String("Url"))
+ readUrl();
+ else if (name() == QLatin1String("Image"))
+ readImage();
+ else if (name() == QLatin1String("Tags"))
+ readTags();
+ else
+ skipSubtree();
+ }
+}
+
+void OpenSearchReader::readName()
+{
+ Q_ASSERT(isStartElement() && name() == QLatin1String("ShortName"));
+ m_engine->setName(readElementText());
+}
+
+void OpenSearchReader::readDescription()
+{
+ Q_ASSERT(isStartElement() && name() == QLatin1String("Description"));
+ m_engine->setDescription(readElementText());
+}
+
+void OpenSearchReader::readUrl()
+{
+ Q_ASSERT(isStartElement() && name() == QLatin1String("Url"));
+
+ QString type = attributes().value(QLatin1String("type")).toString();
+ QString url = attributes().value(QLatin1String("template")).toString();
+ QString method = attributes().value(QLatin1String("method")).toString();
+
+ if (type.isEmpty() || type == QLatin1String("application/xhtml+xml"))
+ type = QLatin1String("text/html");
+
+ if (url.isEmpty()) {
+ skipSubtree();
+ return;
+ }
+
+ if (type == QLatin1String("application/x-suggestions+json")
+ && !m_engine->suggestionsUrlTemplate().isEmpty()) {
+ skipSubtree();
+ return;
+ }
+
+ if (type == QLatin1String("text/html")
+ && !m_engine->searchUrlTemplate().isEmpty()) {
+ skipSubtree();
+ return;
+ }
+
+ OpenSearchEngine::Parameters parameters;
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (!isStartElement())
+ continue;
+
+ if (name() == QLatin1String("Param") || name() == QLatin1String("Parameter"))
+ readParameter(&parameters);
+ else
+ skipSubtree();
+ }
+
+ if (type == QLatin1String("application/x-suggestions+json")) {
+ m_engine->setSuggestionsUrlTemplate(url);
+ m_engine->setSuggestionsParameters(parameters);
+ m_engine->setSuggestionsMethod(method);
+ } else if (type == QLatin1String("text/html")) {
+ m_engine->setSearchUrlTemplate(url);
+ m_engine->setSearchParameters(parameters);
+ m_engine->setSearchMethod(method);
+ }
+}
+
+void OpenSearchReader::readParameter(OpenSearchEngine::Parameters *parameters)
+{
+ Q_ASSERT(isStartElement() && (name() == QLatin1String("Param") || name() == QLatin1String("Parameter")));
+
+ QString key = attributes().value(QLatin1String("name")).toString();
+ QString value = attributes().value(QLatin1String("value")).toString();
+
+ if (key.isEmpty() || value.isEmpty())
+ return;
+
+ parameters->append(OpenSearchEngine::Parameter(key, value));
+ readNext();
+}
+
+void OpenSearchReader::readImage()
+{
+ Q_ASSERT(isStartElement() && name() == QLatin1String("Image"));
+ m_engine->setImageUrl(readElementText());
+}
+
+void OpenSearchReader::readTags()
+{
+ Q_ASSERT(isStartElement() && name() == QLatin1String("Tags"));
+ m_engine->setTags(readElementText().split(QLatin1Char(' '), QString::SkipEmptyParts));
+}
+
+void OpenSearchReader::skipSubtree()
+{
+ Q_ASSERT(isStartElement());
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement())
+ skipSubtree();
+ }
+}
diff --git a/src/opensearch/opensearchreader.h b/src/opensearch/src/opensearchreader.h
index a4f11bc..fadcbc6 100644
--- a/src/opensearch/opensearchreader.h
+++ b/src/opensearch/src/opensearchreader.h
@@ -22,19 +22,26 @@
#include <qxmlstream.h>
-class OpenSearchEngine;
+#include "opensearchengine.h"
class OpenSearchReader : public QXmlStreamReader
{
public:
OpenSearchReader();
-
OpenSearchEngine *read(QIODevice *device);
private:
- OpenSearchEngine *read();
+ void readDocument();
+ void readName();
+ void readDescription();
+ void readUrl();
+ void readParameter(OpenSearchEngine::Parameters *parameters);
+ void readImage();
+ void readTags();
+ void skipSubtree();
+private:
+ OpenSearchEngine *m_engine;
};
#endif // OPENSEARCHREADER_H
-
diff --git a/src/opensearch/opensearchwriter.cpp b/src/opensearch/src/opensearchwriter.cpp
index 10b7c54..3877006 100644
--- a/src/opensearch/opensearchwriter.cpp
+++ b/src/opensearch/src/opensearchwriter.cpp
@@ -130,6 +130,9 @@ void OpenSearchWriter::write(OpenSearchEngine *engine)
if (!engine->imageUrl().isEmpty())
writeTextElement(QLatin1String("Image"), engine->imageUrl());
+ if (!engine->tags().isEmpty())
+ writeTextElement(QLatin1String("Tags"), engine->tags().join(QLatin1String(" ")));
+
writeEndElement();
writeEndDocument();
}
diff --git a/src/opensearch/opensearchwriter.h b/src/opensearch/src/opensearchwriter.h
index ab7fd61..fdd552f 100644
--- a/src/opensearch/opensearchwriter.h
+++ b/src/opensearch/src/opensearchwriter.h
@@ -37,4 +37,3 @@ private:
};
#endif // OPENSEARCHWRITER_H
-
diff --git a/src/opensearch/tests/opensearchengine/.gitignore b/src/opensearch/tests/opensearchengine/.gitignore
new file mode 100644
index 0000000..b4eb4cd
--- /dev/null
+++ b/src/opensearch/tests/opensearchengine/.gitignore
@@ -0,0 +1 @@
+tst_opensearchengine
diff --git a/src/opensearch/tests/opensearchengine/opensearchengine.pro b/src/opensearch/tests/opensearchengine/opensearchengine.pro
new file mode 100644
index 0000000..0c5f37b
--- /dev/null
+++ b/src/opensearch/tests/opensearchengine/opensearchengine.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = tst_opensearchengine
+
+QT += network
+
+include(../tests.pri)
+include(../../src/opensearch.pri)
+
+SOURCES += \
+ tst_opensearchengine.cpp
+
+RESOURCES += \
+ opensearchengine.qrc
diff --git a/src/opensearch/tests/opensearchengine/opensearchengine.qrc b/src/opensearch/tests/opensearchengine/opensearchengine.qrc
new file mode 100644
index 0000000..8d254e0
--- /dev/null
+++ b/src/opensearch/tests/opensearchengine/opensearchengine.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>suggestions.txt</file>
+</qresource>
+</RCC>
diff --git a/src/opensearch/tests/opensearchengine/suggestions.txt b/src/opensearch/tests/opensearchengine/suggestions.txt
new file mode 100644
index 0000000..73a1e67
--- /dev/null
+++ b/src/opensearch/tests/opensearchengine/suggestions.txt
@@ -0,0 +1 @@
+["sea", ["sears", "search engines", "search engine", "search", "sears.com", "seattle times"], ["7,390,000 results", "17,900,000 results", "25,700,000 results", "1,220,000,000 results", "1 result", "17,600,000 results"], ["http://example.com?q=sears", "http://example.com?q=search+engines", "http://example.com?q=search+engine", "http://example.com?q=search", "http://example.com?q=sears.com", "http://example.com?q=seattle+times"]] \ No newline at end of file
diff --git a/src/opensearch/tests/opensearchengine/tst_opensearchengine.cpp b/src/opensearch/tests/opensearchengine/tst_opensearchengine.cpp
new file mode 100644
index 0000000..5bf3e05
--- /dev/null
+++ b/src/opensearch/tests/opensearchengine/tst_opensearchengine.cpp
@@ -0,0 +1,910 @@
+/*
+ * Copyright 2009 Benjamin C. Meyer <ben@meyerhome.net>
+ * Copyright 2009 Jakub Wieczorek <faw217@gmail.com>
+ *
+ * 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 <qtest.h>
+#include "qtry.h"
+#include "opensearchengine.h"
+#include "opensearchenginedelegate.h"
+
+#include <qbuffer.h>
+#include <qfile.h>
+#include <qlocale.h>
+#include <qnetworkaccessmanager.h>
+#include <qnetworkreply.h>
+#include <qnetworkrequest.h>
+#include <qsignalspy.h>
+#include <qtimer.h>
+
+typedef OpenSearchEngine::Parameters Parameters;
+typedef OpenSearchEngine::Parameter Parameter;
+
+class tst_OpenSearchEngine : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void opensearchengine_data();
+ void opensearchengine();
+
+ void description_data();
+ void description();
+ void image();
+ void imageUrl_data();
+ void imageUrl();
+ void isValid_data();
+ void isValid();
+ void name_data();
+ void name();
+ void operatorlessthan();
+ void operatorequal_data();
+ void operatorequal();
+ void providesSuggestions_data();
+ void providesSuggestions();
+ void requestSuggestions_data();
+ void requestSuggestions();
+ void requestSuggestionsCrash();
+ void searchParameters_data();
+ void searchParameters();
+ void searchUrl_data();
+ void searchUrl();
+ void searchUrlTemplate_data();
+ void searchUrlTemplate();
+ void suggestionsParameters_data();
+ void suggestionsParameters();
+ void suggestionsUrl_data();
+ void suggestionsUrl();
+ void suggestionsUrlTemplate_data();
+ void suggestionsUrlTemplate();
+ void parseTemplate_data();
+ void parseTemplate();
+ void languageCodes_data();
+ void languageCodes();
+ void requestMethods();
+ void delegate();
+};
+
+// Subclass that exposes the protected functions.
+class SubOpenSearchEngine : public OpenSearchEngine
+{
+public:
+ void call_imageChanged()
+ { return SubOpenSearchEngine::imageChanged(); }
+
+ void call_loadImage() const
+ { return SubOpenSearchEngine::loadImage(); }
+
+ QString call_parseTemplate(QString const &searchTerm, QString const &searchTemplate) const
+ { return SubOpenSearchEngine::parseTemplate(searchTerm, searchTemplate); }
+
+ void call_suggestions(QStringList const &suggestions)
+ { return SubOpenSearchEngine::suggestions(suggestions); }
+};
+
+class SuggestionsTestNetworkReply : public QNetworkReply
+{
+ Q_OBJECT
+
+public:
+ SuggestionsTestNetworkReply(const QNetworkRequest &request, QObject *parent = 0)
+ : QNetworkReply(parent)
+ {
+ setOperation(QNetworkAccessManager::GetOperation);
+ setRequest(request);
+ setUrl(request.url());
+ setOpenMode(QIODevice::ReadOnly);
+
+ expectedResult.setFileName(":/suggestions.txt");
+ expectedResult.open(QIODevice::ReadOnly);
+ setError(QNetworkReply::NoError, tr("No Error"));
+
+ QTimer::singleShot(50, this, SLOT(sendSuggestions()));
+ }
+
+ ~SuggestionsTestNetworkReply()
+ {
+ close();
+ }
+
+ qint64 bytesAvailable() const
+ {
+ return expectedResult.bytesAvailable() + QNetworkReply::bytesAvailable();
+ }
+
+ void close()
+ {
+ expectedResult.close();
+ }
+
+ qint64 readData(char *data, qint64 maxSize)
+ {
+ return expectedResult.read(data, maxSize);
+ }
+
+ void abort()
+ {
+ }
+
+private slots:
+ void sendSuggestions()
+ {
+ // Publish result
+ setHeader(QNetworkRequest::ContentTypeHeader, QByteArray("text/html"));
+ setHeader(QNetworkRequest::ContentLengthHeader, expectedResult.bytesAvailable());
+ setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 200);
+ setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, QByteArray("Ok"));
+
+ emit metaDataChanged();
+ emit readyRead();
+ emit downloadProgress(expectedResult.size(), expectedResult.size());
+ emit finished();
+ }
+
+private:
+ QFile expectedResult;
+};
+
+class SuggestionsTestNetworkAccessManager : public QNetworkAccessManager
+{
+public:
+ SuggestionsTestNetworkAccessManager(QObject *parent = 0)
+ : QNetworkAccessManager(parent)
+ {
+ }
+
+ QNetworkRequest lastRequest;
+ Operation lastOperation;
+ bool lastOutgoingData;
+
+protected:
+ QNetworkReply *createRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, QIODevice *outgoingData = 0)
+ {
+ lastOperation = operation;
+ lastRequest = request;
+ lastOutgoingData = (bool)outgoingData;
+
+ return new SuggestionsTestNetworkReply(request, 0);
+ }
+};
+
+class Delegate : public OpenSearchEngineDelegate
+{
+ public:
+ Delegate()
+ : OpenSearchEngineDelegate()
+ , callsCount(0)
+ {
+ }
+
+ ~Delegate()
+ {
+ }
+
+ void performSearchRequest(const QNetworkRequest &request,
+ QNetworkAccessManager::Operation operation,
+ const QByteArray &data)
+ {
+ ++callsCount;
+ lastRequest = request;
+ lastOperation = operation;
+ lastData = data;
+ }
+
+ QNetworkRequest lastRequest;
+ QNetworkAccessManager::Operation lastOperation;
+ QByteArray lastData;
+ int callsCount;
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_OpenSearchEngine::initTestCase()
+{
+ QCoreApplication::setApplicationName("tst_opensearchengine");
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_OpenSearchEngine::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_OpenSearchEngine::init()
+{
+}
+
+// This will be called after every test function.
+void tst_OpenSearchEngine::cleanup()
+{
+}
+
+void tst_OpenSearchEngine::opensearchengine_data()
+{
+}
+
+void tst_OpenSearchEngine::opensearchengine()
+{
+ SubOpenSearchEngine engine;
+ QCOMPARE(engine.description(), QString());
+ QCOMPARE(engine.image(), QImage());
+ QCOMPARE(engine.imageUrl(), QString());
+ QCOMPARE(engine.isValid(), false);
+ QCOMPARE(engine.name(), QString());
+ OpenSearchEngine other;
+ QCOMPARE(engine.operator<(other), false);
+ QCOMPARE(engine.operator==(other), true);
+ QCOMPARE(engine.providesSuggestions(), false);
+ engine.requestSuggestions(QString());
+ QCOMPARE(engine.searchParameters(), QList<Parameter>());
+ QCOMPARE(engine.searchUrl(QString()), QUrl());
+ QCOMPARE(engine.searchUrlTemplate(), QString());
+ engine.setDescription(QString());
+ engine.setImage(QImage());
+ engine.setImageUrl(QString());
+ engine.setName(QString());
+ engine.setSearchParameters(QList<Parameter>());
+ engine.setSearchUrlTemplate(QString());
+ engine.setSuggestionsParameters(QList<Parameter>());
+ engine.setSuggestionsUrlTemplate(QString());
+ QCOMPARE(engine.suggestionsParameters(), QList<Parameter>());
+ QCOMPARE(engine.suggestionsUrl(QString()), QUrl());
+ QCOMPARE(engine.suggestionsUrlTemplate(), QString());
+ QCOMPARE(engine.tags(), QStringList());
+ engine.setTags(QStringList() << "foo" << "bar");
+ QCOMPARE(engine.tags(), QStringList() << "foo" << "bar");
+ engine.call_imageChanged();
+ engine.call_loadImage();
+ QVERIFY(!engine.networkAccessManager());
+ QNetworkAccessManager manager;
+ engine.setNetworkAccessManager(&manager);
+ QCOMPARE(engine.networkAccessManager(), &manager);
+ QCOMPARE(engine.call_parseTemplate(QString(), QString()), QString());
+ engine.call_suggestions(QStringList());
+}
+
+void tst_OpenSearchEngine::description_data()
+{
+ QTest::addColumn<QString>("description");
+ QTest::newRow("null") << QString();
+ QTest::newRow("foo") << QString("foo");
+}
+
+// public QString description() const
+void tst_OpenSearchEngine::description()
+{
+ QFETCH(QString, description);
+
+ SubOpenSearchEngine engine;
+
+ QSignalSpy spy0(&engine, SIGNAL(imageChanged()));
+ QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&)));
+
+ engine.setDescription(description);
+ QCOMPARE(engine.description(), description);
+ QCOMPARE(engine.property("description").toString(), description);
+ engine.setProperty("description", QString());
+ QCOMPARE(engine.property("description").toString(), QString());
+
+ QCOMPARE(spy0.count(), 0);
+ QCOMPARE(spy1.count(), 0);
+}
+
+// public QImage image() const
+void tst_OpenSearchEngine::image()
+{
+ SubOpenSearchEngine engine;
+
+ QNetworkAccessManager manager;
+ engine.setNetworkAccessManager(&manager);
+
+ QSignalSpy spy0(&engine, SIGNAL(imageChanged()));
+ QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&)));
+
+ QBuffer imageBuffer;
+ imageBuffer.open(QBuffer::ReadWrite);
+ QPixmap image(1, 1);
+ image.fill();
+ image.save(&imageBuffer, "PNG");
+ QString imageUrl = QString("data:image/png;base64,").append(imageBuffer.buffer().toBase64());
+ engine.setImageUrl(imageUrl);
+ QCOMPARE(engine.image(), QImage());
+
+ QTRY_COMPARE(spy0.count(), 1);
+ QCOMPARE(spy1.count(), 0);
+ QVERIFY(engine.image() != QImage());
+
+ SubOpenSearchEngine engine2;
+ QSignalSpy spy2(&engine2, SIGNAL(imageChanged()));
+
+ QVERIFY(engine2.imageUrl().isEmpty());
+ engine2.setImage(engine.image());
+ QCOMPARE(engine2.imageUrl(), imageUrl);
+
+ QCOMPARE(spy2.count(), 1);
+}
+
+void tst_OpenSearchEngine::imageUrl_data()
+{
+ QTest::addColumn<QString>("imageUrl");
+ QTest::newRow("null") << QString();
+ QTest::newRow("foo") << QString("foo");
+}
+
+// public QString imageUrl() const
+void tst_OpenSearchEngine::imageUrl()
+{
+ QFETCH(QString, imageUrl);
+
+ SubOpenSearchEngine engine;
+
+ QSignalSpy spy0(&engine, SIGNAL(imageChanged()));
+ QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&)));
+
+ engine.setImageUrl(imageUrl);
+ QCOMPARE(engine.imageUrl(), imageUrl);
+ QCOMPARE(engine.property("imageUrl").toString(), imageUrl);
+ engine.setProperty("imageUrl", QString());
+ QCOMPARE(engine.property("imageUrl").toString(), QString());
+
+ QCOMPARE(spy0.count(), 0);
+ QCOMPARE(spy1.count(), 0);
+}
+
+void tst_OpenSearchEngine::isValid_data()
+{
+ QTest::addColumn<QString>("name");
+ QTest::addColumn<QString>("searchUrlTemplate");
+ QTest::addColumn<bool>("isValid");
+ QTest::newRow("false-0") << QString() << QString() << false;
+ QTest::newRow("false-1") << QString() << QString("x") << false;
+ QTest::newRow("false-2") << QString("x") << QString() << false;
+ QTest::newRow("true") << QString("x") << QString("y") << true;
+}
+
+// public bool isValid() const
+void tst_OpenSearchEngine::isValid()
+{
+ QFETCH(QString, name);
+ QFETCH(QString, searchUrlTemplate);
+ QFETCH(bool, isValid);
+
+ SubOpenSearchEngine engine;
+
+ QSignalSpy spy0(&engine, SIGNAL(imageChanged()));
+ QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&)));
+
+ engine.setName(name);
+ engine.setSearchUrlTemplate(searchUrlTemplate);
+ QCOMPARE(engine.isValid(), isValid);
+
+ QCOMPARE(spy0.count(), 0);
+ QCOMPARE(spy1.count(), 0);
+}
+
+void tst_OpenSearchEngine::name_data()
+{
+ QTest::addColumn<QString>("name");
+ QTest::newRow("null") << QString();
+ QTest::newRow("foo") << QString("foo");
+}
+
+// public QString name() const
+void tst_OpenSearchEngine::name()
+{
+ QFETCH(QString, name);
+
+ SubOpenSearchEngine engine;
+
+ QSignalSpy spy0(&engine, SIGNAL(imageChanged()));
+ QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&)));
+
+ engine.setName(name);
+ QCOMPARE(engine.name(), name);
+ QCOMPARE(engine.property("name").toString(), name);
+ engine.setProperty("name", QString());
+ QCOMPARE(engine.property("name").toString(), QString());
+
+ QCOMPARE(spy0.count(), 0);
+ QCOMPARE(spy1.count(), 0);
+}
+
+// public bool operator<(OpenSearchEngine const &other) const
+void tst_OpenSearchEngine::operatorlessthan()
+{
+ SubOpenSearchEngine engine1;
+ engine1.setName("a");
+ SubOpenSearchEngine engine2;
+ engine2.setName("b");
+
+ QVERIFY(engine1 < engine2);
+}
+
+Q_DECLARE_METATYPE(Parameters)
+void tst_OpenSearchEngine::operatorequal_data()
+{
+ QTest::addColumn<QString>("name");
+ QTest::addColumn<QString>("description");
+ QTest::addColumn<QString>("imageUrl");
+ QTest::addColumn<QString>("searchUrlTemplate");
+ QTest::addColumn<QString>("suggestionsUrlTemplate");
+ QTest::addColumn<Parameters>("searchParameters");
+ QTest::addColumn<Parameters>("suggestionsParameters");
+ QTest::addColumn<bool>("operatorequal");
+ QTest::newRow("null") << QString() << QString() << QString() << QString() << QString()
+ << Parameters() << Parameters()
+ << true;
+ QTest::newRow("name") << QString("x") << QString() << QString() << QString() << QString()
+ << Parameters() << Parameters()
+ << false;
+ QTest::newRow("description") << QString() << QString("x") << QString() << QString() << QString()
+ << Parameters() << Parameters()
+ << false;
+ QTest::newRow("imageUrl") << QString() << QString() << QString("x") << QString() << QString()
+ << Parameters() << Parameters()
+ << false;
+ QTest::newRow("parameters") << QString() << QString() << QString() << QString() << QString()
+ << (Parameters() << Parameter("a", "b")) << Parameters()
+ << false;
+}
+
+// public bool operator==(OpenSearchEngine const &other) const
+void tst_OpenSearchEngine::operatorequal()
+{
+ QFETCH(QString, name);
+ QFETCH(QString, description);
+ QFETCH(QString, imageUrl);
+ QFETCH(QString, searchUrlTemplate);
+ QFETCH(QString, suggestionsUrlTemplate);
+ QFETCH(Parameters, searchParameters);
+ QFETCH(Parameters, suggestionsParameters);
+ QFETCH(bool, operatorequal);
+
+ SubOpenSearchEngine engine;
+ SubOpenSearchEngine other;
+ other.setName(name);
+ other.setDescription(description);
+ other.setImageUrl(imageUrl);
+ other.setSearchUrlTemplate(searchUrlTemplate);
+ other.setSuggestionsUrlTemplate(suggestionsUrlTemplate);
+ other.setSearchParameters(searchParameters);
+ other.setSuggestionsParameters(suggestionsParameters);
+
+ QCOMPARE(engine.operator==(other), operatorequal);
+}
+
+void tst_OpenSearchEngine::providesSuggestions_data()
+{
+ QTest::addColumn<QString>("suggestionsUrlTemplate");
+ QTest::addColumn<bool>("providesSuggestions");
+ QTest::newRow("false") << QString() << false;
+ QTest::newRow("true") << QString("foo") << true;
+}
+
+// public bool providesSuggestions() const
+void tst_OpenSearchEngine::providesSuggestions()
+{
+ QFETCH(QString, suggestionsUrlTemplate);
+ QFETCH(bool, providesSuggestions);
+
+ SubOpenSearchEngine engine;
+
+ QSignalSpy spy0(&engine, SIGNAL(imageChanged()));
+ QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&)));
+
+ engine.setSuggestionsUrlTemplate(suggestionsUrlTemplate);
+ QCOMPARE(engine.providesSuggestions(), providesSuggestions);
+
+ QCOMPARE(spy0.count(), 0);
+ QCOMPARE(spy1.count(), 0);
+}
+
+void tst_OpenSearchEngine::requestSuggestions_data()
+{
+ QTest::addColumn<QString>("searchTerm");
+ QTest::addColumn<QString>("method");
+ QTest::addColumn<QNetworkAccessManager::Operation>("lastOperation");
+ QTest::newRow("null") << QString() << QString() << QNetworkAccessManager::GetOperation;
+ QTest::newRow("foo") << QString("foo") << QString("get") << QNetworkAccessManager::GetOperation;
+ QTest::newRow("bar") << QString("bar") << QString("post") << QNetworkAccessManager::PostOperation;
+ QTest::newRow("baz") << QString("baz") << QString("put") << QNetworkAccessManager::GetOperation;
+}
+
+Q_DECLARE_METATYPE(QNetworkAccessManager::Operation)
+// public void requestSuggestions(QString const &searchTerm)
+void tst_OpenSearchEngine::requestSuggestions()
+{
+ QFETCH(QString, searchTerm);
+ QFETCH(QString, method);
+ QFETCH(QNetworkAccessManager::Operation, lastOperation);
+
+ SuggestionsTestNetworkAccessManager manager;
+ SubOpenSearchEngine engine;
+ engine.setNetworkAccessManager(&manager);
+ engine.setSuggestionsMethod(method);
+ engine.setSuggestionsUrlTemplate("http://foobar.baz");
+ engine.setSuggestionsParameters(Parameters() << Parameter("a", "b"));
+
+ QVERIFY(engine.providesSuggestions());
+
+ QSignalSpy spy(&engine, SIGNAL(suggestions(QStringList const&)));
+
+ engine.requestSuggestions(searchTerm);
+
+ if (searchTerm.isEmpty()) {
+ QTest::qWait(200);
+ QCOMPARE(spy.count(), 0);
+ } else {
+ QTRY_COMPARE(spy.count(), 1);
+
+ QStringList suggestions;
+ suggestions << "sears" << "search engines" << "search engine" << "search" << "sears.com" << "seattle times";
+ QCOMPARE(spy.at(0).at(0).toStringList(), suggestions);
+
+ QCOMPARE(manager.lastOperation, lastOperation);
+ QCOMPARE(manager.lastOutgoingData, lastOperation == QNetworkAccessManager::PostOperation);
+ }
+}
+
+void tst_OpenSearchEngine::requestSuggestionsCrash()
+{
+ SuggestionsTestNetworkAccessManager manager;
+ SubOpenSearchEngine engine;
+ engine.setNetworkAccessManager(&manager);
+ engine.setSuggestionsUrlTemplate("http://foobar.baz");
+
+ QVERIFY(engine.providesSuggestions());
+
+ QSignalSpy spy(&engine, SIGNAL(suggestions(QStringList const&)));
+
+ QStringList colors = QColor::colorNames();
+
+ for (int i = 0; i < colors.count(); ++i)
+ engine.requestSuggestions(colors.at(i));
+
+ QTRY_COMPARE(spy.count(), 1);
+
+ QStringList suggestions;
+ suggestions << "sears" << "search engines" << "search engine" << "search" << "sears.com" << "seattle times";
+ QCOMPARE(spy.at(0).at(0).toStringList(), suggestions);
+}
+
+void tst_OpenSearchEngine::searchParameters_data()
+{
+ QTest::addColumn<Parameters>("searchParameters");
+ QTest::newRow("null") << QList<Parameter>();
+ QTest::newRow("something") << (Parameters() << Parameter("a", "b"));
+}
+
+// public QList<Parameter> searchParameters() const
+void tst_OpenSearchEngine::searchParameters()
+{
+ QFETCH(Parameters, searchParameters);
+
+ SubOpenSearchEngine engine;
+
+ QSignalSpy spy0(&engine, SIGNAL(imageChanged()));
+ QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&)));
+
+ engine.setSearchParameters(searchParameters);
+ QCOMPARE(engine.searchParameters(), searchParameters);
+ QCOMPARE(qvariant_cast<Parameters>(engine.property("searchParameters")), searchParameters);
+
+ QCOMPARE(spy0.count(), 0);
+ QCOMPARE(spy1.count(), 0);
+}
+
+void tst_OpenSearchEngine::searchUrl_data()
+{
+ QTest::addColumn<QString>("searchTerm");
+ QTest::addColumn<QString>("searchUrlTemplate");
+ QTest::addColumn<Parameters>("parameters");
+ QTest::addColumn<QUrl>("searchUrl");
+ QTest::newRow("null") << QString() << QString() << Parameters() << QUrl();
+ QTest::newRow("foo") << QString("foo") << QString("http://foobar.baz/?q={searchTerms}")
+ << Parameters() << QUrl(QString("http://foobar.baz/?q=foo"));
+ QTest::newRow("empty") << QString() << QString("http://foobar.baz/?q={searchTerms}")
+ << Parameters() << QUrl(QString("http://foobar.baz/?q="));
+ QTest::newRow("parameters") << QString("baz") << QString("http://foobar.baz/?q={searchTerms}")
+ << (Parameters() << Parameter("abc", "{searchTerms}") << Parameter("x", "yz"))
+ << QUrl(QString("http://foobar.baz/?q=baz&abc=baz&x=yz"));
+}
+
+// public QUrl searchUrl(QString const &searchTerm) const
+void tst_OpenSearchEngine::searchUrl()
+{
+ QFETCH(QString, searchTerm);
+ QFETCH(QString, searchUrlTemplate);
+ QFETCH(Parameters, parameters);
+ QFETCH(QUrl, searchUrl);
+
+ SubOpenSearchEngine engine;
+ engine.setSearchParameters(parameters);
+ engine.setSearchUrlTemplate(searchUrlTemplate);
+
+ QCOMPARE(engine.searchUrl(searchTerm), searchUrl);
+}
+
+void tst_OpenSearchEngine::searchUrlTemplate_data()
+{
+ QTest::addColumn<QString>("searchUrlTemplate");
+ QTest::newRow("null") << QString();
+ QTest::newRow("foo") << QString("foo");
+}
+
+// public QString searchUrlTemplate() const
+void tst_OpenSearchEngine::searchUrlTemplate()
+{
+ QFETCH(QString, searchUrlTemplate);
+
+ SubOpenSearchEngine engine;
+
+ QSignalSpy spy0(&engine, SIGNAL(imageChanged()));
+ QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&)));
+
+ engine.setSearchUrlTemplate(searchUrlTemplate);
+ QCOMPARE(engine.property("searchUrlTemplate").toString(), searchUrlTemplate);
+ engine.setProperty("searchUrlTemplate", QString());
+ QCOMPARE(engine.property("searchUrlTemplate").toString(), QString());
+ engine.setProperty("searchUrlTemplate", searchUrlTemplate);
+ QCOMPARE(engine.searchUrlTemplate(), searchUrlTemplate);
+
+ QCOMPARE(spy0.count(), 0);
+ QCOMPARE(spy1.count(), 0);
+}
+
+void tst_OpenSearchEngine::suggestionsParameters_data()
+{
+ QTest::addColumn<Parameters>("suggestionsParameters");
+ QTest::newRow("null") << QList<Parameter>();
+ QTest::newRow("something") << (Parameters() << Parameter("a", "b"));
+}
+
+// public QList<Parameter> suggestionsParameters() const
+void tst_OpenSearchEngine::suggestionsParameters()
+{
+ QFETCH(Parameters, suggestionsParameters);
+
+ SubOpenSearchEngine engine;
+
+ QSignalSpy spy0(&engine, SIGNAL(imageChanged()));
+ QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&)));
+
+ engine.setSuggestionsParameters(suggestionsParameters);
+ QCOMPARE(engine.suggestionsParameters(), suggestionsParameters);
+
+ QCOMPARE(spy0.count(), 0);
+ QCOMPARE(spy1.count(), 0);
+}
+
+void tst_OpenSearchEngine::suggestionsUrl_data()
+{
+ QTest::addColumn<QString>("searchTerm");
+ QTest::addColumn<QString>("suggestionsUrlTemplate");
+ QTest::addColumn<Parameters>("parameters");
+ QTest::addColumn<QUrl>("suggestionsUrl");
+ QTest::newRow("null") << QString() << QString() << Parameters() << QUrl();
+ QTest::newRow("foo") << QString("foo") << QString("http://foobar.baz/?q={searchTerms}")
+ << Parameters() << QUrl(QString("http://foobar.baz/?q=foo"));
+ QTest::newRow("empty") << QString() << QString("http://foobar.baz/?q={searchTerms}")
+ << Parameters() << QUrl(QString("http://foobar.baz/?q="));
+ QTest::newRow("parameters") << QString("baz") << QString("http://foobar.baz/?q={searchTerms}")
+ << (Parameters() << Parameter("a", "bc"))
+ << QUrl(QString("http://foobar.baz/?q=baz&a=bc"));
+}
+
+// public QUrl suggestionsUrl(QString const &searchTerm) const
+void tst_OpenSearchEngine::suggestionsUrl()
+{
+ QFETCH(QString, searchTerm);
+ QFETCH(QString, suggestionsUrlTemplate);
+ QFETCH(Parameters, parameters);
+ QFETCH(QUrl, suggestionsUrl);
+
+ SubOpenSearchEngine engine;
+ engine.setSuggestionsParameters(parameters);
+ engine.setSuggestionsUrlTemplate(suggestionsUrlTemplate);
+
+ QCOMPARE(engine.suggestionsUrl(searchTerm), suggestionsUrl);
+}
+
+void tst_OpenSearchEngine::suggestionsUrlTemplate_data()
+{
+ QTest::addColumn<QString>("suggestionsUrlTemplate");
+ QTest::newRow("null") << QString();
+ QTest::newRow("foo") << QString("foo");
+}
+
+// public QString suggestionsUrlTemplate() const
+void tst_OpenSearchEngine::suggestionsUrlTemplate()
+{
+ QFETCH(QString, suggestionsUrlTemplate);
+
+ SubOpenSearchEngine engine;
+
+ QSignalSpy spy0(&engine, SIGNAL(imageChanged()));
+ QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&)));
+
+ engine.setSuggestionsUrlTemplate(suggestionsUrlTemplate);
+ QCOMPARE(engine.suggestionsUrlTemplate(), suggestionsUrlTemplate);
+
+ QCOMPARE(spy0.count(), 0);
+ QCOMPARE(spy1.count(), 0);
+}
+
+void tst_OpenSearchEngine::parseTemplate_data()
+{
+ QString lang = QLocale().name().replace(QLatin1Char('_'), QLatin1Char('-'));
+
+ QTest::addColumn<QString>("searchTerm");
+ QTest::addColumn<QString>("searchTemplate");
+ QTest::addColumn<QString>("parseTemplate");
+ QTest::addColumn<bool>("valid");
+ QTest::newRow("null") << QString() << QString() << QString() << false;
+ QTest::newRow("foo") << QString("foo") << QString("http://foobar.baz/?q={searchTerms}")
+ << QString("http://foobar.baz/?q=foo") << true;
+ QTest::newRow("allParameters") << QString("bar")
+ << QString("http://foobar.baz/?st={searchTerms}&amp;c={count}"
+ "&amp;si={startIndex}&amp;sp={startPage}&amp;l={language}"
+ "&amp;ie={inputEncoding}&amp;oe={outputEncoding}")
+ << QString("http://foobar.baz/?st=bar&amp;c=20&amp;si=0&amp;"
+ "sp=0&amp;l=%1&amp;ie=UTF-8&amp;oe=UTF-8").arg(lang)
+ << true;
+ QTest::newRow("tricky") << QString("{count}") << QString("http://foobar.baz/q={searchTerms}&amp;count={count}")
+ << QString("http://foobar.baz/q=%7Bcount%7D&amp;count=20") << true;
+ QTest::newRow("multiple") << QString("abc") << QString("http://foobar.baz/?q={searchTerms}&amp;x={searchTerms}")
+ << QString("http://foobar.baz/?q=abc&amp;x=abc") << true;
+ QTest::newRow("referrer") << QString("foo")
+ << QString("http://foobar.baz/?q={searchTerms}&amp;a={source}&amp;b={ref:source}&amp;c={referrer:source?}")
+ << QString("http://foobar.baz/?q=foo&amp;a=tst_opensearchengine"
+ "&amp;b=tst_opensearchengine&amp;c=tst_opensearchengine")
+ << true;
+ QTest::newRow("inputEncoding") << QString("c++") << QString("http://foobar.baz/?q={searchTerms}")
+ << QString("http://foobar.baz/?q=c%2B%2B") << true;
+}
+
+// protected QString parseTemplate(QString const &searchTerm, QString const &searchTemplate) const
+void tst_OpenSearchEngine::parseTemplate()
+{
+ QFETCH(QString, searchTerm);
+ QFETCH(QString, searchTemplate);
+ QFETCH(QString, parseTemplate);
+ QFETCH(bool, valid);
+
+ SubOpenSearchEngine engine;
+ QString url = engine.call_parseTemplate(searchTerm, searchTemplate);
+ QCOMPARE(url, parseTemplate);
+ QCOMPARE(QUrl(url).isValid(), valid);
+}
+
+void tst_OpenSearchEngine::languageCodes_data()
+{
+ QTest::addColumn<QString>("languageCode");
+ QTest::addColumn<QString>("url");
+
+ QTest::newRow("es") << QString("es") << QString("http://foobar.baz/?l=es-ES");
+ QTest::newRow("pt_BR") << QString("pt_BR") << QString("http://foobar.baz/?l=pt-BR");
+}
+
+void tst_OpenSearchEngine::languageCodes()
+{
+ QFETCH(QString, languageCode);
+ QFETCH(QString, url);
+
+ QLocale::setDefault(QLocale(languageCode));
+
+ SubOpenSearchEngine engine;
+ QCOMPARE(engine.call_parseTemplate(QString("foo"), QString("http://foobar.baz/?l={language}")), url);
+}
+
+void tst_OpenSearchEngine::requestMethods()
+{
+ SubOpenSearchEngine engine;
+
+ QCOMPARE(engine.searchMethod(), QString("get"));
+ QCOMPARE(engine.suggestionsMethod(), QString("get"));
+
+ engine.setSearchMethod("post");
+ QCOMPARE(engine.searchMethod(), QString("post"));
+ QCOMPARE(engine.suggestionsMethod(), QString("get"));
+
+ engine.setSearchMethod("get");
+ QCOMPARE(engine.searchMethod(), QString("get"));
+ QCOMPARE(engine.suggestionsMethod(), QString("get"));
+
+ engine.setSuggestionsMethod("PoSt");
+ QCOMPARE(engine.searchMethod(), QString("get"));
+ QCOMPARE(engine.suggestionsMethod(), QString("post"));
+
+ engine.setSearchMethod("foo");
+ QCOMPARE(engine.searchMethod(), QString("get"));
+ QCOMPARE(engine.suggestionsMethod(), QString("post"));
+
+ engine.setSuggestionsMethod("bar");
+ QCOMPARE(engine.searchMethod(), QString("get"));
+ QCOMPARE(engine.suggestionsMethod(), QString("post"));
+}
+
+void tst_OpenSearchEngine::delegate()
+{
+ SubOpenSearchEngine engine;
+ engine.setName(QString("foo"));
+ engine.setDescription(QString("bar"));
+ engine.setSearchUrlTemplate(QString("http://foobar.baz/?q={searchTerms}"));
+
+ QCOMPARE(engine.delegate(), (Delegate*)0);
+ engine.setDelegate(0);
+ QCOMPARE(engine.delegate(), (Delegate*)0);
+ engine.requestSearchResults(QString("baz"));
+
+ Delegate delegate;
+ engine.setDelegate(&delegate);
+ QCOMPARE(engine.delegate(), &delegate);
+ engine.requestSearchResults(QString("baz"));
+
+ QCOMPARE(delegate.callsCount, 1);
+ QCOMPARE(delegate.lastOperation, QNetworkAccessManager::GetOperation);
+ QCOMPARE(delegate.lastData, QByteArray());
+ QNetworkRequest request(QUrl(engine.call_parseTemplate(QString("baz"), engine.searchUrlTemplate())));
+ QCOMPARE(delegate.lastRequest, request);
+ QVERIFY(delegate.lastRequest.url().hasQueryItem("q"));
+ QCOMPARE(delegate.lastRequest.url().queryItemValue("q"), QString("baz"));
+
+ engine.setSearchParameters(Parameters() << Parameter("a", "b") << Parameter("b", "c"));
+ engine.requestSearchResults(QString("baz"));
+
+ QCOMPARE(delegate.callsCount, 2);
+ QCOMPARE(delegate.lastOperation, QNetworkAccessManager::GetOperation);
+ QCOMPARE(delegate.lastData, QByteArray());
+
+ QVERIFY(delegate.lastRequest.url().hasQueryItem("a"));
+ QCOMPARE(delegate.lastRequest.url().queryItemValue("a"), QString("b"));
+ QVERIFY(delegate.lastRequest.url().hasQueryItem("b"));
+ QCOMPARE(delegate.lastRequest.url().queryItemValue("b"), QString("c"));
+ QVERIFY(delegate.lastRequest.url().hasQueryItem("q"));
+ QCOMPARE(delegate.lastRequest.url().queryItemValue("q"), QString("baz"));
+
+ QUrl url(engine.call_parseTemplate(QString("baz"), engine.searchUrlTemplate()));
+ QCOMPARE(delegate.lastRequest.url().toString(QUrl::RemoveQuery), url.toString(QUrl::RemoveQuery));
+
+ engine.setSearchMethod(QString("post"));
+ engine.requestSearchResults(QString("baz"));
+
+ QCOMPARE(delegate.callsCount, 3);
+ QCOMPARE(delegate.lastOperation, QNetworkAccessManager::PostOperation);
+ request = QNetworkRequest(QUrl(engine.call_parseTemplate(QString("baz"), engine.searchUrlTemplate())));
+ QCOMPARE(delegate.lastRequest, request);
+ QVERIFY(delegate.lastRequest.url().hasQueryItem("q"));
+ QCOMPARE(delegate.lastRequest.url().queryItemValue("q"), QString("baz"));
+
+ QVERIFY(!delegate.lastData.isEmpty());
+ QStringList query = QString(delegate.lastData).split('&');
+ QCOMPARE(query.count(), 2);
+ QCOMPARE(query, QStringList() << "a=b" << "b=c");
+}
+
+QTEST_MAIN(tst_OpenSearchEngine)
+#include "tst_opensearchengine.moc"
+
diff --git a/src/opensearch/tests/opensearchreader/.gitignore b/src/opensearch/tests/opensearchreader/.gitignore
new file mode 100644
index 0000000..bcc3fd0
--- /dev/null
+++ b/src/opensearch/tests/opensearchreader/.gitignore
@@ -0,0 +1 @@
+tst_opensearchreader
diff --git a/src/opensearch/tests/opensearchreader/opensearchreader.pro b/src/opensearch/tests/opensearchreader/opensearchreader.pro
new file mode 100644
index 0000000..cb17f92
--- /dev/null
+++ b/src/opensearch/tests/opensearchreader/opensearchreader.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+TARGET = tst_opensearchreader
+
+include(../tests.pri)
+include(../../src/opensearch.pri)
+
+SOURCES += \
+ tst_opensearchreader.cpp
+
+RESOURCES += \
+ opensearchreader.qrc
diff --git a/src/opensearch/tests/opensearchreader/opensearchreader.qrc b/src/opensearch/tests/opensearchreader/opensearchreader.qrc
new file mode 100644
index 0000000..ad2044c
--- /dev/null
+++ b/src/opensearch/tests/opensearchreader/opensearchreader.qrc
@@ -0,0 +1,12 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>testfile1.xml</file>
+ <file>testfile2.xml</file>
+ <file>testfile3.xml</file>
+ <file>testfile4.xml</file>
+ <file>testfile5.xml</file>
+ <file>testfile6.xml</file>
+ <file>testfile7.xml</file>
+ <file>testfile8.xml</file>
+</qresource>
+</RCC>
diff --git a/src/opensearch/tests/opensearchreader/testfile1.xml b/src/opensearch/tests/opensearchreader/testfile1.xml
new file mode 100644
index 0000000..ee1ed1c
--- /dev/null
+++ b/src/opensearch/tests/opensearchreader/testfile1.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+ <ShortName>Wikipedia (en)</ShortName>
+ <Description >Full text search in the English Wikipedia</Description>
+ <Url method="get" type="application/rss+xml" template="http://en.wikipedia.org/rss" />
+ <Url method="post" type="text/html" template="http://en.wikipedia.org/bar" />
+ <Url method="get" type="application/x-suggestions+json" template="http://en.wikipedia.org/foo" />
+ <Url method="get" template="http://en.wikipedia.org/baz" />
+ <Image width="16" height="16">http://en.wikipedia.org/favicon.ico</Image>
+</OpenSearchDescription> \ No newline at end of file
diff --git a/src/opensearch/tests/opensearchreader/testfile2.xml b/src/opensearch/tests/opensearchreader/testfile2.xml
new file mode 100644
index 0000000..0a620b4
--- /dev/null
+++ b/src/opensearch/tests/opensearchreader/testfile2.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+ <ShortName>Wikipedia (en)</ShortName>
+ <Url method="get" type="application/x-suggestions+json" template="http://en.wikipedia.org/foo" />
+ <Image width="16" height="16">http://en.wikipedia.org/favicon.ico</Image>
+</OpenSearchDescription> \ No newline at end of file
diff --git a/src/opensearch/tests/opensearchreader/testfile3.xml b/src/opensearch/tests/opensearchreader/testfile3.xml
new file mode 100644
index 0000000..c778e26
--- /dev/null
+++ b/src/opensearch/tests/opensearchreader/testfile3.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+ <ShortName>GitHub</ShortName>
+ <Description>Search GitHub</Description>
+ <Url type="text/html" method="get" template="http://github.com/search">
+ <Param name="q" value="{searchTerms}"/>
+ <Parameter name="b" value="foo"/>
+ </Url>
+ <Url method="post" type="application/x-suggestions+json" template="http://github.com/suggestions">
+ <Parameter name="bar" value="baz"/>
+ </Url>
+</OpenSearchDescription> \ No newline at end of file
diff --git a/src/opensearch/tests/opensearchreader/testfile4.xml b/src/opensearch/tests/opensearchreader/testfile4.xml
new file mode 100644
index 0000000..9c484a2
--- /dev/null
+++ b/src/opensearch/tests/opensearchreader/testfile4.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+ <ShortName>Google</ShortName>
+ <Description>Google Web Search</Description>
+ <Url method="get" type="text/html" template="http://www.google.com/search?bar" />
+ <Url method="get" type="application/x-suggestions+json" template="http://suggestqueries.google.com/complete/foo" />
+ <Image width="16" height="16">http://www.google.com/favicon.ico</Image>
+</OpenSearchDescription> \ No newline at end of file
diff --git a/src/opensearch/tests/opensearchreader/testfile5.xml b/src/opensearch/tests/opensearchreader/testfile5.xml
new file mode 100644
index 0000000..266e4b1
--- /dev/null
+++ b/src/opensearch/tests/opensearchreader/testfile5.xml
@@ -0,0 +1 @@
+<foo><bar></bar></foo> \ No newline at end of file
diff --git a/src/opensearch/tests/opensearchreader/testfile6.xml b/src/opensearch/tests/opensearchreader/testfile6.xml
new file mode 100644
index 0000000..4495beb
--- /dev/null
+++ b/src/opensearch/tests/opensearchreader/testfile6.xml
@@ -0,0 +1,5 @@
+<OpenSearchDescription>
+ <ShortName>Google</ShortName>
+ <Description>Google Web Search</Description>
+ <Url method="get" type="text/html" template="http://www.google.com/search?bar" />
+</OpenSearchDescription> \ No newline at end of file
diff --git a/src/opensearch/tests/opensearchreader/testfile7.xml b/src/opensearch/tests/opensearchreader/testfile7.xml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/opensearch/tests/opensearchreader/testfile7.xml
diff --git a/src/opensearch/tests/opensearchreader/testfile8.xml b/src/opensearch/tests/opensearchreader/testfile8.xml
new file mode 100644
index 0000000..c203851
--- /dev/null
+++ b/src/opensearch/tests/opensearchreader/testfile8.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+ <ShortName>Web Search</ShortName>
+ <Description>Use Example.com to search the Web.</Description>
+ <Tags>example web</Tags>
+ <!-- <Contact>admin@example.com</Contact> -->
+ <Url type="text/html" template="http://example.com/"/>
+</OpenSearchDescription> \ No newline at end of file
diff --git a/src/opensearch/tests/opensearchreader/tst_opensearchreader.cpp b/src/opensearch/tests/opensearchreader/tst_opensearchreader.cpp
new file mode 100644
index 0000000..8b0f677
--- /dev/null
+++ b/src/opensearch/tests/opensearchreader/tst_opensearchreader.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2009 Jakub Wieczorek <faw217@gmail.com>
+ *
+ * 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 <QtTest/QtTest>
+
+#include "opensearchreader.h"
+#include "opensearchengine.h"
+
+typedef OpenSearchEngine::Parameters Parameters;
+typedef OpenSearchEngine::Parameter Parameter;
+
+class tst_OpenSearchReader : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void read_data();
+ void read();
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_OpenSearchReader::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_OpenSearchReader::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_OpenSearchReader::init()
+{
+}
+
+// This will be called after every test function.
+void tst_OpenSearchReader::cleanup()
+{
+}
+
+Q_DECLARE_METATYPE(Parameters)
+void tst_OpenSearchReader::read_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<QString>("name");
+ QTest::addColumn<QString>("description");
+ QTest::addColumn<QString>("searchUrlTemplate");
+ QTest::addColumn<QString>("suggestionsUrlTemplate");
+ QTest::addColumn<QString>("imageUrl");
+ QTest::addColumn<Parameters>("searchParameters");
+ QTest::addColumn<Parameters>("suggestionsParameters");
+ QTest::addColumn<QString>("searchMethod");
+ QTest::addColumn<QString>("suggestionsMethod");
+ QTest::addColumn<QStringList>("tags");
+
+ QTest::newRow("null") << QString(":/doesNotExist") << false << QString() << QString() << QString() << QString()
+ << QString() << Parameters() << Parameters() << QString("get")
+ << QString("get") << QStringList();
+
+ QTest::newRow("testfile1") << QString(":/testfile1.xml") << true << QString("Wikipedia (en)")
+ << QString("Full text search in the English Wikipedia") << QString("http://en.wikipedia.org/bar")
+ << QString("http://en.wikipedia.org/foo") << QString("http://en.wikipedia.org/favicon.ico")
+ << Parameters() << Parameters() << QString("post")
+ << QString("get") << QStringList();
+
+ QTest::newRow("testfile2") << QString(":/testfile2.xml") << false << QString("Wikipedia (en)")
+ << QString() << QString() << QString("http://en.wikipedia.org/foo") << QString("http://en.wikipedia.org/favicon.ico")
+ << Parameters() << Parameters() << QString("get")
+ << QString("get") << QStringList();
+
+ QTest::newRow("testfile3") << QString(":/testfile3.xml") << true << QString("GitHub") << QString("Search GitHub")
+ << QString("http://github.com/search") << QString("http://github.com/suggestions") << QString()
+ << (Parameters() << Parameter(QString("q"), QString("{searchTerms}"))
+ << Parameter(QString("b"), QString("foo")))
+ << (Parameters() << Parameter(QString("bar"), QString("baz")))
+ << QString("get") << QString("post") << QStringList();
+
+ QTest::newRow("testfile4") << QString(":/testfile4.xml") << true << QString("Google") << QString("Google Web Search")
+ << QString("http://www.google.com/search?bar") << QString("http://suggestqueries.google.com/complete/foo")
+ << QString("http://www.google.com/favicon.ico") << Parameters()
+ << Parameters() << QString("get") << QString("get") << QStringList();
+
+ QTest::newRow("testfile5") << QString(":/testfile5.xml") << false << QString() << QString() << QString() << QString()
+ << QString() << Parameters() << Parameters() << QString("get")
+ << QString("get") << QStringList();
+
+ QTest::newRow("testfile6") << QString(":/testfile6.xml") << false << QString() << QString() << QString() << QString()
+ << QString() << Parameters() << Parameters() << QString("get")
+ << QString("get") << QStringList();
+
+ QTest::newRow("testfile7") << QString(":/testfile7.xml") << false << QString() << QString() << QString() << QString()
+ << QString() << Parameters() << Parameters() << QString("get")
+ << QString("get") << QStringList();
+
+ QTest::newRow("testfile8") << QString(":/testfile8.xml") << true << QString("Web Search") << QString("Use Example.com to search the Web.")
+ << QString("http://example.com/") << QString() << QString() << Parameters() << Parameters() << QString("get")
+ << QString("get") << (QStringList() << "example" << "web");
+}
+
+void tst_OpenSearchReader::read()
+{
+ QFETCH(QString, fileName);
+ QFETCH(bool, valid);
+ QFETCH(QString, name);
+ QFETCH(QString, description);
+ QFETCH(QString, searchUrlTemplate);
+ QFETCH(QString, suggestionsUrlTemplate);
+ QFETCH(QString, imageUrl);
+ QFETCH(Parameters, searchParameters);
+ QFETCH(Parameters, suggestionsParameters);
+ QFETCH(QString, searchMethod);
+ QFETCH(QString, suggestionsMethod);
+ QFETCH(QStringList, tags);
+
+ QFile file(fileName);
+ file.open(QIODevice::ReadOnly);
+ OpenSearchReader reader;
+ OpenSearchEngine *engine = reader.read(&file);
+
+ QCOMPARE(engine->isValid(), valid);
+ QCOMPARE(engine->name(), name);
+ QCOMPARE(engine->description(), description);
+ QCOMPARE(engine->searchUrlTemplate(), searchUrlTemplate);
+ QCOMPARE(engine->suggestionsUrlTemplate(), suggestionsUrlTemplate);
+ QCOMPARE(engine->searchParameters(), searchParameters);
+ QCOMPARE(engine->suggestionsParameters(), suggestionsParameters);
+ QCOMPARE(engine->imageUrl(), imageUrl);
+ QCOMPARE(engine->searchMethod(), searchMethod);
+ QCOMPARE(engine->suggestionsMethod(), suggestionsMethod);
+ QCOMPARE(engine->tags(), tags);
+
+ delete engine;
+}
+
+QTEST_MAIN(tst_OpenSearchReader)
+
+#include "tst_opensearchreader.moc"
+
diff --git a/src/opensearch/tests/opensearchwriter/.gitignore b/src/opensearch/tests/opensearchwriter/.gitignore
new file mode 100644
index 0000000..a2db00e
--- /dev/null
+++ b/src/opensearch/tests/opensearchwriter/.gitignore
@@ -0,0 +1 @@
+tst_opensearchwriter
diff --git a/src/opensearch/tests/opensearchwriter/opensearchwriter.pro b/src/opensearch/tests/opensearchwriter/opensearchwriter.pro
new file mode 100644
index 0000000..c88b532
--- /dev/null
+++ b/src/opensearch/tests/opensearchwriter/opensearchwriter.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+TARGET = tst_opensearchwriter
+
+include(../tests.pri)
+include(../../src/opensearch.pri)
+
+SOURCES += \
+ tst_opensearchwriter.cpp
+
+RESOURCES += \
+ opensearchwriter.qrc
diff --git a/src/opensearch/tests/opensearchwriter/opensearchwriter.qrc b/src/opensearch/tests/opensearchwriter/opensearchwriter.qrc
new file mode 100644
index 0000000..0c9fde0
--- /dev/null
+++ b/src/opensearch/tests/opensearchwriter/opensearchwriter.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>testfile1.xml</file>
+ <file>testfile2.xml</file>
+ <file>testfile3.xml</file>
+</qresource>
+</RCC>
diff --git a/src/opensearch/tests/opensearchwriter/testfile1.xml b/src/opensearch/tests/opensearchwriter/testfile1.xml
new file mode 100644
index 0000000..04c05a3
--- /dev/null
+++ b/src/opensearch/tests/opensearchwriter/testfile1.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+ <ShortName>Foo Bar</ShortName>
+ <Description>Bar Foo</Description>
+ <Url method="get" type="text/html" template="http://foobar.barfoo/search"/>
+</OpenSearchDescription>
diff --git a/src/opensearch/tests/opensearchwriter/testfile2.xml b/src/opensearch/tests/opensearchwriter/testfile2.xml
new file mode 100644
index 0000000..78e4360
--- /dev/null
+++ b/src/opensearch/tests/opensearchwriter/testfile2.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+ <ShortName>Arora!</ShortName>
+ <Description>a cross platform web browser built using Qt and WebKit</Description>
+ <Url method="get" type="text/html" template="http://foobar.barfoo/search"/>
+ <Url method="post" type="application/x-suggestions+json" template="http://foobar.barfoo/suggest"/>
+ <Tags>foo bar</Tags>
+</OpenSearchDescription>
diff --git a/src/opensearch/tests/opensearchwriter/testfile3.xml b/src/opensearch/tests/opensearchwriter/testfile3.xml
new file mode 100644
index 0000000..058f5ea
--- /dev/null
+++ b/src/opensearch/tests/opensearchwriter/testfile3.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+ <ShortName>Foo Bar</ShortName>
+ <Description>Bar Foo</Description>
+ <Url method="post" type="text/html" template="http://foobar.barfoo/search" xmlns:p="http://a9.com/-/spec/opensearch/extensions/parameters/1.0/">
+ <p:Parameter name="q" value="{searchTerms}"/>
+ <p:Parameter name="a" value="foo"/>
+ </Url>
+ <Url method="get" type="application/x-suggestions+json" template="http://foobar.barfoo/suggest" xmlns:p="http://a9.com/-/spec/opensearch/extensions/parameters/1.0/">
+ <p:Parameter name="q" value="{searchTerms}"/>
+ </Url>
+</OpenSearchDescription>
diff --git a/src/opensearch/tests/opensearchwriter/tst_opensearchwriter.cpp b/src/opensearch/tests/opensearchwriter/tst_opensearchwriter.cpp
new file mode 100644
index 0000000..a87f0df
--- /dev/null
+++ b/src/opensearch/tests/opensearchwriter/tst_opensearchwriter.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2009 Jakub Wieczorek <faw217@gmail.com>
+ *
+ * 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 <QtTest/QtTest>
+
+#include "opensearchwriter.h"
+#include "opensearchengine.h"
+
+class tst_OpenSearchWriter : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void write_data();
+ void write();
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_OpenSearchWriter::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_OpenSearchWriter::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_OpenSearchWriter::init()
+{
+}
+
+// This will be called after every test function.
+void tst_OpenSearchWriter::cleanup()
+{
+}
+
+Q_DECLARE_METATYPE(OpenSearchEngine::Parameters)
+void tst_OpenSearchWriter::write_data()
+{
+ QTest::addColumn<QString>("name");
+ QTest::addColumn<QString>("description");
+ QTest::addColumn<QString>("searchUrlTemplate");
+ QTest::addColumn<QString>("suggestionsUrlTemplate");
+ QTest::addColumn<QString>("imageUrl");
+ QTest::addColumn<OpenSearchEngine::Parameters>("searchParameters");
+ QTest::addColumn<OpenSearchEngine::Parameters>("suggestionsParameters");
+ QTest::addColumn<QString>("searchMethod");
+ QTest::addColumn<QString>("suggestionsMethod");
+ QTest::addColumn<QStringList>("tags");
+ QTest::addColumn<QString>("fileName");
+
+ QTest::newRow("testfile1") << QString("Foo Bar") << QString("Bar Foo") << QString("http://foobar.barfoo/search") << QString()
+ << QString() << OpenSearchEngine::Parameters() << OpenSearchEngine::Parameters()
+ << QString() << QString("get") << QStringList() << QString(":/testfile1.xml");
+
+ QTest::newRow("testfile2") << QString("Arora!") << QString("a cross platform web browser built using Qt and WebKit")
+ << QString("http://foobar.barfoo/search") << QString("http://foobar.barfoo/suggest") << QString()
+ << OpenSearchEngine::Parameters() << OpenSearchEngine::Parameters() << QString("get") << QString("post")
+ << (QStringList() << "foo" << "bar") << QString(":/testfile2.xml");
+
+ QTest::newRow("testile3") << QString("Foo Bar") << QString("Bar Foo") << QString("http://foobar.barfoo/search")
+ << QString("http://foobar.barfoo/suggest") << QString()
+ << (OpenSearchEngine::Parameters() << OpenSearchEngine::Parameter("q", "{searchTerms}") << OpenSearchEngine::Parameter("a", "foo"))
+ << (OpenSearchEngine::Parameters() << OpenSearchEngine::Parameter("q", "{searchTerms}"))
+ << QString("post") << QString("foo") << QStringList() << QString(":/testfile3.xml");
+}
+
+void tst_OpenSearchWriter::write()
+{
+ QFETCH(QString, name);
+ QFETCH(QString, description);
+ QFETCH(QString, searchUrlTemplate);
+ QFETCH(QString, suggestionsUrlTemplate);
+ QFETCH(QString, imageUrl);
+ QFETCH(OpenSearchEngine::Parameters, searchParameters);
+ QFETCH(OpenSearchEngine::Parameters, suggestionsParameters);
+ QFETCH(QString, searchMethod);
+ QFETCH(QString, suggestionsMethod);
+ QFETCH(QStringList, tags);
+ QFETCH(QString, fileName);
+
+ OpenSearchEngine engine;
+ OpenSearchWriter writer;
+
+ engine.setName(name);
+ engine.setDescription(description);
+ engine.setSearchUrlTemplate(searchUrlTemplate);
+ engine.setSuggestionsUrlTemplate(suggestionsUrlTemplate);
+ engine.setImageUrl(imageUrl);
+ engine.setSearchParameters(searchParameters);
+ engine.setSuggestionsParameters(suggestionsParameters);
+ engine.setSearchMethod(searchMethod);
+ engine.setSuggestionsMethod(suggestionsMethod);
+ engine.setTags(tags);
+
+ QByteArray output;
+ QBuffer buffer(&output);
+ writer.write(&buffer, &engine);
+
+ QFile expected(fileName);
+ expected.open(QIODevice::ReadOnly);
+
+ QCOMPARE(output, expected.readAll());
+}
+
+QTEST_MAIN(tst_OpenSearchWriter)
+
+#include "tst_opensearchwriter.moc"
+
diff --git a/src/opensearch/tests/qtry.h b/src/opensearch/tests/qtry.h
new file mode 100644
index 0000000..4d9b712
--- /dev/null
+++ b/src/opensearch/tests/qtry.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2008-2009 Benjamin C. Meyer <ben@meyerhome.net>
+ *
+ * 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 QTRY_H
+#define QTRY_H
+
+#include <qtest.h>
+
+#ifndef QTRY_COMPARE
+
+#define __TRY_TIMEOUT__ 5000
+#define __TRY_STEP__ 50
+
+#define __QTRY(__expression__, __functionToCall__) \
+ do { \
+ int __i = 0; \
+ while (!(__expression__) && __i < __TRY_TIMEOUT__) { \
+ QTest::qWait(__TRY_STEP__); \
+ __i += __TRY_STEP__; \
+ } \
+ __functionToCall__; \
+ } while(0)
+
+#define QTRY_COMPARE(__expression__, __expected__) \
+ __QTRY((__expression__ == __expected__), QCOMPARE(__expression__, __expected__));
+
+#define QTRY_VERIFY(__expression__) \
+ __QTRY(__expression__, QVERIFY(__expression__));
+
+#endif // QTRY_COMPARE
+
+#endif // QTRY_H
+
diff --git a/src/opensearch/tests/tests.pri b/src/opensearch/tests/tests.pri
new file mode 100644
index 0000000..096f22a
--- /dev/null
+++ b/src/opensearch/tests/tests.pri
@@ -0,0 +1,12 @@
+win32: CONFIG += console
+mac:CONFIG -= app_bundle
+
+CONFIG += qtestlib
+
+HEADERS += qtry.h
+
+include(../build.pri)
+DESTDIR = $$BUILDDIR/tests
+
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
diff --git a/src/opensearch/tests/tests.pro b/src/opensearch/tests/tests.pro
new file mode 100644
index 0000000..0660b2c
--- /dev/null
+++ b/src/opensearch/tests/tests.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+SUBDIRS = opensearchengine opensearchreader opensearchwriter
+
+CONFIG += ordered
diff --git a/src/opensearch/opensearchdialog.cpp b/src/opensearchdialog.cpp
index 94fdf8d..94fdf8d 100644
--- a/src/opensearch/opensearchdialog.cpp
+++ b/src/opensearchdialog.cpp
diff --git a/src/opensearch/opensearchdialog.h b/src/opensearchdialog.h
index 5f50e97..5f50e97 100644
--- a/src/opensearch/opensearchdialog.h
+++ b/src/opensearchdialog.h
diff --git a/src/opensearch/opensearchdialog.ui b/src/opensearchdialog.ui
index 1e503e5..1e503e5 100644
--- a/src/opensearch/opensearchdialog.ui
+++ b/src/opensearchdialog.ui
diff --git a/src/opensearch/opensearchengineaction.cpp b/src/opensearchengineaction.cpp
index 6674022..6674022 100644
--- a/src/opensearch/opensearchengineaction.cpp
+++ b/src/opensearchengineaction.cpp
diff --git a/src/opensearch/opensearchengineaction.h b/src/opensearchengineaction.h
index aeb93b2..aeb93b2 100644
--- a/src/opensearch/opensearchengineaction.h
+++ b/src/opensearchengineaction.h
diff --git a/src/opensearch/opensearchenginemodel.cpp b/src/opensearchenginemodel.cpp
index a35f1bb..a35f1bb 100644
--- a/src/opensearch/opensearchenginemodel.cpp
+++ b/src/opensearchenginemodel.cpp
diff --git a/src/opensearch/opensearchenginemodel.h b/src/opensearchenginemodel.h
index 23001cf..23001cf 100644
--- a/src/opensearch/opensearchenginemodel.h
+++ b/src/opensearchenginemodel.h
diff --git a/src/opensearch/opensearchmanager.cpp b/src/opensearchmanager.cpp
index d9bb0a2..d9bb0a2 100644
--- a/src/opensearch/opensearchmanager.cpp
+++ b/src/opensearchmanager.cpp
diff --git a/src/opensearch/opensearchmanager.h b/src/opensearchmanager.h
index 1d3f33c..1d3f33c 100644
--- a/src/opensearch/opensearchmanager.h
+++ b/src/opensearchmanager.h
diff --git a/src/src.pri b/src/src.pri
index 7c1a0e3..0b602da 100644
--- a/src/src.pri
+++ b/src/src.pri
@@ -7,7 +7,7 @@ win32|os2 : Debug : CONFIG += console
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
-QT += webkit network
+QT += webkit network script
# Share object files for faster compiling
RCC_DIR = $$PWD/.rcc
@@ -30,6 +30,7 @@ FORMS += \
acceptlanguagedialog.ui \
downloaditem.ui \
downloads.ui \
+ opensearchdialog.ui \
searchbanner.ui \
settings.ui
@@ -46,6 +47,10 @@ HEADERS += \
downloadmanager.h \
modelmenu.h \
modeltoolbar.h \
+ opensearchdialog.h \
+ opensearchengineaction.h \
+ opensearchenginemodel.h \
+ opensearchmanager.h \
plaintexteditsearch.h \
searchbar.h \
searchbutton.h \
@@ -74,6 +79,10 @@ SOURCES += \
downloadmanager.cpp \
modelmenu.cpp \
modeltoolbar.cpp \
+ opensearchdialog.cpp \
+ opensearchengineaction.cpp \
+ opensearchenginemodel.cpp \
+ opensearchmanager.cpp \
plaintexteditsearch.cpp \
searchbar.cpp \
searchbutton.cpp \
@@ -94,7 +103,7 @@ include(bookmarks/bookmarks.pri)
include(history/history.pri)
include(locationbar/locationbar.pri)
include(network/network.pri)
-include(opensearch/opensearch.pri)
+include(opensearch/src/opensearch-nolib.pri)
include(qwebplugins/qwebplugins.pri)
include(utils/utils.pri)
include(useragent/useragent.pri)