diff --git a/src/lib/navigation/completer/locationcompleter.cpp b/src/lib/navigation/completer/locationcompleter.cpp index 5ae9176c6..ea5ded732 100644 --- a/src/lib/navigation/completer/locationcompleter.cpp +++ b/src/lib/navigation/completer/locationcompleter.cpp @@ -28,6 +28,8 @@ #include "bookmarks.h" #include "bookmarkitem.h" #include "qzsettings.h" +#include "opensearchengine.h" +#include "networkmanager.h" #include @@ -77,6 +79,18 @@ void LocationCompleter::complete(const QString &string) LocationCompleterRefreshJob* job = new LocationCompleterRefreshJob(trimmedStr); connect(job, SIGNAL(finished()), this, SLOT(refreshJobFinished())); connect(this, SIGNAL(cancelRefreshJob()), job, SLOT(jobCancelled())); + + if (qzSettings->searchFromAddressBar && trimmedStr.length() > 2) { + if (!m_openSearchEngine) { + m_openSearchEngine = new OpenSearchEngine(this); + m_openSearchEngine->setNetworkAccessManager(mApp->networkManager()); + connect(m_openSearchEngine, &OpenSearchEngine::suggestions, this, &LocationCompleter::addSuggestions); + } + m_openSearchEngine->setSuggestionsUrl(LocationBar::searchEngine().suggestionsUrl); + m_openSearchEngine->setSuggestionsParameters(LocationBar::searchEngine().suggestionsParameters); + m_suggestionsTerm = trimmedStr; + m_openSearchEngine->requestSuggestions(m_suggestionsTerm); + } } void LocationCompleter::showMostVisited() @@ -96,6 +110,7 @@ void LocationCompleter::refreshJobFinished() m_lastRefreshTimestamp = job->timestamp(); showPopup(); + addSuggestions(m_oldSuggestions); if (!s_view->currentIndex().isValid() && s_model->index(0, 0).data(LocationCompleterModel::VisitSearchItemRole).toBool()) { m_ignoreCurrentChanged = true; @@ -113,6 +128,8 @@ void LocationCompleter::refreshJobFinished() void LocationCompleter::slotPopupClosed() { + m_oldSuggestions.clear(); + disconnect(s_view, SIGNAL(closed()), this, SLOT(slotPopupClosed())); disconnect(s_view, SIGNAL(indexActivated(QModelIndex)), this, SLOT(indexActivated(QModelIndex))); disconnect(s_view, SIGNAL(indexCtrlActivated(QModelIndex)), this, SLOT(indexCtrlActivated(QModelIndex))); @@ -123,6 +140,33 @@ void LocationCompleter::slotPopupClosed() emit popupClosed(); } +void LocationCompleter::addSuggestions(const QStringList &suggestions) +{ + const auto suggestionItems = s_model->suggestionItems(); + + // Delete existing suggestions + for (QStandardItem *item : suggestionItems) { + s_model->takeRow(item->row()); + delete item; + } + + // Add new suggestions + QList items; + for (const QString &suggestion : suggestions) { + QStandardItem* item = new QStandardItem(); + item->setText(suggestion); + item->setData(suggestion, LocationCompleterModel::TitleRole); + item->setData(suggestion, LocationCompleterModel::UrlRole); + item->setData(m_suggestionsTerm, LocationCompleterModel::SearchStringRole); + item->setData(true, LocationCompleterModel::SearchSuggestionRole); + items.append(item); + } + + s_model->addCompletions(items); + adjustPopupSize(); + m_oldSuggestions = suggestions; +} + void LocationCompleter::currentChanged(const QModelIndex &index) { if (m_ignoreCurrentChanged) { diff --git a/src/lib/navigation/completer/locationcompleter.h b/src/lib/navigation/completer/locationcompleter.h index 31d6a5676..8e3542d5b 100644 --- a/src/lib/navigation/completer/locationcompleter.h +++ b/src/lib/navigation/completer/locationcompleter.h @@ -27,6 +27,7 @@ class QModelIndex; class LocationBar; class BrowserWindow; +class OpenSearchEngine; class LocationCompleterModel; class LocationCompleterView; @@ -56,9 +57,9 @@ signals: private slots: void refreshJobFinished(); void slotPopupClosed(); + void addSuggestions(const QStringList &suggestions); void currentChanged(const QModelIndex &index); - void indexActivated(const QModelIndex &index); void indexCtrlActivated(const QModelIndex &index); void indexShiftActivated(const QModelIndex &index); @@ -77,6 +78,9 @@ private: QString m_originalText; bool m_popupClosed; bool m_ignoreCurrentChanged = false; + OpenSearchEngine* m_openSearchEngine = nullptr; + QStringList m_oldSuggestions; + QString m_suggestionsTerm; static LocationCompleterView* s_view; static LocationCompleterModel* s_model; diff --git a/src/lib/navigation/completer/locationcompleterdelegate.cpp b/src/lib/navigation/completer/locationcompleterdelegate.cpp index 4701ecf6b..cff968bc5 100644 --- a/src/lib/navigation/completer/locationcompleterdelegate.cpp +++ b/src/lib/navigation/completer/locationcompleterdelegate.cpp @@ -93,6 +93,7 @@ void LocationCompleterDelegate::paint(QPainter* painter, const QStyleOptionViewI style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, w); const bool isVisitSearchItem = index.data(LocationCompleterModel::VisitSearchItemRole).toBool(); + const bool isSearchSuggestion = index.data(LocationCompleterModel::SearchSuggestionRole).toBool(); const bool isWebSearch = qzSettings->searchFromAddressBar && !isUrlOrDomain(m_originalText.trimmed()); // Draw icon @@ -100,7 +101,7 @@ void LocationCompleterDelegate::paint(QPainter* painter, const QStyleOptionViewI const int iconYPos = center - (iconSize / 2); QRect iconRect(leftPosition, iconYPos, iconSize, iconSize); QPixmap pixmap = index.data(Qt::DecorationRole).value().pixmap(iconSize); - if (isVisitSearchItem && isWebSearch) { + if (isSearchSuggestion || (isVisitSearchItem && isWebSearch)) { pixmap = QIcon::fromTheme(QSL("edit-find"), QIcon(QSL(":icons/menu/search-icon.svg"))).pixmap(iconSize); } painter->drawPixmap(iconRect, pixmap); @@ -166,11 +167,11 @@ void LocationCompleterDelegate::paint(QPainter* painter, const QStyleOptionViewI QRect textRect(linkRect); textRect.setX(textRect.x() + m_padding + 16 + m_padding); viewItemDrawText(painter, &opt, textRect, tr("Switch to tab"), textPalette.color(colorLinkRole)); - } else if (isVisitSearchItem) { - if (!isWebSearch) { + } else if (isVisitSearchItem || isSearchSuggestion) { + if (!isSearchSuggestion && !isWebSearch) { link = tr("Visit"); } else { - link = tr("Search on %1").arg(LocationBar::searchEngineName()); + link = tr("Search on %1").arg(LocationBar::searchEngine().name); } viewItemDrawText(painter, &opt, linkRect, link, textPalette.color(colorLinkRole)); } else { diff --git a/src/lib/navigation/completer/locationcompletermodel.cpp b/src/lib/navigation/completer/locationcompletermodel.cpp index 583079dea..082281ae3 100644 --- a/src/lib/navigation/completer/locationcompletermodel.cpp +++ b/src/lib/navigation/completer/locationcompletermodel.cpp @@ -1,6 +1,6 @@ /* ============================================================ -* QupZilla - WebKit based browser -* Copyright (C) 2010-2014 David Rosca +* QupZilla - Qt web browser +* Copyright (C) 2010-2017 David Rosca * * 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 @@ -33,17 +33,32 @@ LocationCompleterModel::LocationCompleterModel(QObject* parent) void LocationCompleterModel::setCompletions(const QList &items) { - foreach (QStandardItem* item, items) { + clear(); + addCompletions(items); +} + +void LocationCompleterModel::addCompletions(const QList &items) +{ + for (QStandardItem *item : items) { item->setIcon(QPixmap::fromImage(item->data(ImageRole).value())); setTabPosition(item); - if (item->icon().isNull()) { item->setIcon(IconProvider::emptyWebIcon()); } + appendRow({item}); } +} - clear(); - appendColumn(items); +QList LocationCompleterModel::suggestionItems() const +{ + QList items; + for (int i = 0; i < rowCount(); ++i) { + QStandardItem *it = item(i); + if (it->data(SearchSuggestionRole).toBool()) { + items.append(it); + } + } + return items; } QSqlQuery LocationCompleterModel::createDomainQuery(const QString &text) diff --git a/src/lib/navigation/completer/locationcompletermodel.h b/src/lib/navigation/completer/locationcompletermodel.h index cc8526010..139c4b16e 100644 --- a/src/lib/navigation/completer/locationcompletermodel.h +++ b/src/lib/navigation/completer/locationcompletermodel.h @@ -39,12 +39,16 @@ public: TabPositionWindowRole, TabPositionTabRole, ImageRole, - VisitSearchItemRole + VisitSearchItemRole, + SearchSuggestionRole }; explicit LocationCompleterModel(QObject* parent = 0); void setCompletions(const QList &items); + void addCompletions(const QList &items); + + QList suggestionItems() const; static QSqlQuery createHistoryQuery(const QString &searchString, int limit, bool exactMatch = false); static QSqlQuery createDomainQuery(const QString &text); diff --git a/src/lib/navigation/locationbar.cpp b/src/lib/navigation/locationbar.cpp index c24f33fe8..0ec924c23 100644 --- a/src/lib/navigation/locationbar.cpp +++ b/src/lib/navigation/locationbar.cpp @@ -33,7 +33,6 @@ #include "qzsettings.h" #include "colors.h" #include "autofillicon.h" -#include "searchenginesmanager.h" #include "completer/locationcompleter.h" #include @@ -146,7 +145,7 @@ void LocationBar::setText(const QString &text) void LocationBar::updatePlaceHolderText() { if (qzSettings->searchFromAddressBar) { - setPlaceholderText(tr("Enter URL address or search on %1").arg(searchEngineName())); + setPlaceholderText(tr("Enter URL address or search on %1").arg(searchEngine().name)); } else setPlaceholderText(tr("Enter URL address")); } @@ -239,14 +238,14 @@ QString LocationBar::convertUrlToText(const QUrl &url) return stringUrl; } -QString LocationBar::searchEngineName() +SearchEnginesManager::Engine LocationBar::searchEngine() { if (!qzSettings->searchFromAddressBar) { - return QString(); + return SearchEnginesManager::Engine(); } else if (qzSettings->searchWithDefaultEngine) { - return mApp->searchEnginesManager()->defaultEngine().name; + return mApp->searchEnginesManager()->defaultEngine(); } else { - return mApp->searchEnginesManager()->activeEngine().name; + return mApp->searchEnginesManager()->activeEngine(); } } diff --git a/src/lib/navigation/locationbar.h b/src/lib/navigation/locationbar.h index 7f7399a68..0260bce85 100644 --- a/src/lib/navigation/locationbar.h +++ b/src/lib/navigation/locationbar.h @@ -20,6 +20,7 @@ #include "qzcommon.h" #include "lineedit.h" +#include "searchenginesmanager.h" class QStringListModel; @@ -44,7 +45,7 @@ public: void setWebView(TabbedWebView* view); static QString convertUrlToText(const QUrl &url); - static QString searchEngineName(); + static SearchEnginesManager::Engine searchEngine(); public slots: void setText(const QString &text);