Removed GPL code. Added own implementation of suggestions engine. Fixed Google maps different issues

This commit is contained in:
vladest 2017-10-30 18:15:42 +01:00
parent c735809e32
commit 586dde7dd7
8 changed files with 147 additions and 853 deletions

View file

@ -36,13 +36,11 @@ Rectangle {
property bool keyboardRaised: false
property bool punctuationMode: false
property var suggestionsList: []
readonly property string searchUrlTemplate: "https://www.google.com/search?client=hifibrowser&q=";
OpenSearchEngine {
WebBrowserSuggestionsEngine {
id: searchEngine
name: "Google";
searchUrlTemplate: "https://www.google.com/search?client=hifibrowser&q={searchTerms}";
suggestionsUrlTemplate: "https://suggestqueries.google.com/complete/search?output=firefox&q=%s";
suggestionsUrl: "https://suggestqueries.google.com/complete/search?output=firefox&q=%s";
onSuggestions: {
if (suggestions.length > 0) {
@ -65,7 +63,7 @@ Rectangle {
repeat: false
onTriggered: {
if (addressBar.editText !== "") {
searchEngine.requestSuggestions(addressBarInput.text);
searchEngine.querySuggestions(addressBarInput.text);
}
}
}
@ -74,18 +72,19 @@ Rectangle {
function goTo(url) {
//must be valid attempt to open an site with dot
var urlNew = url
if (url.indexOf(".") > 0) {
if (url.indexOf("http") < 0) {
url = "http://" + url;
urlNew = "http://" + url;
}
} else {
url = searchEngine.searchUrl(url)
urlNew = searchUrlTemplate + url
}
addressBar.model = []
webStack.currentItem.webEngineView.url = url
addressBar.editText = webStack.currentItem.webEngineView.url
//need to rebind if binfing was broken by selecting from suggestions
addressBar.editText = Qt.binding( function() { return webStack.currentItem.webEngineView.url; });
webStack.currentItem.webEngineView.url = urlNew
suggestionRequestTimer.stop();
addressBar.popup.close();
}
@ -305,11 +304,13 @@ Rectangle {
objectName: "tabletWebEngineView"
//profile: HFWebEngineProfile;
profile.httpUserAgent: "Mozilla/5.0 (Android; Mobile; rv:13.0) Gecko/13.0 Firefox/13.0"
property string userScriptUrl: ""
onLoadingChanged: {
if (!loading) {
addressBarInput.cursorPosition = 0 //set input field cursot to beginning
suggestionRequestTimer.stop();
addressBar.popup.close();
}
@ -360,7 +361,6 @@ Rectangle {
Component.onCompleted: {
webChannel.registerObject("eventBridge", eventBridge);
webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper);
//webEngineView.profile.httpUserAgent = "Mozilla/5.0 Chrome (HighFidelityInterface)";
}
onFeaturePermissionRequested: {

View file

@ -203,7 +203,7 @@
#include "commerce/Wallet.h"
#include "commerce/QmlCommerce.h"
#include "opensearch/opensearchengine.h"
#include "webbrowser/webbrowsersuggestionsengine.h"
// On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU
// FIXME seems to be broken.
@ -2225,7 +2225,7 @@ void Application::initializeUi() {
QmlCommerce::registerType();
qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem");
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
qmlRegisterType<OpenSearchEngine>("HifiWeb", 1, 0, "OpenSearchEngine");
qmlRegisterType<WebBrowserSuggestionsEngine>("HifiWeb", 1, 0, "WebBrowserSuggestionsEngine");
auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->create();

View file

@ -1,650 +0,0 @@
#include "opensearchengine.h"
#include "qregexp.h"
#include "opensearchenginedelegate.h"
#include <qbuffer.h>
#include <qcoreapplication.h>
#include <qlocale.h>
#include <qnetworkrequest.h>
#include <qnetworkreply.h>
#include <qregexp.h>
#include <qstringlist.h>
#include <QUrlQuery>
#include <QJsonDocument>
#include <NetworkAccessManager.h>
/*!
\class OpenSearchEngine
\brief A class representing a single search engine described in OpenSearch format
OpenSearchEngine is a class that represents a single search engine based on
the OpenSearch format.
For more information about the format, see http://www.opensearch.org/.
Instances of the class hold all the data associated with the corresponding search
engines, such as name(), description() and also URL templates that are used
to construct URLs, which can be used later to perform search queries. Search engine
can also have an image, even an external one, in this case it will be downloaded
automatically from the network.
OpenSearchEngine instances can be constructed from scratch but also read from
external sources and written back to them. OpenSearchReader and OpenSearchWriter
are the classes provided for reading and writing OpenSearch descriptions.
Default constructed engines need to be filled with the necessary information before
they can be used to peform search requests. First of all, a search engine should have
the metadata including the name and the description.
However, the most important are URL templates, which are the construction of URLs
but can also contain template parameters, that are replaced with corresponding values
at the time of constructing URLs.
There are two types of URL templates: search URL template and suggestions URL template.
Search URL template is needed for constructing search URLs, which point directly to
search results. Suggestions URL template is necessary to construct suggestion queries
URLs, which are then used for requesting contextual suggestions, a popular service
offered along with search results that provides search terms related to what has been
supplied by the user.
Both types of URLs are constructed by the class, by searchUrl() and suggestionsUrl()
functions respectively. However, search requests are supposed to be performed outside
the class, while suggestion queries can be executed using the requestSuggestions()
method. The class will take care of peforming the network request and parsing the
JSON response.
Both the image request and suggestion queries need network access. The class can
perform network requests on its own, though the client application needs to provide
a network access manager, which then will to be used for network operations.
Without that, both images delivered from remote locations and contextual suggestions
will be disabled.
\sa OpenSearchReader, OpenSearchWriter
*/
/*!
Constructs an engine with a given \a parent.
*/
OpenSearchEngine::OpenSearchEngine(QObject* parent)
: QObject(parent)
, m_searchMethod(QLatin1String("get"))
, m_suggestionsMethod(QLatin1String("get"))
, m_suggestionsReply(0)
, m_delegate(0)
{
m_requestMethods.insert(QLatin1String("get"), QNetworkAccessManager::GetOperation);
m_requestMethods.insert(QLatin1String("post"), QNetworkAccessManager::PostOperation);
}
/*!
A destructor.
*/
OpenSearchEngine::~OpenSearchEngine()
{
}
QString OpenSearchEngine::parseTemplate(const QString &searchTerm, const QString &searchTemplate)
{
QString language = QLocale().name();
// Simple conversion to RFC 3066.
language = language.replace(QLatin1Char('_'), QLatin1Char('-'));
QString result = searchTemplate;
result.replace(QLatin1String("{count}"), QLatin1String("20"));
result.replace(QLatin1String("{startIndex}"), QLatin1String("0"));
result.replace(QLatin1String("{startPage}"), QLatin1String("0"));
result.replace(QLatin1String("{language}"), language);
result.replace(QLatin1String("{inputEncoding}"), QLatin1String("UTF-8"));
result.replace(QLatin1String("{outputEncoding}"), QLatin1String("UTF-8"));
result.replace(QRegExp(QLatin1String("\\{([^\\}]*:|)source\\??\\}")), QCoreApplication::applicationName());
result.replace(QLatin1String("{searchTerms}"), QLatin1String(QUrl::toPercentEncoding(searchTerm)));
return result;
}
/*!
\property OpenSearchEngine::name
\brief the name of the engine
\sa description()
*/
QString OpenSearchEngine::name() const
{
return m_name;
}
void OpenSearchEngine::setName(const QString &name)
{
m_name = name;
}
/*!
\property OpenSearchEngine::description
\brief the description of the engine
\sa name()
*/
QString OpenSearchEngine::description() const
{
return m_description;
}
void OpenSearchEngine::setDescription(const QString &description)
{
m_description = description;
}
/*!
\property OpenSearchEngine::searchUrlTemplate
\brief the template of the search URL
\sa searchUrl(), searchParameters(), suggestionsUrlTemplate()
*/
QString OpenSearchEngine::searchUrlTemplate() const
{
return m_searchUrlTemplate;
}
void OpenSearchEngine::setSearchUrlTemplate(const QString &searchUrlTemplate)
{
if (!searchUrlTemplate.startsWith(QLatin1String("http://")) && !searchUrlTemplate.startsWith(QLatin1String("https://"))) {
return;
}
m_searchUrlTemplate = searchUrlTemplate;
}
/*!
Constructs and returns a search URL with a given \a searchTerm.
The URL template is processed according to the specification:
http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_URL_template_syntax
A list of template parameters currently supported and what they are replaced with:
\table
\header \o parameter
\o value
\row \o "{count}"
\o "20"
\row \o "{startIndex}"
\o "0"
\row \o "{startPage}"
\o "0"
\row \o "{language}"
\o "the default language code (RFC 3066)"
\row \o "{inputEncoding}"
\o "UTF-8"
\row \o "{outputEncoding}"
\o "UTF-8"
\row \o "{*:source}"
\o "application name, QCoreApplication::applicationName()"
\row \o "{searchTerms}"
\o "the string supplied by the user"
\endtable
\sa searchUrlTemplate(), searchParameters(), suggestionsUrl()
*/
QUrl OpenSearchEngine::searchUrl(const QString &searchTerm) const
{
if (m_searchUrlTemplate.isEmpty()) {
return QUrl();
}
QUrl retVal = QUrl::fromEncoded(parseTemplate(searchTerm, m_searchUrlTemplate).toUtf8());
QUrlQuery query(retVal);
if (m_searchMethod != QLatin1String("post")) {
Parameters::const_iterator end = m_searchParameters.constEnd();
Parameters::const_iterator i = m_searchParameters.constBegin();
for (; i != end; ++i) {
query.addQueryItem(i->first, parseTemplate(searchTerm, i->second));
}
retVal.setQuery(query);
}
return retVal;
}
QByteArray OpenSearchEngine::getPostData(const QString &searchTerm) const
{
if (m_searchMethod != QLatin1String("post")) {
return QByteArray();
}
QUrl retVal = QUrl("http://foo.bar");
QUrlQuery query(retVal);
Parameters::const_iterator end = m_searchParameters.constEnd();
Parameters::const_iterator i = m_searchParameters.constBegin();
for (; i != end; ++i) {
query.addQueryItem(i->first, parseTemplate(searchTerm, i->second));
}
retVal.setQuery(query);
QByteArray data = retVal.toEncoded(QUrl::RemoveScheme);
return data.contains('?') ? data.mid(data.lastIndexOf('?') + 1) : QByteArray();
}
/*!
\property providesSuggestions
\brief indicates whether the engine supports contextual suggestions
*/
bool OpenSearchEngine::providesSuggestions() const
{
return (!m_suggestionsUrlTemplate.isEmpty() || !m_preparedSuggestionsUrl.isEmpty());
}
/*!
\property OpenSearchEngine::suggestionsUrlTemplate
\brief the template of the suggestions URL
\sa suggestionsUrl(), suggestionsParameters(), searchUrlTemplate()
*/
QString OpenSearchEngine::suggestionsUrlTemplate() const
{
return m_suggestionsUrlTemplate;
}
void OpenSearchEngine::setSuggestionsUrlTemplate(const QString &suggestionsUrlTemplate)
{
if (!suggestionsUrlTemplate.startsWith(QLatin1String("http://")) && !suggestionsUrlTemplate.startsWith(QLatin1String("https://"))) {
return;
}
m_suggestionsUrlTemplate = suggestionsUrlTemplate;
}
/*!
Constructs a suggestions URL with a given \a searchTerm.
The URL template is processed according to the specification:
http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_URL_template_syntax
See searchUrl() for more information about processing template parameters.
\sa suggestionsUrlTemplate(), suggestionsParameters(), searchUrl()
*/
QUrl OpenSearchEngine::suggestionsUrl(const QString &searchTerm) const
{
if (!m_preparedSuggestionsUrl.isEmpty()) {
QString s = m_preparedSuggestionsUrl;
s.replace(QLatin1String("%s"), searchTerm);
return QUrl(s);
}
if (m_suggestionsUrlTemplate.isEmpty()) {
return QUrl();
}
QUrl retVal = QUrl::fromEncoded(parseTemplate(searchTerm, m_suggestionsUrlTemplate).toUtf8());
QUrlQuery query(retVal);
if (m_suggestionsMethod != QLatin1String("post")) {
Parameters::const_iterator end = m_suggestionsParameters.constEnd();
Parameters::const_iterator i = m_suggestionsParameters.constBegin();
for (; i != end; ++i) {
query.addQueryItem(i->first, parseTemplate(searchTerm, i->second));
}
retVal.setQuery(query);
}
return retVal;
}
/*!
\property searchParameters
\brief additional parameters that will be included in the search URL
For more information see:
http://www.opensearch.org/Specifications/OpenSearch/Extensions/Parameter/1.0
*/
OpenSearchEngine::Parameters OpenSearchEngine::searchParameters() const
{
return m_searchParameters;
}
void OpenSearchEngine::setSearchParameters(const Parameters &searchParameters)
{
m_searchParameters = searchParameters;
}
/*!
\property suggestionsParameters
\brief additional parameters that will be included in the suggestions URL
For more information see:
http://www.opensearch.org/Specifications/OpenSearch/Extensions/Parameter/1.0
*/
OpenSearchEngine::Parameters OpenSearchEngine::suggestionsParameters() const
{
return m_suggestionsParameters;
}
void OpenSearchEngine::setSuggestionsParameters(const Parameters &suggestionsParameters)
{
m_suggestionsParameters = suggestionsParameters;
}
/*!
\property searchMethod
\brief HTTP request method that will be used to perform search requests
*/
QString OpenSearchEngine::searchMethod() const
{
return m_searchMethod;
}
void OpenSearchEngine::setSearchMethod(const QString &method)
{
QString requestMethod = method.toLower();
if (!m_requestMethods.contains(requestMethod)) {
return;
}
m_searchMethod = requestMethod;
}
/*!
\property suggestionsMethod
\brief HTTP request method that will be used to perform suggestions requests
*/
QString OpenSearchEngine::suggestionsMethod() const
{
return m_suggestionsMethod;
}
void OpenSearchEngine::setSuggestionsMethod(const QString &method)
{
QString requestMethod = method.toLower();
if (!m_requestMethods.contains(requestMethod)) {
return;
}
m_suggestionsMethod = requestMethod;
}
/*!
\property imageUrl
\brief the image URL of the engine
When setting a new image URL, it won't be loaded immediately. The first request will be
deferred until image() is called for the first time.
\note To be able to request external images, you need to provide a network access manager,
which will be used for network operations.
\sa image(), networkAccessManager()
*/
QString OpenSearchEngine::imageUrl() const
{
return m_imageUrl;
}
void OpenSearchEngine::setImageUrl(const QString &imageUrl)
{
m_imageUrl = imageUrl;
}
void OpenSearchEngine::loadImage() const
{
if (m_imageUrl.isEmpty()) {
return;
}
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(QUrl::fromEncoded(m_imageUrl.toUtf8())));
connect(reply, SIGNAL(finished()), this, SLOT(imageObtained()));
}
void OpenSearchEngine::imageObtained()
{
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
if (!reply) {
return;
}
QByteArray response = reply->readAll();
reply->close();
reply->deleteLater();
if (response.isEmpty()) {
return;
}
m_image.loadFromData(response);
emit imageChanged();
}
/*!
\property image
\brief the image of the engine
When no image URL has been set and an image will be set explicitly, a new data URL
will be constructed, holding the image data encoded with Base64.
\sa imageUrl()
*/
QImage OpenSearchEngine::image() const
{
if (m_image.isNull()) {
loadImage();
}
return m_image;
}
void OpenSearchEngine::setImage(const QImage &image)
{
if (m_imageUrl.isEmpty()) {
QBuffer imageBuffer;
imageBuffer.open(QBuffer::ReadWrite);
if (image.save(&imageBuffer, "PNG")) {
m_imageUrl = QString(QLatin1String("data:image/png;base64,%1"))
.arg(QLatin1String(imageBuffer.buffer().toBase64()));
}
}
m_image = image;
emit imageChanged();
}
/*!
\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());
}
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);
}
/*!
Requests contextual suggestions on the search engine, for a given \a searchTerm.
If succeeded, suggestions() signal will be emitted once the suggestions are received.
\note To be able to request suggestions, you need to provide a network access manager,
which will be used for network operations.
\sa requestSearchResults()
*/
void OpenSearchEngine::setSuggestionsParameters(const QByteArray &parameters)
{
m_preparedSuggestionsParameters = parameters;
}
void OpenSearchEngine::setSuggestionsUrl(const QString &string)
{
m_preparedSuggestionsUrl = string;
}
QString OpenSearchEngine::getSuggestionsUrl()
{
return suggestionsUrl("searchstring").toString().replace(QLatin1String("searchstring"), QLatin1String("%s"));
}
QByteArray OpenSearchEngine::getSuggestionsParameters()
{
QStringList parameters;
Parameters::const_iterator end = m_suggestionsParameters.constEnd();
Parameters::const_iterator i = m_suggestionsParameters.constBegin();
for (; i != end; ++i) {
parameters.append(i->first + QLatin1String("=") + i->second);
}
QByteArray data = parameters.join(QLatin1String("&")).toUtf8();
return data;
}
void OpenSearchEngine::requestSuggestions(const QString &searchTerm)
{
if (searchTerm.isEmpty() || !providesSuggestions()) {
return;
}
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
if (m_suggestionsReply) {
m_suggestionsReply->disconnect(this);
m_suggestionsReply->abort();
m_suggestionsReply->deleteLater();
m_suggestionsReply = 0;
}
Q_ASSERT(m_requestMethods.contains(m_suggestionsMethod));
if (m_suggestionsMethod == QLatin1String("get")) {
m_suggestionsReply = networkAccessManager.get(QNetworkRequest(suggestionsUrl(searchTerm)));
}
else {
QStringList parameters;
Parameters::const_iterator end = m_suggestionsParameters.constEnd();
Parameters::const_iterator i = m_suggestionsParameters.constBegin();
for (; i != end; ++i) {
parameters.append(i->first + QLatin1String("=") + i->second);
}
QByteArray data = parameters.join(QLatin1String("&")).toUtf8();
m_suggestionsReply = networkAccessManager.post(QNetworkRequest(suggestionsUrl(searchTerm)), data);
}
connect(m_suggestionsReply, SIGNAL(finished()), this, SLOT(suggestionsObtained()));
}
/*!
Requests search results on the search engine, for a given \a searchTerm.
The default implementation does nothing, to supply your own you need to create your own
OpenSearchEngineDelegate subclass and supply it to the engine. Then the function will call
the performSearchRequest() method of the delegate, which can then handle the request
in a custom way.
\sa requestSuggestions(), delegate()
*/
void OpenSearchEngine::requestSearchResults(const QString &searchTerm)
{
if (!m_delegate || searchTerm.isEmpty()) {
return;
}
Q_ASSERT(m_requestMethods.contains(m_searchMethod));
QNetworkRequest request(QUrl(searchUrl(searchTerm)));
QByteArray data;
QNetworkAccessManager::Operation operation = m_requestMethods.value(m_searchMethod);
if (operation == QNetworkAccessManager::PostOperation) {
QStringList parameters;
Parameters::const_iterator end = m_searchParameters.constEnd();
Parameters::const_iterator i = m_searchParameters.constBegin();
for (; i != end; ++i) {
parameters.append(i->first + QLatin1String("=") + i->second);
}
data = parameters.join(QLatin1String("&")).toUtf8();
}
m_delegate->performSearchRequest(request, operation, data);
}
void OpenSearchEngine::suggestionsObtained()
{
const QByteArray response = m_suggestionsReply->readAll();
m_suggestionsReply->close();
m_suggestionsReply->deleteLater();
m_suggestionsReply = 0;
QJsonParseError err;
QJsonDocument json = QJsonDocument::fromJson(response, &err);
const QVariant res = json.toVariant();
if (err.error != QJsonParseError::NoError || res.type() != QVariant::List)
return;
const QVariantList list = res.toList();
if (list.size() < 2)
return;
QStringList out;
foreach (const QVariant &v, list.at(1).toList())
out.append(v.toString());
emit suggestions(out);
}
/*!
\property delegate
\brief the delegate that is used to perform specific tasks.
It can be currently supplied to provide a custom behaviour ofthe requetSearchResults() method.
The default implementation does nothing.
*/
OpenSearchEngineDelegate* OpenSearchEngine::delegate() const
{
return m_delegate;
}
void OpenSearchEngine::setDelegate(OpenSearchEngineDelegate* delegate)
{
m_delegate = delegate;
}
/*!
\fn void OpenSearchEngine::imageChanged()
This signal is emitted whenever the image of the engine changes.
\sa image(), imageUrl()
*/
/*!
\fn void OpenSearchEngine::suggestions(const QStringList &suggestions)
This signal is emitted whenever new contextual suggestions have been provided
by the search engine. To request suggestions, use requestSuggestions().
The suggestion set is specified by \a suggestions.
\sa requestSuggestions()
*/

View file

@ -1,128 +0,0 @@
#ifndef OPENSEARCHENGINE_H
#define OPENSEARCHENGINE_H
#include <qpair.h>
#include <qimage.h>
#include <qmap.h>
#include <qnetworkaccessmanager.h>
#include <qstring.h>
#include <qurl.h>
class QNetworkReply;
class OpenSearchEngineDelegate;
class OpenSearchEngine : public QObject
{
Q_OBJECT
signals:
void imageChanged();
void suggestions(const QStringList &suggestions);
public:
typedef QPair<QString, QString> Parameter;
typedef QList<Parameter> Parameters;
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(QString description READ description WRITE setDescription)
Q_PROPERTY(QString searchUrlTemplate READ searchUrlTemplate WRITE setSearchUrlTemplate)
Q_PROPERTY(Parameters searchParameters READ searchParameters WRITE setSearchParameters)
Q_PROPERTY(QString searchMethod READ searchMethod WRITE setSearchMethod)
Q_PROPERTY(QString suggestionsUrlTemplate READ suggestionsUrlTemplate WRITE setSuggestionsUrlTemplate)
Q_PROPERTY(QString suggestionsUrl READ getSuggestionsUrl WRITE setSuggestionsUrl)
Q_PROPERTY(Parameters suggestionsParameters READ suggestionsParameters WRITE setSuggestionsParameters)
Q_PROPERTY(QString suggestionsMethod READ suggestionsMethod WRITE setSuggestionsMethod)
Q_PROPERTY(bool providesSuggestions READ providesSuggestions)
Q_PROPERTY(QString imageUrl READ imageUrl WRITE setImageUrl)
Q_PROPERTY(bool valid READ isValid)
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);
QByteArray getPostData(const QString &searchTerm) const;
bool providesSuggestions() const;
QString suggestionsUrlTemplate() const;
void setSuggestionsUrlTemplate(const QString &suggestionsUrl);
QUrl suggestionsUrl(const QString &searchTerm) const;
Parameters searchParameters() const;
void setSearchParameters(const Parameters &searchParameters);
Parameters suggestionsParameters() const;
void setSuggestionsParameters(const Parameters &suggestionsParameters);
QString searchMethod() const;
void setSearchMethod(const QString &method);
QString suggestionsMethod() const;
void setSuggestionsMethod(const QString &method);
QString imageUrl() const;
void setImageUrl(const QString &url);
QImage image() const;
void setImage(const QImage &image);
bool isValid() const;
void setSuggestionsUrl(const QString &string);
void setSuggestionsParameters(const QByteArray &parameters);
QString getSuggestionsUrl();
QByteArray getSuggestionsParameters();
OpenSearchEngineDelegate* delegate() const;
void setDelegate(OpenSearchEngineDelegate* delegate);
bool operator==(const OpenSearchEngine &other) const;
bool operator<(const OpenSearchEngine &other) const;
public slots:
QUrl searchUrl(const QString &searchTerm) const;
void requestSuggestions(const QString &searchTerm);
void requestSearchResults(const QString &searchTerm);
protected:
static QString parseTemplate(const QString &searchTerm, const QString &searchTemplate);
void loadImage() const;
private slots:
void imageObtained();
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;
QByteArray m_preparedSuggestionsParameters;
QString m_preparedSuggestionsUrl;
QMap<QString, QNetworkAccessManager::Operation> m_requestMethods;
QNetworkReply* m_suggestionsReply;
OpenSearchEngineDelegate* m_delegate;
};
#endif // OPENSEARCHENGINE_H

View file

@ -1,43 +0,0 @@
#include "opensearchenginedelegate.h"
/*!
\class OpenSearchEngineDelegate
\brief An abstract class providing custom processing of specific activities.
OpenSearchEngineDelegate is an abstract class that can be subclassed and set on
an OpenSearchEngine. It allows to customize some parts of the default implementation
or even extend it with missing bits.
Currently subclasses can only provide a custom way of handling search requests by
reimplementing the performSearchRequest() method.
\sa OpenSearchEngine
*/
/*!
Constructs the delegate.
*/
OpenSearchEngineDelegate::OpenSearchEngineDelegate()
{
}
/*!
Destructs the delegate.
*/
OpenSearchEngineDelegate::~OpenSearchEngineDelegate()
{
}
/*!
\fn void performSearchRequest(const QNetworkRequest &request,
QNetworkAccessManager::Operation operation, const QByteArray &data) = 0
This method will be used after OpenSearchEngine::requestResults() is called.
For example, a console application that uses the OpenSearchEngine class to generate
a search URL for a search term supplied by the user would reimplement the function
and forward the request to e.g. a web browser.
Likewise, a web browser that uses the OpenSearchEngine class to support multiple search
engines e.g. in a toolbar would perform the request and navigate to the search results site.
*/

View file

@ -1,18 +0,0 @@
#ifndef OPENSEARCHENGINEDELEGATE_H
#define OPENSEARCHENGINEDELEGATE_H
#include <qnetworkaccessmanager.h>
#include <qnetworkrequest.h>
class OpenSearchEngineDelegate
{
public:
OpenSearchEngineDelegate();
virtual ~OpenSearchEngineDelegate();
virtual void performSearchRequest(const QNetworkRequest &request,
QNetworkAccessManager::Operation operation,
const QByteArray &data) = 0;
};
#endif // OPENSEARCHENGINEDELEGATE_H

View file

@ -0,0 +1,87 @@
//
// webbrowsersuggestionsengine.cpp
// interface/src/webbrowser
//
// Created by Vlad Stelmahovsky Kapolka on 30/10/17.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "webbrowsersuggestionsengine.h"
#include "qregexp.h"
#include <qbuffer.h>
#include <qcoreapplication.h>
#include <qlocale.h>
#include <qnetworkrequest.h>
#include <qnetworkreply.h>
#include <qregexp.h>
#include <qstringlist.h>
#include <QUrlQuery>
#include <QJsonDocument>
#include <NetworkAccessManager.h>
const QString GoogleSuggestionsUrl = "https://suggestqueries.google.com/complete/search?output=firefox&q=%1";
WebBrowserSuggestionsEngine::WebBrowserSuggestionsEngine(QObject* parent)
: QObject(parent)
, _suggestionsReply(0) {
_currentNAM = &NetworkAccessManager::getInstance();
connect(_currentNAM, &QNetworkAccessManager::finished, this, &WebBrowserSuggestionsEngine::suggestionsFinished);
}
WebBrowserSuggestionsEngine::~WebBrowserSuggestionsEngine() {
disconnect(_currentNAM, &QNetworkAccessManager::finished, this, &WebBrowserSuggestionsEngine::suggestionsFinished);
}
void WebBrowserSuggestionsEngine::querySuggestions(const QString &searchString) {
if (_suggestionsReply) {
_suggestionsReply->disconnect(this);
_suggestionsReply->abort();
_suggestionsReply->deleteLater();
_suggestionsReply = 0;
}
QString url = QString(GoogleSuggestionsUrl).arg(searchString);
_suggestionsReply = _currentNAM->get(QNetworkRequest(url));
}
void WebBrowserSuggestionsEngine::suggestionsFinished(QNetworkReply *reply) {
if (reply != _suggestionsReply) {
return; //invalid reply. ignore
}
const QByteArray response = _suggestionsReply->readAll();
_suggestionsReply->close();
_suggestionsReply->deleteLater();
_suggestionsReply = 0;
QJsonParseError err;
QJsonDocument json = QJsonDocument::fromJson(response, &err);
const QVariant res = json.toVariant();
if (err.error != QJsonParseError::NoError || res.type() != QVariant::List) {
return;
}
const QVariantList list = res.toList();
if (list.size() < 2) {
return;
}
QStringList out;
const QVariantList& suggList = list.at(1).toList();
foreach (const QVariant &v, suggList) {
out.append(v.toString());
}
emit suggestions(out);
}

View file

@ -0,0 +1,46 @@
#ifndef WEBBROWSERSUGGESTIONSENGINE_H
#define WEBBROWSERSUGGESTIONSENGINE_H
#include <qpair.h>
#include <qimage.h>
#include <qmap.h>
//
// webbrowsersuggestionsengine.h
// interface/src/webbrowser
//
// Created by Vlad Stelmahovsky Kapolka on 30/10/17.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <qnetworkaccessmanager.h>
#include <qstring.h>
#include <qurl.h>
class QNetworkReply;
class WebBrowserSuggestionsEngine : public QObject
{
Q_OBJECT
public:
WebBrowserSuggestionsEngine(QObject* parent = 0);
virtual ~WebBrowserSuggestionsEngine();
public slots:
void querySuggestions(const QString& searchString);
signals:
void suggestions(const QStringList& suggestions);
private slots:
void suggestionsFinished(QNetworkReply *reply);
private:
QNetworkReply* _suggestionsReply;
QNetworkAccessManager* _currentNAM;
};
#endif // WEBBROWSERSUGGESTIONSENGINE_H