From e9d099f4c5efa41fafd16408f13400cb37616f18 Mon Sep 17 00:00:00 2001
From: lionelc <lionelc@lionelc.(none)>
Date: Thu, 12 Aug 2010 18:31:16 +0200
Subject: introduce a new SuggestionListItem introduce an opensearch engine

---
 src/CMakeLists.txt               |   7 +-
 src/search/opensearchengine.cpp  | 229 +++++++++++++++++++++++++++++++++++++++
 src/search/opensearchengine.h    |  93 ++++++++++++++++
 src/search/opensearchmanager.cpp | 175 ++++++++++++++++++++++++++++++
 src/search/opensearchmanager.h   |  88 +++++++++++++++
 src/search/opensearchreader.cpp  | 133 +++++++++++++++++++++++
 src/search/opensearchreader.h    |  39 +++++++
 src/search/opensearchwriter.cpp  | 110 +++++++++++++++++++
 src/search/opensearchwriter.h    |  41 +++++++
 src/search/searchengine.cpp      | 153 ++++++++++++++++++++++++++
 src/search/searchengine.h        |  62 +++++++++++
 src/searchengine.cpp             | 153 --------------------------
 src/searchengine.h               |  62 -----------
 src/settings/settingsdialog.cpp  |   2 +-
 src/urlbar/completionwidget.cpp  |   2 +-
 src/urlbar/listitem.cpp          |  30 ++++-
 src/urlbar/listitem.h            |  12 ++
 src/urlbar/urlresolver.cpp       |  21 +++-
 src/urlbar/urlresolver.h         |   4 +-
 src/webview.cpp                  |   2 +-
 20 files changed, 1193 insertions(+), 225 deletions(-)
 create mode 100644 src/search/opensearchengine.cpp
 create mode 100644 src/search/opensearchengine.h
 create mode 100644 src/search/opensearchmanager.cpp
 create mode 100644 src/search/opensearchmanager.h
 create mode 100644 src/search/opensearchreader.cpp
 create mode 100644 src/search/opensearchreader.h
 create mode 100644 src/search/opensearchwriter.cpp
 create mode 100644 src/search/opensearchwriter.h
 create mode 100644 src/search/searchengine.cpp
 create mode 100644 src/search/searchengine.h
 delete mode 100644 src/searchengine.cpp
 delete mode 100644 src/searchengine.h

(limited to 'src')

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 46e9240c..a6658ed0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -29,7 +29,6 @@ SET( rekonq_KDEINIT_SRCS
     websnap.cpp
     webview.cpp
     webtab.cpp
-    searchengine.cpp
     #----------------------------------------
     history/autosaver.cpp 
     history/historymanager.cpp
@@ -63,6 +62,12 @@ SET( rekonq_KDEINIT_SRCS
     #----------------------------------------
     analyzer/analyzerpanel.cpp
     analyzer/networkanalyzer.cpp
+    #----------------------------------------
+    search/searchengine.cpp
+    search/opensearchwriter.cpp
+    search/opensearchreader.cpp
+    search/opensearchmanager.cpp
+    search/opensearchengine.cpp
 )
 
 
diff --git a/src/search/opensearchengine.cpp b/src/search/opensearchengine.cpp
new file mode 100644
index 00000000..a7bcf11e
--- /dev/null
+++ b/src/search/opensearchengine.cpp
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2009 Jakub Wieczorek <faw217@gmail.com>
+ * Copyright 2009 Christian Franke <cfchris6@ts2server.com>
+ * Copyright 2009 Fredy Yanardi <fyanardi@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 "opensearchengine.h"
+
+#include <QtCore/QRegExp>
+#include <QtCore/QStringList>
+#include <QtScript/QScriptEngine>
+#include <QtScript/QScriptValue>
+
+OpenSearchEngine::OpenSearchEngine(QObject *)
+    : m_scriptEngine(0)
+{
+}
+
+OpenSearchEngine::~OpenSearchEngine()
+{
+    if (m_scriptEngine) {
+        delete m_scriptEngine;
+    }
+}
+
+QString OpenSearchEngine::parseTemplate(const QString &searchTerm, const QString &searchTemplate)
+{
+    QString result = searchTemplate;
+    result.replace(QLatin1String("{count}"), QLatin1String("20"));
+    result.replace(QLatin1String("{startIndex}"), QLatin1String("0"));
+    result.replace(QLatin1String("{startPage}"), QLatin1String("0"));
+    // TODO - get setting from KDE
+    result.replace(QLatin1String("{language}"), QLatin1String("en-US"));
+    result.replace(QLatin1String("{inputEncoding}"), QLatin1String("UTF-8"));
+    result.replace(QLatin1String("{outputEncoding}"), QLatin1String("UTF-8"));
+    result.replace(QLatin1String("{searchTerms}"), searchTerm);
+
+    return result;
+}
+
+QString OpenSearchEngine::name() const
+{
+    return m_name;
+}
+
+void OpenSearchEngine::setName(const QString &name)
+{
+    m_name = name;
+}
+
+QString OpenSearchEngine::description() const
+{
+    return m_description;
+}
+
+void OpenSearchEngine::setDescription(const QString &description)
+{
+    m_description = description;
+}
+
+QString OpenSearchEngine::searchUrlTemplate() const
+{
+    return m_searchUrlTemplate;
+}
+
+void OpenSearchEngine::setSearchUrlTemplate(const QString &searchUrlTemplate)
+{
+    m_searchUrlTemplate = searchUrlTemplate;
+}
+
+KUrl OpenSearchEngine::searchUrl(const QString &searchTerm) const
+{
+    if (m_searchUrlTemplate.isEmpty()) {
+        return KUrl();
+    }
+
+    KUrl retVal = KUrl::fromEncoded(parseTemplate(searchTerm, m_searchUrlTemplate).toUtf8());
+
+    QList<Parameter>::const_iterator end = m_searchParameters.constEnd();
+    QList<Parameter>::const_iterator i = m_searchParameters.constBegin();
+    for (; i != end; ++i) {
+        retVal.addQueryItem(i->first, parseTemplate(searchTerm, i->second));
+    }
+
+    return retVal;
+}
+
+bool OpenSearchEngine::providesSuggestions() const
+{
+    return !m_suggestionsUrlTemplate.isEmpty();
+}
+
+QString OpenSearchEngine::suggestionsUrlTemplate() const
+{
+    return m_suggestionsUrlTemplate;
+}
+
+void OpenSearchEngine::setSuggestionsUrlTemplate(const QString &suggestionsUrlTemplate)
+{
+    m_suggestionsUrlTemplate = suggestionsUrlTemplate;
+}
+
+KUrl OpenSearchEngine::suggestionsUrl(const QString &searchTerm) const
+{
+    if (m_suggestionsUrlTemplate.isEmpty()) {
+        return KUrl();
+    }
+
+    KUrl retVal = KUrl::fromEncoded(parseTemplate(searchTerm, m_suggestionsUrlTemplate).toUtf8());
+
+    QList<Parameter>::const_iterator end = m_suggestionsParameters.constEnd();
+    QList<Parameter>::const_iterator i = m_suggestionsParameters.constBegin();
+    for (; i != end; ++i) {
+        retVal.addQueryItem(i->first, parseTemplate(searchTerm, i->second));
+    }
+
+    return retVal;
+}
+
+QList<OpenSearchEngine::Parameter> OpenSearchEngine::searchParameters() const
+{
+    return m_searchParameters;
+}
+
+void OpenSearchEngine::setSearchParameters(const QList<Parameter> &searchParameters)
+{
+    m_searchParameters = searchParameters;
+}
+
+QList<OpenSearchEngine::Parameter> OpenSearchEngine::suggestionsParameters() const
+{
+    return m_suggestionsParameters;
+}
+
+void OpenSearchEngine::setSuggestionsParameters(const QList<Parameter> &suggestionsParameters)
+{
+    m_suggestionsParameters = suggestionsParameters;
+}
+
+QString OpenSearchEngine::imageUrl() const
+{
+    return m_imageUrl;
+}
+
+void OpenSearchEngine::setImageUrl(const QString &imageUrl)
+{
+    m_imageUrl = imageUrl;
+}
+
+QImage OpenSearchEngine::image() const
+{
+    return m_image;
+}
+
+void OpenSearchEngine::setImage(const QImage &image)
+{
+    m_image = image;
+}
+
+bool OpenSearchEngine::isValid() const
+{
+    return (!m_name.isEmpty() && !m_searchUrlTemplate.isEmpty());
+}
+
+bool OpenSearchEngine::operator==(const OpenSearchEngine &other) const
+{
+    return (m_name == other.m_name
+            && m_description == other.m_description
+            && m_imageUrl == other.m_imageUrl
+            && m_searchUrlTemplate == other.m_searchUrlTemplate
+            && m_suggestionsUrlTemplate == other.m_suggestionsUrlTemplate
+            && m_searchParameters == other.m_searchParameters
+            && m_suggestionsParameters == other.m_suggestionsParameters);
+}
+
+bool OpenSearchEngine::operator<(const OpenSearchEngine &other) const
+{
+    return (m_name < other.m_name);
+}
+
+QStringList OpenSearchEngine::parseSuggestion(const QByteArray &resp)
+{
+    QString response(resp);
+    response = response.trimmed();
+
+    if (response.isEmpty()) {
+        return QStringList();
+    }
+
+    if (!response.startsWith(QLatin1Char('[')) || !response.endsWith(QLatin1Char(']'))) {
+        return QStringList();
+    }
+
+    if (!m_scriptEngine) {
+        m_scriptEngine = new QScriptEngine();
+    }
+
+    // Evaluate the JSON response using QtScript.
+    if (!m_scriptEngine->canEvaluate(response)) {
+        return QStringList();
+    }
+
+    QScriptValue responseParts = m_scriptEngine->evaluate(response);
+
+    if (!responseParts.property(1).isArray()) {
+        return QStringList();
+    }
+
+    QStringList suggestionsList;
+    qScriptValueToSequence(responseParts.property(1), suggestionsList);
+
+    return suggestionsList;
+}
+
diff --git a/src/search/opensearchengine.h b/src/search/opensearchengine.h
new file mode 100644
index 00000000..c981f443
--- /dev/null
+++ b/src/search/opensearchengine.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2009 Jakub Wieczorek <faw217@gmail.com>
+ * Copyright 2009 Christian Franke <cfchris6@ts2server.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
+ */
+
+#ifndef OPENSEARCHENGINE_H
+#define OPENSEARCHENGINE_H
+
+#include <QtCore/QPair>
+#include <QtGui/QImage>
+
+#include <KUrl>
+
+class QNetworkAccessManager;
+class QNetworkReply;
+class QScriptEngine;
+
+class OpenSearchEngine
+{
+public:
+    typedef QPair<QString, QString> Parameter;
+
+    OpenSearchEngine(QObject *parent = 0);
+    ~OpenSearchEngine();
+
+    QString name() const;
+    void setName(const QString &name);
+
+    QString description() const;
+    void setDescription(const QString &description);
+
+    QString searchUrlTemplate() const;
+    void setSearchUrlTemplate(const QString &searchUrl);
+    KUrl searchUrl(const QString &searchTerm) const;
+
+    bool providesSuggestions() const;
+
+    QString suggestionsUrlTemplate() const;
+    void setSuggestionsUrlTemplate(const QString &suggestionsUrl);
+    KUrl suggestionsUrl(const QString &searchTerm) const;
+
+    QList<Parameter> searchParameters() const;
+    void setSearchParameters(const QList<Parameter> &searchParameters);
+
+    QList<Parameter> suggestionsParameters() const;
+    void setSuggestionsParameters(const QList<Parameter> &suggestionsParameters);
+
+    QString imageUrl() const;
+    void setImageUrl(const QString &url);
+
+    QImage image() const;
+    void setImage(const QImage &image);
+
+    bool isValid() const;
+
+    bool operator==(const OpenSearchEngine &other) const;
+    bool operator<(const OpenSearchEngine &other) const;
+
+    QStringList parseSuggestion(const QByteArray &response);
+
+    static QString parseTemplate(const QString &searchTerm, const QString &searchTemplate);
+
+private:
+    QString m_name;
+    QString m_description;
+
+    QString m_imageUrl;
+    QImage m_image;
+
+    QString m_searchUrlTemplate;
+    QString m_suggestionsUrlTemplate;
+    QList<Parameter> m_searchParameters;
+    QList<Parameter> m_suggestionsParameters;
+
+    QScriptEngine *m_scriptEngine;
+};
+
+#endif // OPENSEARCHENGINE_H
diff --git a/src/search/opensearchmanager.cpp b/src/search/opensearchmanager.cpp
new file mode 100644
index 00000000..6e37db77
--- /dev/null
+++ b/src/search/opensearchmanager.cpp
@@ -0,0 +1,175 @@
+/* This file is part of the KDE project
+ * Copyright (C) 2009 Fredy Yanardi <fyanardi@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "opensearchmanager.h"
+
+#include <QtCore/QFile>
+
+#include <KDebug>
+#include <KGlobal>
+#include <KStandardDirs>
+#include <KUrl>
+#include <kio/scheduler.h>
+
+#include "opensearchengine.h"
+#include "opensearchreader.h"
+#include "opensearchwriter.h"
+
+OpenSearchManager::OpenSearchManager(QObject *parent)
+    : QObject(parent)
+    , m_activeEngine(0)
+{
+    m_state = IDLE;
+}
+
+OpenSearchManager::~OpenSearchManager() {
+    qDeleteAll(m_enginesMap.values());
+    m_enginesMap.clear();
+}
+
+void OpenSearchManager::setSearchProvider(const QString &searchProvider)
+{
+    m_activeEngine = 0;
+
+    if (!m_enginesMap.contains(searchProvider)) {
+        const QString fileName = KGlobal::dirs()->findResource("data", "konqueror/opensearch/" + searchProvider + ".xml");
+        if (fileName.isEmpty()) {
+            return;
+        }
+        QFile file(fileName);
+
+        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+            kWarning(1202) << "Cannot open opensearch description file: " + fileName;
+            return;
+        }
+
+        OpenSearchReader reader;
+        OpenSearchEngine *engine = reader.read(&file);
+
+        if (engine) {
+            m_enginesMap.insert(searchProvider, engine);
+        }
+        else {
+            return;
+        }
+    }
+
+    m_activeEngine = m_enginesMap.value(searchProvider);
+}
+
+bool OpenSearchManager::isSuggestionAvailable()
+{
+    return m_activeEngine != 0;
+}
+
+void OpenSearchManager::addOpenSearchEngine(const KUrl &url, const QString &title)
+{
+    Q_UNUSED(title);
+
+    m_jobData.clear();
+
+    if (m_state != IDLE) {
+        // TODO: cancel job
+    }
+
+    m_state = REQ_DESCRIPTION;
+    KIO::TransferJob *job = KIO::get(url, KIO::NoReload, KIO::HideProgressInfo);
+    connect(job, SIGNAL(data(KIO::Job *, const QByteArray &)),
+            this, SLOT(dataReceived(KIO::Job *, const QByteArray &)));
+    connect(job, SIGNAL(result(KJob *)), SLOT(jobFinished(KJob *)));
+}
+
+void OpenSearchManager::requestSuggestion(const QString &searchText)
+{
+    if (!m_activeEngine) {
+        return;
+    }
+
+    if (m_state != IDLE) {
+        // TODO: cancel job
+    }
+    m_state = REQ_SUGGESTION;
+
+    KUrl url = m_activeEngine->suggestionsUrl(searchText);
+    kDebug(1202) << "Requesting for suggestions: " << url.url();
+    m_jobData.clear();
+    KIO::TransferJob *job = KIO::get(url, KIO::NoReload, KIO::HideProgressInfo);
+    connect(job, SIGNAL(data(KIO::Job *, const QByteArray &)),
+            this, SLOT(dataReceived(KIO::Job *, const QByteArray &)));
+    connect(job, SIGNAL(result(KJob *)), SLOT(jobFinished(KJob *)));
+}
+
+void OpenSearchManager::dataReceived(KIO::Job *job, const QByteArray &data)
+{
+    Q_UNUSED(job);
+    m_jobData.append(data);
+}
+
+void OpenSearchManager::jobFinished(KJob *job)
+{
+    if (job->error()) {
+        return; // just silently return
+    }
+
+    if (m_state == REQ_SUGGESTION) {
+        const QStringList suggestionsList = m_activeEngine->parseSuggestion(m_jobData);
+        kDebug(1202) << "Received suggestion from " << m_activeEngine->name() << ": " << suggestionsList;
+
+        emit suggestionReceived(suggestionsList);
+    }
+    else if (m_state == REQ_DESCRIPTION) {
+        OpenSearchReader reader;
+        OpenSearchEngine *engine = reader.read(m_jobData);
+        if (engine) {
+            m_enginesMap.insert(engine->name(), engine);
+            QString path = KGlobal::dirs()->findResource("data", "konqueror/opensearch/");
+            QString fileName = trimmedEngineName(engine->name());
+            QFile file(path + fileName + ".xml");
+            OpenSearchWriter writer;
+            writer.write(&file, engine);
+
+            QString searchUrl = OpenSearchEngine::parseTemplate("\\{@}", engine->searchUrlTemplate());
+            emit openSearchEngineAdded(engine->name(), searchUrl, fileName);
+        }
+        else {
+            kFatal() << "Error while adding new open search engine";
+        }
+    }
+}
+
+QString OpenSearchManager::trimmedEngineName(const QString &engineName) const
+{
+    QString trimmed;
+    QString::ConstIterator constIter = engineName.constBegin();
+    while (constIter != engineName.constEnd()) {
+        if (constIter->isSpace()) {
+            trimmed.append('-');
+        }
+        else if (*constIter != '.') {
+            trimmed.append(constIter->toLower());
+        }
+        constIter++;
+    }
+
+    return trimmed;
+}
+
+#include "opensearchmanager.moc"
+
+ 
diff --git a/src/search/opensearchmanager.h b/src/search/opensearchmanager.h
new file mode 100644
index 00000000..59e7e6b2
--- /dev/null
+++ b/src/search/opensearchmanager.h
@@ -0,0 +1,88 @@
+/* This file is part of the KDE project
+ * Copyright (C) 2009 Fredy Yanardi <fyanardi@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef OPENSEARCHMANAGER_H
+#define OPENSEARCHMANAGER_H
+
+#include <QtCore/QObject>
+#include <kio/jobclasses.h>
+
+class SuggestionEngine;
+
+class OpenSearchEngine;
+
+/**
+ * This class acts as a proxy between the SearchBar plugin and the individual suggestion engine.
+ * This class has a map of all available engines, and route the suggestion request to the correct engine
+ */
+class OpenSearchManager : public QObject
+{
+    Q_OBJECT
+
+    enum STATE {
+        REQ_SUGGESTION,
+        REQ_DESCRIPTION,
+        IDLE
+    };
+public:
+    /**
+     * Constructor
+     */
+    explicit OpenSearchManager(QObject *parent = 0);
+
+    virtual ~OpenSearchManager();
+
+    void setSearchProvider(const QString &searchProvider);
+
+    /**
+     * Check whether a search suggestion engine is available for the given search provider
+     * @param searchProvider the queried search provider
+     */
+    bool isSuggestionAvailable();
+
+    void addOpenSearchEngine(const KUrl &url, const QString &title);
+
+public slots:
+    /**
+     * Ask the specific suggestion engine to request for suggestion for the search text
+     * @param searchProvider the search provider that provides the suggestion service
+     * @param searchText the text to be queried to the suggestion service
+     */
+    void requestSuggestion(const QString &searchProvider);
+
+private slots:
+    void dataReceived(KIO::Job *job, const QByteArray &data);
+    void jobFinished(KJob *job);
+
+signals:
+    void suggestionReceived(const QStringList &suggestion);
+    void openSearchEngineAdded(const QString &name, const QString &searchUrl, const QString &fileName);
+
+private:
+    QString trimmedEngineName(const QString &engineName) const;
+
+    // QString substitutueSearchText(const QString &searchText, const QString &requestURL) const;
+    QByteArray m_jobData;
+    QMap<QString, OpenSearchEngine*> m_enginesMap;
+    OpenSearchEngine *m_activeEngine;
+    STATE m_state;
+};
+
+#endif // OPENSEARCHMANAGER_H
+
diff --git a/src/search/opensearchreader.cpp b/src/search/opensearchreader.cpp
new file mode 100644
index 00000000..0aa0f91f
--- /dev/null
+++ b/src/search/opensearchreader.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2009 Jakub Wieczorek <faw217@gmail.com>
+ * Copyright 2009 Fredy Yanardi <fyanardi@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 <QtCore/QIODevice>
+
+OpenSearchReader::OpenSearchReader()
+    : QXmlStreamReader()
+{
+}
+
+OpenSearchEngine *OpenSearchReader::read(const QByteArray &data)
+{
+    clear();
+
+    addData(data);
+
+    return read();
+}
+
+OpenSearchEngine *OpenSearchReader::read(QIODevice *device)
+{
+    clear();
+
+    if (!device->isOpen()) {
+        device->open(QIODevice::ReadOnly);
+    }
+
+    setDevice(device);
+    return read();
+}
+
+OpenSearchEngine *OpenSearchReader::read()
+{
+    OpenSearchEngine *engine = new OpenSearchEngine();
+
+    while (!isStartElement() && !atEnd()) {
+        readNext();
+    }
+
+    if (name() != QLatin1String("OpenSearchDescription")
+        || namespaceUri() != QLatin1String("http://a9.com/-/spec/opensearch/1.1/")) {
+        raiseError(QObject::tr("The file is not an OpenSearch 1.1 file."));
+        return engine;
+    }
+
+    while (!(isEndElement() && name() == QLatin1String("OpenSearchDescription")) && !atEnd()) {
+        readNext();
+
+        if (!isStartElement()) {
+            continue;
+        }
+
+        if (name() == QLatin1String("ShortName")) {
+            engine->setName(readElementText());
+        }
+        else if (name() == QLatin1String("Description")) {
+            engine->setDescription(readElementText());
+        }
+        else if (name() == QLatin1String("Url")) {
+            QString type = attributes().value(QLatin1String("type")).toString();
+            QString url = attributes().value(QLatin1String("template")).toString();
+
+            if (url.isEmpty())
+                continue;
+
+            QList<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);
+            }
+            else {
+                engine->setSearchUrlTemplate(url);
+                engine->setSearchParameters(parameters);
+            }
+        }
+        else if (name() == QLatin1String("Image")) {
+             engine->setImageUrl(readElementText());
+        }
+
+        if (!engine->name().isEmpty()
+            && !engine->description().isEmpty()
+            && !engine->suggestionsUrlTemplate().isEmpty()
+            && !engine->searchUrlTemplate().isEmpty()
+            && !engine->imageUrl().isEmpty()) {
+            break;
+        }
+    }
+
+    return engine;
+}
+
diff --git a/src/search/opensearchreader.h b/src/search/opensearchreader.h
new file mode 100644
index 00000000..5481881a
--- /dev/null
+++ b/src/search/opensearchreader.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2009 Jakub Wieczorek <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
+ */
+
+#ifndef OPENSEARCHREADER_H
+#define OPENSEARCHREADER_H
+
+#include <QtCore/QXmlStreamReader>
+
+class OpenSearchEngine;
+
+class OpenSearchReader : public QXmlStreamReader
+{
+public:
+    OpenSearchReader();
+
+    OpenSearchEngine *read(const QByteArray &data);
+    OpenSearchEngine *read(QIODevice *device);
+
+private:
+    OpenSearchEngine *read();
+};
+
+#endif // OPENSEARCHREADER_H
diff --git a/src/search/opensearchwriter.cpp b/src/search/opensearchwriter.cpp
new file mode 100644
index 00000000..a18ce0e2
--- /dev/null
+++ b/src/search/opensearchwriter.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2009 Jakub Wieczorek <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 "opensearchwriter.h"
+
+#include "opensearchengine.h"
+
+#include <QtCore/QIODevice>
+
+#include <KDebug>
+
+OpenSearchWriter::OpenSearchWriter()
+    : QXmlStreamWriter()
+{
+    setAutoFormatting(true);
+}
+
+bool OpenSearchWriter::write(QIODevice *device, OpenSearchEngine *engine)
+{
+    if (!engine)
+        return false;
+
+    if (!device->isOpen())
+        device->open(QIODevice::WriteOnly);
+
+    setDevice(device);
+    write(engine);
+    return true;
+}
+
+void OpenSearchWriter::write(OpenSearchEngine *engine)
+{
+    writeStartDocument();
+    writeStartElement(QLatin1String("OpenSearchDescription"));
+    writeDefaultNamespace(QLatin1String("http://a9.com/-/spec/opensearch/1.1/"));
+
+    if (!engine->name().isEmpty()) {
+        writeTextElement(QLatin1String("ShortName"), engine->name());
+    }
+
+    if (!engine->description().isEmpty()) {
+        writeTextElement(QLatin1String("Description"), engine->description());
+    }
+
+    if (!engine->searchUrlTemplate().isEmpty()) {
+        writeStartElement(QLatin1String("Url"));
+        writeAttribute(QLatin1String("method"), QLatin1String("get"));
+        writeAttribute(QLatin1String("template"), engine->searchUrlTemplate());
+
+        if (!engine->searchParameters().empty()) {
+            writeNamespace(QLatin1String("http://a9.com/-/spec/opensearch/extensions/parameters/1.0/"), QLatin1String("p"));
+
+            QList<OpenSearchEngine::Parameter>::const_iterator end = engine->searchParameters().constEnd();
+            QList<OpenSearchEngine::Parameter>::const_iterator i = engine->searchParameters().constBegin();
+            for (; i != end; ++i) {
+                writeStartElement(QLatin1String("p:Parameter"));
+                writeAttribute(QLatin1String("name"), i->first);
+                writeAttribute(QLatin1String("value"), i->second);
+                writeEndElement();
+            }
+        }
+
+        writeEndElement();
+    }
+
+    if (!engine->suggestionsUrlTemplate().isEmpty()) {
+        writeStartElement(QLatin1String("Url"));
+        writeAttribute(QLatin1String("method"), QLatin1String("get"));
+        writeAttribute(QLatin1String("type"), QLatin1String("application/x-suggestions+json"));
+        writeAttribute(QLatin1String("template"), engine->suggestionsUrlTemplate());
+
+        if (!engine->suggestionsParameters().empty()) {
+            writeNamespace(QLatin1String("http://a9.com/-/spec/opensearch/extensions/parameters/1.0/"), QLatin1String("p"));
+
+            QList<OpenSearchEngine::Parameter>::const_iterator end = engine->suggestionsParameters().constEnd();
+            QList<OpenSearchEngine::Parameter>::const_iterator i = engine->suggestionsParameters().constBegin();
+            for (; i != end; ++i) {
+                writeStartElement(QLatin1String("p:Parameter"));
+                writeAttribute(QLatin1String("name"), i->first);
+                writeAttribute(QLatin1String("value"), i->second);
+                writeEndElement();
+            }
+        }
+
+        writeEndElement();
+    }
+
+    if (!engine->imageUrl().isEmpty())
+        writeTextElement(QLatin1String("Image"), engine->imageUrl());
+
+    writeEndElement();
+    writeEndDocument();
+}
+
diff --git a/src/search/opensearchwriter.h b/src/search/opensearchwriter.h
new file mode 100644
index 00000000..b089c4bb
--- /dev/null
+++ b/src/search/opensearchwriter.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2009 Jakub Wieczorek <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
+ */
+
+#ifndef OPENSEARCHWRITER_H
+#define OPENSEARCHWRITER_H
+
+#include <QtCore/QXmlStreamWriter>
+
+class QIODevice;
+
+class OpenSearchEngine;
+
+class OpenSearchWriter : public QXmlStreamWriter
+{
+public:
+    OpenSearchWriter();
+
+    bool write(QIODevice *device, OpenSearchEngine *engine);
+
+private:
+    void write(OpenSearchEngine *engine);
+};
+
+#endif
+
diff --git a/src/search/searchengine.cpp b/src/search/searchengine.cpp
new file mode 100644
index 00000000..0a66bb64
--- /dev/null
+++ b/src/search/searchengine.cpp
@@ -0,0 +1,153 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2010 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009-2010 by Lionel Chauvin <megabigbug@yahoo.fr>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+//local includes
+#include "searchengine.h"
+
+// Auto Includes
+#include "rekonq.h"
+
+//KDE includes
+#include <KConfigGroup>
+#include <KServiceTypeTrader>
+
+
+QString SearchEngine::m_delimiter = "";
+
+
+QString SearchEngine::delimiter()
+{
+    if (m_delimiter == "") loadDelimiter();
+    return m_delimiter;
+}
+
+
+void SearchEngine::loadDelimiter()
+{
+    KConfig config("kuriikwsfilterrc"); //Share with konqueror
+    KConfigGroup cg = config.group("General");
+    m_delimiter = cg.readEntry("KeywordDelimiter", ":");
+}
+
+
+KService::Ptr SearchEngine::m_defaultWS;
+
+
+KService::Ptr SearchEngine::defaultWS()
+{
+    if (!m_defaultWS) loadDefaultWS();
+    return m_defaultWS;
+}
+
+
+void SearchEngine::loadDefaultWS()
+{
+    KConfig config("kuriikwsfilterrc"); //Share with konqueror
+    KConfigGroup cg = config.group("General");
+    QString d = cg.readEntry("DefaultSearchEngine", "google");
+    m_defaultWS = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(d));
+}
+
+
+KService::Ptr SearchEngine::fromString(QString text)
+{
+    KService::List providers = KServiceTypeTrader::self()->query("SearchProvider");
+    int i = 0;
+    bool found = false;
+    KService::Ptr service;
+    while (!found && i < providers.size())
+    {
+        QStringList list = providers.at(i)->property("Keys").toStringList();
+        foreach(const QString &key, list)
+        {
+            const QString searchPrefix = key + delimiter();
+            if (text.startsWith(searchPrefix))
+            {
+                service = providers.at(i);
+                found = true;
+            }
+        }
+        i++;
+    }
+
+    return service;
+}
+
+
+QString SearchEngine::buildQuery(KService::Ptr engine, QString text)
+{
+    QString query = engine->property("Query").toString();
+    query = query.replace("\\{@}", KUrl::toPercentEncoding(text));
+    return query;
+}
+
+
+KService::List SearchEngine::m_favorites;
+
+
+KService::List SearchEngine::favorites()
+{
+    if (m_favorites.isEmpty()) loadFavorites();
+    return m_favorites;
+}
+
+void SearchEngine::loadFavorites()
+{
+  KConfig config("kuriikwsfilterrc"); //Share with konqueror
+  KConfigGroup cg = config.group("General");
+  QStringList favoriteEngines;
+  favoriteEngines << "google"; //defaults
+  favoriteEngines = cg.readEntry("FavoriteSearchEngines", favoriteEngines);
+  
+  KService::List favorites;
+  KService::Ptr service;
+  foreach(const QString &engine, favoriteEngines)
+  {
+    service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(engine));
+    if (service)
+      favorites << service;
+  }
+  
+  m_favorites = favorites;
+}
+
+
+KService::Ptr SearchEngine::defaultEngine()
+{
+  KConfig config("kuriikwsfilterrc"); //Share with konqueror
+  KConfigGroup cg = config.group("General");
+  QString d = cg.readEntry("DefaultSearchEngine");
+  KService::Ptr service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(d));
+  if (!service)
+  {
+    d = QL1S("google");
+    service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(d));
+  }
+  
+  return service;
+  
+}
diff --git a/src/search/searchengine.h b/src/search/searchengine.h
new file mode 100644
index 00000000..2e30e056
--- /dev/null
+++ b/src/search/searchengine.h
@@ -0,0 +1,62 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2010 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009-2010 by Lionel Chauvin <megabigbug@yahoo.fr>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+#ifndef SEARCHENGINE_H
+#define SEARCHENGINE_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// KDE Includes
+#include <KService>
+
+//Qt Includes
+#include <QString>
+
+
+class SearchEngine
+{
+public:
+
+    static QString delimiter();
+    static KService::Ptr defaultEngine();
+    static KService::List favorites();
+    static KService::Ptr fromString(QString text);
+    static QString buildQuery(KService::Ptr engine, QString text);
+    static KService::Ptr defaultWS();
+
+    static void loadDelimiter();
+    static void loadFavorites();
+    static void loadDefaultWS();
+
+private:
+    static QString m_delimiter;
+    static KService::List m_favorites;
+    static KService::Ptr m_defaultWS;
+};
+
+#endif
diff --git a/src/searchengine.cpp b/src/searchengine.cpp
deleted file mode 100644
index 0a66bb64..00000000
--- a/src/searchengine.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-/* ============================================================
-*
-* This file is a part of the rekonq project
-*
-* Copyright (C) 2008-2010 by Andrea Diamantini <adjam7 at gmail dot com>
-* Copyright (C) 2009-2010 by Lionel Chauvin <megabigbug@yahoo.fr>
-*
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation; either version 2 of
-* the License or (at your option) version 3 or any later version
-* accepted by the membership of KDE e.V. (or its successor approved
-* by the membership of KDE e.V.), which shall act as a proxy
-* defined in Section 14 of version 3 of the license.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*
-* ============================================================ */
-
-
-//local includes
-#include "searchengine.h"
-
-// Auto Includes
-#include "rekonq.h"
-
-//KDE includes
-#include <KConfigGroup>
-#include <KServiceTypeTrader>
-
-
-QString SearchEngine::m_delimiter = "";
-
-
-QString SearchEngine::delimiter()
-{
-    if (m_delimiter == "") loadDelimiter();
-    return m_delimiter;
-}
-
-
-void SearchEngine::loadDelimiter()
-{
-    KConfig config("kuriikwsfilterrc"); //Share with konqueror
-    KConfigGroup cg = config.group("General");
-    m_delimiter = cg.readEntry("KeywordDelimiter", ":");
-}
-
-
-KService::Ptr SearchEngine::m_defaultWS;
-
-
-KService::Ptr SearchEngine::defaultWS()
-{
-    if (!m_defaultWS) loadDefaultWS();
-    return m_defaultWS;
-}
-
-
-void SearchEngine::loadDefaultWS()
-{
-    KConfig config("kuriikwsfilterrc"); //Share with konqueror
-    KConfigGroup cg = config.group("General");
-    QString d = cg.readEntry("DefaultSearchEngine", "google");
-    m_defaultWS = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(d));
-}
-
-
-KService::Ptr SearchEngine::fromString(QString text)
-{
-    KService::List providers = KServiceTypeTrader::self()->query("SearchProvider");
-    int i = 0;
-    bool found = false;
-    KService::Ptr service;
-    while (!found && i < providers.size())
-    {
-        QStringList list = providers.at(i)->property("Keys").toStringList();
-        foreach(const QString &key, list)
-        {
-            const QString searchPrefix = key + delimiter();
-            if (text.startsWith(searchPrefix))
-            {
-                service = providers.at(i);
-                found = true;
-            }
-        }
-        i++;
-    }
-
-    return service;
-}
-
-
-QString SearchEngine::buildQuery(KService::Ptr engine, QString text)
-{
-    QString query = engine->property("Query").toString();
-    query = query.replace("\\{@}", KUrl::toPercentEncoding(text));
-    return query;
-}
-
-
-KService::List SearchEngine::m_favorites;
-
-
-KService::List SearchEngine::favorites()
-{
-    if (m_favorites.isEmpty()) loadFavorites();
-    return m_favorites;
-}
-
-void SearchEngine::loadFavorites()
-{
-  KConfig config("kuriikwsfilterrc"); //Share with konqueror
-  KConfigGroup cg = config.group("General");
-  QStringList favoriteEngines;
-  favoriteEngines << "google"; //defaults
-  favoriteEngines = cg.readEntry("FavoriteSearchEngines", favoriteEngines);
-  
-  KService::List favorites;
-  KService::Ptr service;
-  foreach(const QString &engine, favoriteEngines)
-  {
-    service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(engine));
-    if (service)
-      favorites << service;
-  }
-  
-  m_favorites = favorites;
-}
-
-
-KService::Ptr SearchEngine::defaultEngine()
-{
-  KConfig config("kuriikwsfilterrc"); //Share with konqueror
-  KConfigGroup cg = config.group("General");
-  QString d = cg.readEntry("DefaultSearchEngine");
-  KService::Ptr service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(d));
-  if (!service)
-  {
-    d = QL1S("google");
-    service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(d));
-  }
-  
-  return service;
-  
-}
diff --git a/src/searchengine.h b/src/searchengine.h
deleted file mode 100644
index 2e30e056..00000000
--- a/src/searchengine.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* ============================================================
-*
-* This file is a part of the rekonq project
-*
-* Copyright (C) 2008-2010 by Andrea Diamantini <adjam7 at gmail dot com>
-* Copyright (C) 2009-2010 by Lionel Chauvin <megabigbug@yahoo.fr>
-*
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation; either version 2 of
-* the License or (at your option) version 3 or any later version
-* accepted by the membership of KDE e.V. (or its successor approved
-* by the membership of KDE e.V.), which shall act as a proxy
-* defined in Section 14 of version 3 of the license.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*
-* ============================================================ */
-
-#ifndef SEARCHENGINE_H
-#define SEARCHENGINE_H
-
-
-// Rekonq Includes
-#include "rekonq_defines.h"
-
-// KDE Includes
-#include <KService>
-
-//Qt Includes
-#include <QString>
-
-
-class SearchEngine
-{
-public:
-
-    static QString delimiter();
-    static KService::Ptr defaultEngine();
-    static KService::List favorites();
-    static KService::Ptr fromString(QString text);
-    static QString buildQuery(KService::Ptr engine, QString text);
-    static KService::Ptr defaultWS();
-
-    static void loadDelimiter();
-    static void loadFavorites();
-    static void loadDefaultWS();
-
-private:
-    static QString m_delimiter;
-    static KService::List m_favorites;
-    static KService::Ptr m_defaultWS;
-};
-
-#endif
diff --git a/src/settings/settingsdialog.cpp b/src/settings/settingsdialog.cpp
index cd64f434..d53b1900 100644
--- a/src/settings/settingsdialog.cpp
+++ b/src/settings/settingsdialog.cpp
@@ -36,7 +36,7 @@
 #include "application.h"
 #include "mainwindow.h"
 #include "webtab.h"
-#include "searchengine.h"
+#include "search/searchengine.h"
 
 // Widget Includes
 #include "adblockwidget.h"
diff --git a/src/urlbar/completionwidget.cpp b/src/urlbar/completionwidget.cpp
index b77e2d7c..8e72b26b 100644
--- a/src/urlbar/completionwidget.cpp
+++ b/src/urlbar/completionwidget.cpp
@@ -34,7 +34,7 @@
 // Local Includes
 #include "application.h"
 #include "urlresolver.h"
-#include "searchengine.h"
+#include "search/searchengine.h"
 #include "urlbar.h"
 
 // KDE Includes
diff --git a/src/urlbar/listitem.cpp b/src/urlbar/listitem.cpp
index f10cefd7..c9946257 100644
--- a/src/urlbar/listitem.cpp
+++ b/src/urlbar/listitem.cpp
@@ -36,7 +36,7 @@
 #include "application.h"
 #include "websnap.h"
 #include "completionwidget.h"
-#include "searchengine.h"
+#include "search/searchengine.h"
 
 // KDE Includes
 #include <KIcon>
@@ -161,6 +161,7 @@ TypeIconLabel::TypeIconLabel(int type, QWidget *parent)
     if (type & UrlSearchItem::Browse) hLayout->addWidget(getIcon("applications-internet"));
     if (type & UrlSearchItem::Bookmark) hLayout->addWidget(getIcon("rating"));
     if (type & UrlSearchItem::History) hLayout->addWidget(getIcon("view-history"));
+    if (type & UrlSearchItem::Suggestion) hLayout->addWidget(getIcon("help-hint"));
 }
 
 
@@ -390,6 +391,23 @@ void EngineBar::selectNextEngine()
 // ---------------------------------------------------------------
 
 
+SuggestionListItem::SuggestionListItem(const UrlSearchItem &item, const QString &text, QWidget *parent)
+        : ListItem(item, parent)
+{
+    QHBoxLayout *hLayout = new QHBoxLayout;
+    hLayout->setSpacing(4);
+
+    hLayout->addWidget(new IconLabel(item.url, this));
+    hLayout->addWidget(new TextLabel(item.title, text, this));
+    hLayout->addWidget(new TypeIconLabel(item.type, this));
+
+    setLayout(hLayout);
+}
+
+
+// ---------------------------------------------------------------
+
+
 BrowseListItem::BrowseListItem(const UrlSearchItem &item, const QString &text, QWidget *parent)
         : ListItem(item, parent)
 {
@@ -427,7 +445,15 @@ ListItem *ListItemFactory::create(const UrlSearchItem &item, const QString &text
         }
         else
         {
-            newItem = new PreviewListItem(item, text, parent);
+
+            if (item.type & UrlSearchItem::Suggestion)
+            {
+                newItem = new SuggestionListItem(item, text, parent);
+            }
+            else
+            {
+                newItem = new PreviewListItem(item, text, parent);
+            }
         }
     }
 
diff --git a/src/urlbar/listitem.h b/src/urlbar/listitem.h
index dcb4f76d..0e1a7ad5 100644
--- a/src/urlbar/listitem.h
+++ b/src/urlbar/listitem.h
@@ -174,6 +174,18 @@ private:
 // -------------------------------------------------------------------------
 
 
+class SuggestionListItem : public ListItem
+{
+    Q_OBJECT
+
+public:
+    SuggestionListItem(const UrlSearchItem &item, const QString &text, QWidget *parent = 0);
+};
+
+
+// -------------------------------------------------------------------------
+
+
 class PreviewListItem : public ListItem
 {
     Q_OBJECT
diff --git a/src/urlbar/urlresolver.cpp b/src/urlbar/urlresolver.cpp
index f0fd257b..157e26a2 100644
--- a/src/urlbar/urlresolver.cpp
+++ b/src/urlbar/urlresolver.cpp
@@ -31,7 +31,7 @@
 #include "application.h"
 #include "historymanager.h"
 #include "bookmarksmanager.h"
-#include "searchengine.h"
+#include "search/searchengine.h"
 
 // KDE Includes
 #include <KUriFilter>
@@ -243,11 +243,14 @@ UrlSearchList UrlResolver::orderedSearchItems()
         
         availableEntries -= commonList.count();
     }
+
+    UrlSearchList suggestionsList = suggestionResolution();
     
     historyResults = historyList.count();
     bookmarksResults = bookmarksList.count();
     commonResutls = commonList.count();
-    
+    //TODO: count suggestions entries
+
     //now fill the list to MAX_ELEMENTS
     if(availableEntries > 0)
     {
@@ -275,7 +278,7 @@ UrlSearchList UrlResolver::orderedSearchItems()
         }
     }
     
-    list = list + historyList + commonList + bookmarksList;
+    list = list + historyList + commonList + bookmarksList + suggestionsList;
     qWarning() << "orderedSearchItems leave: " << " elapsed: " << myTime.elapsed();
     
     return list;
@@ -343,6 +346,18 @@ UrlSearchList UrlResolver::bookmarksResolution()
 }
 
 
+// STEP 4 = suggestion completion
+UrlSearchList UrlResolver::suggestionResolution()
+{
+    
+    UrlSearchList list;
+    UrlSearchItem gItem(UrlSearchItem::Suggestion, "a", "a");
+    list << gItem;
+
+    return list;
+}
+
+
 UrlSearchItem UrlResolver::privilegedItem(UrlSearchList* list)
 {
     UrlSearchItem item;
diff --git a/src/urlbar/urlresolver.h b/src/urlbar/urlresolver.h
index c79ce184..d41e3f1a 100644
--- a/src/urlbar/urlresolver.h
+++ b/src/urlbar/urlresolver.h
@@ -50,6 +50,7 @@ public:
         Browse          = 0x00000010,
         History         = 0x00000100,
         Bookmark        = 0x00001000,
+        Suggestion      = 0x00010000,
     };
 
     int type;
@@ -108,7 +109,8 @@ private:
     UrlSearchList qurlFromUserInputResolution();
     UrlSearchList bookmarksResolution();
     UrlSearchItem privilegedItem(UrlSearchList* list);
-     
+    UrlSearchList suggestionResolution();
+
     static QRegExp _browseRegexp;
     static QRegExp _searchEnginesRegexp;
 };
diff --git a/src/webview.cpp b/src/webview.cpp
index 441225af..195f38af 100644
--- a/src/webview.cpp
+++ b/src/webview.cpp
@@ -37,7 +37,7 @@
 #include "mainview.h"
 #include "webpage.h"
 #include "bookmarksmanager.h"
-#include "searchengine.h"
+#include "search/searchengine.h"
 #include "websnap.h"
 
 // KDE Includes
-- 
cgit v1.2.1


From 5c049a00fd9c799ea332436267ba1b85bc08fa1e Mon Sep 17 00:00:00 2001
From: megabigbug <megabigbug@arrakis.(none)>
Date: Sun, 15 Aug 2010 08:37:16 +0200
Subject: wait signal

---
 src/CMakeLists.txt         |  2 ++
 src/application.cpp        | 15 +++++++++++++++
 src/application.h          |  3 +++
 src/urlbar/urlresolver.cpp |  5 +++++
 4 files changed, 25 insertions(+)

(limited to 'src')

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a6658ed0..22419da0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -93,6 +93,7 @@ INCLUDE_DIRECTORIES (   ${CMAKE_CURRENT_SOURCE_DIR}
                         ${CMAKE_CURRENT_SOURCE_DIR}/rekonqpage
                         ${CMAKE_CURRENT_SOURCE_DIR}/settings
                         ${CMAKE_CURRENT_SOURCE_DIR}/analyzer
+                        ${CMAKE_CURRENT_SOURCE_DIR}/search
                         ${CMAKE_CURRENT_BINARY_DIR}
                         ${KDE4_INCLUDES}
                         ${QT4_INCLUDES}
@@ -112,6 +113,7 @@ KDE4_ADD_KDEINIT_EXECUTABLE( rekonq ${rekonq_KDEINIT_SRCS} main.cpp )
 
 TARGET_LINK_LIBRARIES ( kdeinit_rekonq
                         ${QT_LIBRARIES} 
+                        ${QT_QTSCRIPT_LIBRARY}
                         ${QT_QTWEBKIT_LIBRARY} 
                         ${KDE4_KDEWEBKIT_LIBS}
                         ${KDE4_KUTILS_LIBS}
diff --git a/src/application.cpp b/src/application.cpp
index 8a24014d..231b45b7 100644
--- a/src/application.cpp
+++ b/src/application.cpp
@@ -42,6 +42,7 @@
 #include "urlbar.h"
 #include "sessionmanager.h"
 #include "adblockmanager.h"
+#include "search/opensearchmanager.h"
 #include "webview.h"
 #include "filterurljob.h"
 #include "tabbar.h"
@@ -64,6 +65,7 @@ QWeakPointer<HistoryManager> Application::s_historyManager;
 QWeakPointer<BookmarkProvider> Application::s_bookmarkProvider;
 QWeakPointer<SessionManager> Application::s_sessionManager;
 QWeakPointer<AdBlockManager> Application::s_adblockManager;
+QWeakPointer<OpenSearchManager> Application::s_opensearchManager;
 
 
 Application::Application()
@@ -98,6 +100,9 @@ Application::~Application()
 
     delete s_adblockManager.data();
     s_adblockManager.clear();
+    
+    delete s_opensearchManager.data();
+    s_opensearchManager.clear();
 }
 
 
@@ -315,6 +320,16 @@ SessionManager *Application::sessionManager()
 }
 
 
+OpenSearchManager *Application::opensearchManager()
+{
+    if (s_opensearchManager.isNull())
+    {
+        s_opensearchManager = new OpenSearchManager(instance());
+    }
+    return s_opensearchManager.data();
+}
+
+
 KIcon Application::icon(const KUrl &url)
 {
     // avoid infinite loop at startup
diff --git a/src/application.h b/src/application.h
index 18c99afb..11943923 100644
--- a/src/application.h
+++ b/src/application.h
@@ -50,6 +50,7 @@ class HistoryManager;
 class MainWindow;
 class SessionManager;
 class AdBlockManager;
+class OpenSearchManager;
 class WebView;
 
 
@@ -111,6 +112,7 @@ public:
     static BookmarkProvider *bookmarkProvider();
     static SessionManager *sessionManager();
     static AdBlockManager *adblockManager();
+    static OpenSearchManager *opensearchManager();
 
     // DOWNLOADS MANAGEMENT METHODS
     void addDownload(const QString &srcUrl, const QString &destUrl);
@@ -148,6 +150,7 @@ private:
     static QWeakPointer<BookmarkProvider> s_bookmarkProvider;
     static QWeakPointer<SessionManager> s_sessionManager;
     static QWeakPointer<AdBlockManager> s_adblockManager;
+    static QWeakPointer<OpenSearchManager> s_opensearchManager;
 
     MainWindowList m_mainWindows;
 };
diff --git a/src/urlbar/urlresolver.cpp b/src/urlbar/urlresolver.cpp
index 157e26a2..189a5e46 100644
--- a/src/urlbar/urlresolver.cpp
+++ b/src/urlbar/urlresolver.cpp
@@ -349,6 +349,11 @@ UrlSearchList UrlResolver::bookmarksResolution()
 // STEP 4 = suggestion completion
 UrlSearchList UrlResolver::suggestionResolution()
 {
+    Application::opensearchManager()->requestSuggestion();
+    while (!m_suggestionReceived) 
+    { 
+        Application->instance()->processEvents(QEventLoop::WaitForMore | QEventLoop::ExcludeUserInput); 
+    }
     
     UrlSearchList list;
     UrlSearchItem gItem(UrlSearchItem::Suggestion, "a", "a");
-- 
cgit v1.2.1


From 20879867364e31cdd8e80d0f732cf03b140e28ea Mon Sep 17 00:00:00 2001
From: megabigbug <megabigbug@arrakis.(none)>
Date: Sun, 15 Aug 2010 16:19:10 +0200
Subject: working opensearch suggestions

---
 src/application.cpp        |   3 +-
 src/application.h          |   3 +-
 src/urlbar/urlresolver.cpp | 255 ++++++++++++++++++++++++++-------------------
 src/urlbar/urlresolver.h   |  29 ++++--
 4 files changed, 176 insertions(+), 114 deletions(-)

(limited to 'src')

diff --git a/src/application.cpp b/src/application.cpp
index 231b45b7..bfe67f45 100644
--- a/src/application.cpp
+++ b/src/application.cpp
@@ -42,7 +42,7 @@
 #include "urlbar.h"
 #include "sessionmanager.h"
 #include "adblockmanager.h"
-#include "search/opensearchmanager.h"
+#include "opensearchmanager.h"
 #include "webview.h"
 #include "filterurljob.h"
 #include "tabbar.h"
@@ -325,6 +325,7 @@ OpenSearchManager *Application::opensearchManager()
     if (s_opensearchManager.isNull())
     {
         s_opensearchManager = new OpenSearchManager(instance());
+        s_opensearchManager.data()->setSearchProvider("google"); //TODO: use other suggestion engines
     }
     return s_opensearchManager.data();
 }
diff --git a/src/application.h b/src/application.h
index 11943923..a08d883c 100644
--- a/src/application.h
+++ b/src/application.h
@@ -33,6 +33,8 @@
 // Rekonq Includes
 #include "rekonq_defines.h"
 
+#include "opensearchmanager.h"
+
 // KDE Includes
 #include <KUniqueApplication>
 #include <KIcon>
@@ -50,7 +52,6 @@ class HistoryManager;
 class MainWindow;
 class SessionManager;
 class AdBlockManager;
-class OpenSearchManager;
 class WebView;
 
 
diff --git a/src/urlbar/urlresolver.cpp b/src/urlbar/urlresolver.cpp
index 189a5e46..ebd01a58 100644
--- a/src/urlbar/urlresolver.cpp
+++ b/src/urlbar/urlresolver.cpp
@@ -31,7 +31,7 @@
 #include "application.h"
 #include "historymanager.h"
 #include "bookmarksmanager.h"
-#include "search/searchengine.h"
+#include "searchengine.h"
 
 // KDE Includes
 #include <KUriFilter>
@@ -45,7 +45,7 @@
 
 // defines
 #define MAX_ELEMENTS 10
-
+#define MIN_SUGGESTIONS 3
 
 // NOTE 
 // default kurifilter plugin list (at least in my box):
@@ -63,7 +63,8 @@ QRegExp UrlResolver::_browseRegexp;
 QRegExp UrlResolver::_searchEnginesRegexp;
 
 UrlResolver::UrlResolver(const QString &typedUrl)
-        : _typedString(typedUrl.trimmed())
+        : QObject()
+        , _typedString(typedUrl.trimmed())
 {
     if ( _browseRegexp.isEmpty() )
     {
@@ -108,20 +109,9 @@ UrlResolver::UrlResolver(const QString &typedUrl)
 
 UrlSearchList UrlResolver::orderedSearchItems()
 {
-    // NOTE 
-    // the logic here is : "we wanna suggest (at least) 10 elements"
-    // so we have (more or less) 2 from first results (1 from QUrl Resolutions, 1 from
-    // search engines).
-    // There are 8 remaining: if bookmarkResults + historyResults <= 8, catch all, else
-    // catch first 4 results from the two resulting lists :)
-
-    QTime myTime;
-    myTime.start();
-    
-    UrlSearchList list;
-
     if( _typedString == QL1S("about:") )
     {
+        UrlSearchList list;
         UrlSearchItem home(UrlSearchItem::Browse, QString("about:home"),       QL1S("home") );
         list << home;
         UrlSearchItem favs(UrlSearchItem::Browse, QString("about:favorites"),  QL1S("favorites") );
@@ -134,122 +124,152 @@ UrlSearchList UrlResolver::orderedSearchItems()
         list << hist;
         UrlSearchItem down(UrlSearchItem::Browse, QString("about:downloads"),  QL1S("downloads") );
         list << down;
-
+        
         return list;
     }
     
+    _computedListsCount = 0;
+
+    //compute lists
+    computeSuggestions();
+    computeQurlFromUserInput();
+    computeWebSearches();
+    computeBookmarks();
+    computeHistory();
+
+    QTime time;
+    time.start();
+
+    while (_computedListsCount < 5 && time.msec() < 1000)
+    {
+        Application::instance()->processEvents(QEventLoop::WaitForMoreEvents | QEventLoop::ExcludeUserInputEvents); 
+    }
+
+    return orderLists();
+}
+
+
+UrlSearchList UrlResolver::orderLists()
+{
+    // NOTE 
+    // the logic here is : "we wanna suggest (at least) 10 elements"
+    // so we have (more or less) 2 from first results (1 from QUrl Resolutions, 1 from
+    // search engines).
+    // There are 8 remaining: if bookmarkResults + historyResults <= 8, catch all, else
+    // catch first 4 results from the two resulting lists :)
+
+    QTime myTime;
+    myTime.start();
+    
+    UrlSearchList list;
+    
     if(_browseRegexp.indexIn(_typedString) != -1)
     {
-        list << qurlFromUserInputResolution();
-        list << webSearchesResolution();
+        list << _qurlFromUserInput;
+        list << _webSearches;
     }
     else
     {
-        list << webSearchesResolution();
-        list << qurlFromUserInputResolution();
+        list << _webSearches;
+        list << _qurlFromUserInput;
     }
 
     //find the history items that match the typed string
-    UrlSearchList historyList = historyResolution();
-    UrlSearchItem privileged = privilegedItem(&historyList);
-    int historyResults = historyList.count();
+    UrlSearchItem privileged = privilegedItem(&_history);
+    int historyCount = _history.count();
     
     //find the bookmarks items that match the typed string
-    UrlSearchList bookmarksList = bookmarksResolution();
     if (privileged.type == UrlSearchItem::Undefined)
     {
-        privileged = privilegedItem(&bookmarksList);
+        privileged = privilegedItem(&_bookmarks);
     }
-    else if(privileged.type == UrlSearchItem::History && bookmarksList.removeOne(privileged))
+    else if(privileged.type == UrlSearchItem::History && _bookmarks.removeOne(privileged))
     {
         privileged.type |= UrlSearchItem::Bookmark;
     }
-    int bookmarksResults = bookmarksList.count();
+    int bookmarksCount = _bookmarks.count();
     
     if (privileged.type != UrlSearchItem::Undefined)
     {
         list.prepend(privileged);
     }
+
+    int availableEntries = MAX_ELEMENTS - list.count() - MIN_SUGGESTIONS;
     
-    int availableEntries = MAX_ELEMENTS - list.count();
-    
-    UrlSearchList commonList;
-    int commonResutls = 0;
+    UrlSearchList common;
+    int commonCount = 0;
 
     //prefer items which are history items als well bookmarks item
     //if there are more than 1000 bookmark results, the performance impact is noticeable
-    if(bookmarksResults < 1000)
+    if(bookmarksCount < 1000)
     {
         //add as many items to the common list as there are available entries in the dropdown list
         UrlSearchItem urlSearchItem;
-        for(int i = 0; i < historyList.count(); i++)
+        for(int i = 0; i < _history.count(); i++)
         {
-            if (bookmarksList.removeOne(historyList.at(i)))
+            if (_bookmarks.removeOne(_history.at(i)))
             {
-                urlSearchItem = historyList.takeAt(i);
+                urlSearchItem = _history.takeAt(i);
                 urlSearchItem.type |= UrlSearchItem::Bookmark;
-                commonList << urlSearchItem;
-                commonResutls++;
-                if(commonResutls >= availableEntries)
+                common << urlSearchItem;
+                commonCount++;
+                if(commonCount >= availableEntries)
                 {
                     break;
                 }
             }
         }
         
-        commonResutls = commonList.count();
-        if(commonResutls >= availableEntries)
+        commonCount = common.count();
+        if(commonCount >= availableEntries)
         {
-            commonList = commonList.mid(0, availableEntries);
-            historyList = UrlSearchList();
-            bookmarksList = UrlSearchList();
+            common = common.mid(0, availableEntries);
+            _history = UrlSearchList();
+            _bookmarks = UrlSearchList();
             availableEntries = 0;
         }
         else        //remove all items from the history and bookmarks list up to the remaining entries in the dropdown list
         {
-            availableEntries -= commonResutls;
-            if(historyResults >= availableEntries)
+            availableEntries -= commonCount;
+            if(historyCount >= availableEntries)
             {
-                historyList = historyList.mid(0, availableEntries);
+                _history = _history.mid(0, availableEntries);
             }
-            if(bookmarksResults >= availableEntries)
+            if(bookmarksCount >= availableEntries)
             {
-                bookmarksList = bookmarksList.mid(0, availableEntries);
+                _bookmarks = _bookmarks.mid(0, availableEntries);
             }
         }
     }
     else        //if there are too many bookmarks items, remove all items up to the remaining entries in the dropdown list
     {
-        
-        if(historyResults >= availableEntries)
+
+        if(historyCount >= availableEntries)
         {
-            historyList = historyList.mid(0, availableEntries);
+            _history = _history.mid(0, availableEntries);
         }
-        if(bookmarksResults >= availableEntries)
+        if(bookmarksCount >= availableEntries)
         {
-            bookmarksList = bookmarksList.mid(0, availableEntries);
+            _bookmarks = _bookmarks.mid(0, availableEntries);
         }
 
         UrlSearchItem urlSearchItem;
-        for(int i = 0; i < historyList.count(); i++)
+        for(int i = 0; i < _history.count(); i++)
         {
-            if (bookmarksList.removeOne(historyList.at(i)))
+            if (_bookmarks.removeOne(_history.at(i)))
             {
-                urlSearchItem = historyList.takeAt(i);
+                urlSearchItem = _history.takeAt(i);
                 urlSearchItem.type |= UrlSearchItem::Bookmark;
-                commonList << urlSearchItem;
+                common << urlSearchItem;
             }
         }
         
-        availableEntries -= commonList.count();
+        availableEntries -= common.count();
     }
-
-    UrlSearchList suggestionsList = suggestionResolution();
     
-    historyResults = historyList.count();
-    bookmarksResults = bookmarksList.count();
-    commonResutls = commonList.count();
-    //TODO: count suggestions entries
+    historyCount = _history.count();
+    bookmarksCount = _bookmarks.count();
+    commonCount = common.count();
 
     //now fill the list to MAX_ELEMENTS
     if(availableEntries > 0)
@@ -257,28 +277,36 @@ UrlSearchList UrlResolver::orderedSearchItems()
         int historyEntries = ((int) (availableEntries / 2)) + availableEntries % 2;
         int bookmarksEntries = availableEntries - historyEntries;
         
-        if (historyResults >= historyEntries && bookmarksResults >= bookmarksEntries)
+        if (historyCount >= historyEntries && bookmarksCount >= bookmarksEntries)
         {
-            historyList = historyList.mid(0, historyEntries);
-            bookmarksList = bookmarksList.mid(0, bookmarksEntries);
+            _history = _history.mid(0, historyEntries);
+            _bookmarks = _bookmarks.mid(0, bookmarksEntries);
         }
-        else if (historyResults < historyEntries && bookmarksResults >= bookmarksEntries)
+        else if (historyCount < historyEntries && bookmarksCount >= bookmarksEntries)
         {
-            if(historyResults + bookmarksResults > availableEntries)
+            if(historyCount + bookmarksCount > availableEntries)
             {
-                bookmarksList = bookmarksList.mid(0, availableEntries - historyResults);
+                _bookmarks = _bookmarks.mid(0, availableEntries - historyCount);
             }
         }
-        else if (historyResults >= historyEntries && bookmarksResults < bookmarksEntries)
+        else if (historyCount >= historyEntries && bookmarksCount < bookmarksEntries)
         {
-            if(historyResults + bookmarksResults > availableEntries)
+            if(historyCount + bookmarksCount > availableEntries)
             {
-                historyList = historyList.mid(0, availableEntries - bookmarksResults);
+                _history = _history.mid(0, availableEntries - bookmarksCount);
             }
         }
     }
-    
-    list = list + historyList + commonList + bookmarksList + suggestionsList;
+
+    availableEntries -=  _history.count();
+    availableEntries -=  _bookmarks.count();
+
+    if (_suggestions.count() > availableEntries + MIN_SUGGESTIONS)
+    {
+        _suggestions = _suggestions.mid(0, availableEntries + MIN_SUGGESTIONS);
+    }
+
+    list = list + _history + common + _bookmarks + _suggestions;
     qWarning() << "orderedSearchItems leave: " << " elapsed: " << myTime.elapsed();
     
     return list;
@@ -289,77 +317,92 @@ UrlSearchList UrlResolver::orderedSearchItems()
 // PRIVATE ENGINES
 
 
-// STEP 1 = QUrl from User Input (easily the best solution... )
-UrlSearchList UrlResolver::qurlFromUserInputResolution()
+//QUrl from User Input (easily the best solution... )
+void UrlResolver::computeQurlFromUserInput()
 {
-    UrlSearchList list;
-    QString url2 = _typedString;
-    QUrl urlFromUserInput = QUrl::fromUserInput(url2);
+    QString url = _typedString;
+    QUrl urlFromUserInput = QUrl::fromUserInput(url);
     if (urlFromUserInput.isValid())
     {
         QString gTitle = i18nc("Browse a website", "Browse");
         UrlSearchItem gItem(UrlSearchItem::Browse, urlFromUserInput.toString(), gTitle);
-        list << gItem;
+        _qurlFromUserInput << gItem;
     }
 
-    return list;
+    _computedListsCount++;
 }
 
 
-// STEP 2 = Web Searches
-UrlSearchList UrlResolver::webSearchesResolution()
+//webSearches
+void UrlResolver::computeWebSearches()
 {
-    return UrlSearchList() << UrlSearchItem(UrlSearchItem::Search, QString(), QString());
+    _webSearches = (UrlSearchList() << UrlSearchItem(UrlSearchItem::Search, QString(), QString()));
+    _computedListsCount++;
 }
 
 
-// STEP 3 = history completion
-UrlSearchList UrlResolver::historyResolution()
+//history
+void UrlResolver::computeHistory()
 {
     QList<HistoryHashItem> found = Application::historyManager()->find(_typedString);
     qSort(found);
 
-    UrlSearchList list;
     foreach (HistoryHashItem i, found)
     {
         if (_searchEnginesRegexp.indexIn(i.url) == -1) //filter all urls that are search engine results
         {
             UrlSearchItem gItem(UrlSearchItem::History, i.url, i.title);
-            list << gItem;
+            _history << gItem;
         }
     }
-    return list;
+
+    _computedListsCount++;
 }
 
 
-// STEP 4 = bookmarks completion
-UrlSearchList UrlResolver::bookmarksResolution()
+// bookmarks
+void UrlResolver::computeBookmarks()
 {
-    UrlSearchList list;
     QList<KBookmark> found = Application::bookmarkProvider()->find(_typedString);
+
     foreach (KBookmark b, found)
     {
         UrlSearchItem gItem(UrlSearchItem::Bookmark, b.url().url(), b.fullText());
-        list << gItem;
+        _bookmarks << gItem;
     }
-    return list;
+
+    _computedListsCount++;
 }
 
 
-// STEP 4 = suggestion completion
-UrlSearchList UrlResolver::suggestionResolution()
+//opensearch suggestion
+void UrlResolver::computeSuggestions()
 {
-    Application::opensearchManager()->requestSuggestion();
-    while (!m_suggestionReceived) 
-    { 
-        Application->instance()->processEvents(QEventLoop::WaitForMore | QEventLoop::ExcludeUserInput); 
+    if (Application::opensearchManager()->isSuggestionAvailable())
+    {
+        connect(Application::opensearchManager(), 
+                SIGNAL(suggestionReceived(const QStringList &)), 
+                this, 
+                SLOT(suggestionsReceived(const QStringList &)));
+
+        Application::opensearchManager()->requestSuggestion(_typedString);
     }
-    
-    UrlSearchList list;
-    UrlSearchItem gItem(UrlSearchItem::Suggestion, "a", "a");
-    list << gItem;
+    else
+    {
+        _computedListsCount++;
+    }
+}
 
-    return list;
+
+void UrlResolver::suggestionsReceived(const QStringList &suggestion)
+{
+    foreach (QString s, suggestion)
+    {
+        UrlSearchItem gItem(UrlSearchItem::Suggestion, s, s);
+        _suggestions << gItem;
+    }
+
+    _computedListsCount++;
 }
 
 
diff --git a/src/urlbar/urlresolver.h b/src/urlbar/urlresolver.h
index d41e3f1a..f72d6731 100644
--- a/src/urlbar/urlresolver.h
+++ b/src/urlbar/urlresolver.h
@@ -38,6 +38,7 @@
 // Qt Includes
 #include <QString>
 #include <QList>
+#include <QStringList>
 
 class UrlSearchItem
 {
@@ -94,8 +95,10 @@ typedef QList <UrlSearchItem> UrlSearchList;
 // ----------------------------------------------------------------------
 
 
-class UrlResolver
+class UrlResolver : public QObject
 {
+    Q_OBJECT
+
 public:
     UrlResolver(const QString &typedUrl);
 
@@ -104,15 +107,29 @@ public:
 private:
     QString _typedString;
 
-    UrlSearchList webSearchesResolution();
-    UrlSearchList historyResolution();
-    UrlSearchList qurlFromUserInputResolution();
-    UrlSearchList bookmarksResolution();
+    UrlSearchList _webSearches;
+    UrlSearchList _qurlFromUserInput;
+    UrlSearchList _history;
+    UrlSearchList _bookmarks;
+    UrlSearchList _suggestions;
+    
+    void computeWebSearches();
+    void computeHistory();
+    void computeQurlFromUserInput();
+    void computeBookmarks();
+    void computeSuggestions();
+
+    int _computedListsCount;
+
     UrlSearchItem privilegedItem(UrlSearchList* list);
-    UrlSearchList suggestionResolution();
+    UrlSearchList orderLists();
 
     static QRegExp _browseRegexp;
     static QRegExp _searchEnginesRegexp;
+    
+private slots:
+    void suggestionsReceived(const QStringList &suggestion);    
+    
 };
 
 // ------------------------------------------------------------------------------
-- 
cgit v1.2.1