mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-22 12:35:14 +00:00
UI/Qt: Migrate to LibWebView's autocomplete engine
As a result, we now no longer depend on Qt::Network.
This commit is contained in:
parent
24ae3cf4e7
commit
398f615300
13 changed files with 100 additions and 371 deletions
|
@ -79,7 +79,7 @@ if (ENABLE_QT AND ENABLE_GUI_TARGETS)
|
|||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Widgets Network)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Widgets)
|
||||
endif()
|
||||
|
||||
# We need to find OpenSSL in order to link it explicitly with all targets.
|
||||
|
|
|
@ -39,7 +39,6 @@ link_qt("ladybird_qt_components") {
|
|||
"Core",
|
||||
"Gui",
|
||||
"Widgets",
|
||||
"Network",
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -1,172 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/JsonArray.h>
|
||||
#include <AK/JsonObject.h>
|
||||
#include <LibURL/URL.h>
|
||||
#include <UI/Qt/AutoComplete.h>
|
||||
#include <UI/Qt/Settings.h>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
AutoComplete::AutoComplete(QWidget* parent)
|
||||
: QCompleter(parent)
|
||||
{
|
||||
m_tree_view = new QTreeView(parent);
|
||||
m_manager = new QNetworkAccessManager(this);
|
||||
m_auto_complete_model = new AutoCompleteModel(this);
|
||||
|
||||
setCompletionMode(QCompleter::UnfilteredPopupCompletion);
|
||||
setModel(m_auto_complete_model);
|
||||
setPopup(m_tree_view);
|
||||
|
||||
m_tree_view->setRootIsDecorated(false);
|
||||
m_tree_view->setHeaderHidden(true);
|
||||
|
||||
connect(this, QOverload<QModelIndex const&>::of(&QCompleter::activated), this, [&](QModelIndex const& index) {
|
||||
emit activated(index);
|
||||
});
|
||||
|
||||
connect(m_manager, &QNetworkAccessManager::finished, this, [&](QNetworkReply* reply) {
|
||||
auto result = got_network_response(reply);
|
||||
if (result.is_error())
|
||||
dbgln("AutoComplete::got_network_response: Error {}", result.error());
|
||||
});
|
||||
}
|
||||
|
||||
ErrorOr<Vector<String>> AutoComplete::parse_google_autocomplete(JsonValue const& json)
|
||||
{
|
||||
if (!json.is_array())
|
||||
return Error::from_string_literal("Expected Google autocomplete response to be a JSON array");
|
||||
|
||||
auto const& values = json.as_array();
|
||||
|
||||
if (values.size() != 5)
|
||||
return Error::from_string_literal("Invalid Google autocomplete response, expected 5 elements in array");
|
||||
|
||||
if (!values[0].is_string())
|
||||
return Error::from_string_literal("Invalid Google autocomplete response, expected first element to be a string");
|
||||
|
||||
auto const& query = values[0].as_string();
|
||||
if (query != m_query)
|
||||
return Error::from_string_literal("Invalid Google autocomplete response, query does not match");
|
||||
|
||||
if (!values[1].is_array())
|
||||
return Error::from_string_literal("Invalid Google autocomplete response, expected second element to be an array");
|
||||
auto const& suggestions_array = values[1].as_array().values();
|
||||
|
||||
Vector<String> results;
|
||||
results.ensure_capacity(suggestions_array.size());
|
||||
for (auto const& suggestion : suggestions_array)
|
||||
results.unchecked_append(suggestion.as_string());
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
ErrorOr<Vector<String>> AutoComplete::parse_duckduckgo_autocomplete(JsonValue const& json)
|
||||
{
|
||||
if (!json.is_array())
|
||||
return Error::from_string_literal("Expected DuckDuckGo autocomplete response to be a JSON array");
|
||||
|
||||
Vector<String> results;
|
||||
results.ensure_capacity(json.as_array().size());
|
||||
|
||||
for (auto const& suggestion : json.as_array().values()) {
|
||||
if (!suggestion.is_object())
|
||||
return Error::from_string_literal("Invalid DuckDuckGo autocomplete response, expected value to be an object");
|
||||
|
||||
if (auto value = suggestion.as_object().get_string("phrase"sv); value.has_value())
|
||||
results.unchecked_append(*value);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
ErrorOr<Vector<String>> AutoComplete::parse_yahoo_autocomplete(JsonValue const& json)
|
||||
{
|
||||
if (!json.is_object())
|
||||
return Error::from_string_literal("Expected Yahoo autocomplete response to be a JSON array");
|
||||
|
||||
auto query = json.as_object().get_string("q"sv);
|
||||
if (!query.has_value())
|
||||
return Error::from_string_literal("Invalid Yahoo autocomplete response, expected \"q\" to be a string");
|
||||
if (query != m_query)
|
||||
return Error::from_string_literal("Invalid Yahoo autocomplete response, query does not match");
|
||||
|
||||
auto suggestions = json.as_object().get_array("r"sv);
|
||||
if (!suggestions.has_value())
|
||||
return Error::from_string_literal("Invalid Yahoo autocomplete response, expected \"r\" to be an object");
|
||||
|
||||
Vector<String> results;
|
||||
results.ensure_capacity(suggestions->size());
|
||||
|
||||
for (auto const& suggestion : suggestions->values()) {
|
||||
if (!suggestion.is_object())
|
||||
return Error::from_string_literal("Invalid Yahoo autocomplete response, expected value to be an object");
|
||||
|
||||
auto result = suggestion.as_object().get_string("k"sv);
|
||||
if (!result.has_value())
|
||||
return Error::from_string_literal("Invalid Yahoo autocomplete response, expected \"k\" to be a string");
|
||||
|
||||
results.unchecked_append(*result);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
ErrorOr<void> AutoComplete::got_network_response(QNetworkReply* reply)
|
||||
{
|
||||
if (reply->error() == QNetworkReply::NetworkError::OperationCanceledError)
|
||||
return {};
|
||||
|
||||
auto reply_data = ak_string_from_qstring(reply->readAll());
|
||||
auto json = TRY(JsonValue::from_string(reply_data));
|
||||
|
||||
auto const& engine_name = Settings::the()->autocomplete_engine().name;
|
||||
|
||||
Vector<String> results;
|
||||
if (engine_name == "Google")
|
||||
results = TRY(parse_google_autocomplete(json));
|
||||
else if (engine_name == "DuckDuckGo")
|
||||
results = TRY(parse_duckduckgo_autocomplete(json));
|
||||
else if (engine_name == "Yahoo")
|
||||
results = TRY(parse_yahoo_autocomplete(json));
|
||||
else
|
||||
return Error::from_string_literal("Invalid engine name");
|
||||
|
||||
constexpr size_t MAX_AUTOCOMPLETE_RESULTS = 6;
|
||||
if (results.is_empty()) {
|
||||
results.append(m_query);
|
||||
} else if (results.size() > MAX_AUTOCOMPLETE_RESULTS) {
|
||||
results.shrink(MAX_AUTOCOMPLETE_RESULTS);
|
||||
}
|
||||
|
||||
m_auto_complete_model->replace_suggestions(move(results));
|
||||
return {};
|
||||
}
|
||||
|
||||
String AutoComplete::auto_complete_url_from_query(StringView query)
|
||||
{
|
||||
auto autocomplete_engine = ak_string_from_qstring(Settings::the()->autocomplete_engine().url);
|
||||
return MUST(autocomplete_engine.replace("{}"sv, URL::percent_encode(query), ReplaceMode::FirstOnly));
|
||||
}
|
||||
|
||||
void AutoComplete::clear_suggestions()
|
||||
{
|
||||
m_auto_complete_model->clear();
|
||||
}
|
||||
|
||||
void AutoComplete::get_search_suggestions(String search_string)
|
||||
{
|
||||
m_query = move(search_string);
|
||||
if (m_reply)
|
||||
m_reply->abort();
|
||||
|
||||
QNetworkRequest request { QUrl(qstring_from_ak_string(auto_complete_url_from_query(m_query))) };
|
||||
m_reply = m_manager->get(request);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Forward.h>
|
||||
#include <AK/String.h>
|
||||
#include <UI/Qt/StringUtils.h>
|
||||
|
||||
#include <QCompleter>
|
||||
#include <QNetworkReply>
|
||||
#include <QTreeView>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
class AutoCompleteModel final : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AutoCompleteModel(QObject* parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int rowCount(QModelIndex const& parent = QModelIndex()) const override { return parent.isValid() ? 0 : m_suggestions.size(); }
|
||||
virtual QVariant data(QModelIndex const& index, int role = Qt::DisplayRole) const override
|
||||
{
|
||||
if (role == Qt::DisplayRole || role == Qt::EditRole)
|
||||
return qstring_from_ak_string(m_suggestions[index.row()]);
|
||||
return {};
|
||||
}
|
||||
|
||||
void add(String const& result)
|
||||
{
|
||||
beginInsertRows({}, m_suggestions.size(), m_suggestions.size());
|
||||
m_suggestions.append(result);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
beginResetModel();
|
||||
m_suggestions.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void replace_suggestions(Vector<String> suggestions)
|
||||
{
|
||||
beginInsertRows({}, m_suggestions.size(), m_suggestions.size());
|
||||
m_suggestions = suggestions;
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
private:
|
||||
AK::Vector<String> m_suggestions;
|
||||
};
|
||||
|
||||
class AutoComplete final : public QCompleter {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AutoComplete(QWidget* parent);
|
||||
|
||||
virtual QString pathFromIndex(QModelIndex const& index) const override
|
||||
{
|
||||
return index.data(Qt::DisplayRole).toString();
|
||||
}
|
||||
|
||||
void get_search_suggestions(String);
|
||||
void clear_suggestions();
|
||||
|
||||
signals:
|
||||
void activated(QModelIndex const&);
|
||||
|
||||
private:
|
||||
static String auto_complete_url_from_query(StringView query);
|
||||
|
||||
ErrorOr<void> got_network_response(QNetworkReply* reply);
|
||||
|
||||
ErrorOr<Vector<String>> parse_google_autocomplete(JsonValue const&);
|
||||
ErrorOr<Vector<String>> parse_duckduckgo_autocomplete(JsonValue const&);
|
||||
ErrorOr<Vector<String>> parse_yahoo_autocomplete(JsonValue const&);
|
||||
|
||||
QNetworkAccessManager* m_manager;
|
||||
AutoCompleteModel* m_auto_complete_model;
|
||||
QTreeView* m_tree_view;
|
||||
QNetworkReply* m_reply { nullptr };
|
||||
|
||||
String m_query;
|
||||
};
|
||||
|
||||
}
|
43
UI/Qt/Autocomplete.cpp
Normal file
43
UI/Qt/Autocomplete.cpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
|
||||
* Copyright (c) 2025, Tim Flynn <trflynn89@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWebView/Autocomplete.h>
|
||||
#include <UI/Qt/Autocomplete.h>
|
||||
#include <UI/Qt/StringUtils.h>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
Autocomplete::Autocomplete(QWidget* parent)
|
||||
: QCompleter(parent)
|
||||
, m_autocomplete(make<WebView::Autocomplete>())
|
||||
, m_model(new QStringListModel(this))
|
||||
, m_popup(new QListView(parent))
|
||||
{
|
||||
m_autocomplete->on_autocomplete_query_complete = [this](auto const& suggestions) {
|
||||
if (suggestions.is_empty()) {
|
||||
m_model->setStringList({});
|
||||
} else {
|
||||
QStringList list;
|
||||
for (auto const& suggestion : suggestions)
|
||||
list.append(qstring_from_ak_string(suggestion));
|
||||
|
||||
m_model->setStringList(list);
|
||||
complete();
|
||||
}
|
||||
};
|
||||
|
||||
setCompletionMode(QCompleter::UnfilteredPopupCompletion);
|
||||
setModel(m_model);
|
||||
setPopup(m_popup);
|
||||
}
|
||||
|
||||
void Autocomplete::query_autocomplete_engine(String search_string)
|
||||
{
|
||||
m_autocomplete->query_autocomplete_engine(move(search_string));
|
||||
}
|
||||
|
||||
}
|
35
UI/Qt/Autocomplete.h
Normal file
35
UI/Qt/Autocomplete.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
|
||||
* Copyright (c) 2025, Tim Flynn <trflynn89@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/NonnullOwnPtr.h>
|
||||
#include <AK/String.h>
|
||||
#include <LibWebView/Forward.h>
|
||||
|
||||
#include <QCompleter>
|
||||
#include <QListView>
|
||||
#include <QStringListModel>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
class Autocomplete final : public QCompleter {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Autocomplete(QWidget* parent);
|
||||
|
||||
void query_autocomplete_engine(String);
|
||||
|
||||
private:
|
||||
NonnullOwnPtr<WebView::Autocomplete> m_autocomplete;
|
||||
|
||||
QStringListModel* m_model { nullptr };
|
||||
QListView* m_popup { nullptr };
|
||||
};
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
qt_add_executable(ladybird ${LADYBIRD_SOURCES})
|
||||
target_sources(ladybird PRIVATE
|
||||
Application.cpp
|
||||
AutoComplete.cpp
|
||||
Autocomplete.cpp
|
||||
BrowserWindow.cpp
|
||||
FindInPageWidget.cpp
|
||||
Icon.cpp
|
||||
|
@ -16,5 +16,5 @@ target_sources(ladybird PRIVATE
|
|||
ladybird.qrc
|
||||
main.cpp
|
||||
)
|
||||
target_link_libraries(ladybird PRIVATE Qt::Core Qt::Gui Qt::Network Qt::Widgets)
|
||||
target_link_libraries(ladybird PRIVATE Qt::Core Qt::Gui Qt::Widgets)
|
||||
create_ladybird_bundle(ladybird)
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
#include <LibURL/URL.h>
|
||||
#include <LibWebView/Application.h>
|
||||
#include <LibWebView/URL.h>
|
||||
#include <UI/Qt/Autocomplete.h>
|
||||
#include <UI/Qt/LocationEdit.h>
|
||||
#include <UI/Qt/Settings.h>
|
||||
#include <UI/Qt/StringUtils.h>
|
||||
|
||||
#include <QApplication>
|
||||
|
@ -20,13 +20,13 @@ namespace Ladybird {
|
|||
|
||||
LocationEdit::LocationEdit(QWidget* parent)
|
||||
: QLineEdit(parent)
|
||||
, m_autocomplete(new Autocomplete(this))
|
||||
{
|
||||
update_placeholder();
|
||||
|
||||
m_autocomplete = make<AutoComplete>(this);
|
||||
this->setCompleter(m_autocomplete);
|
||||
setCompleter(m_autocomplete);
|
||||
|
||||
connect(m_autocomplete, &AutoComplete::activated, [&](QModelIndex const&) {
|
||||
connect(m_autocomplete, QOverload<QModelIndex const&>::of(&QCompleter::activated), [&](QModelIndex const&) {
|
||||
emit returnPressed();
|
||||
});
|
||||
|
||||
|
@ -50,15 +50,7 @@ LocationEdit::LocationEdit(QWidget* parent)
|
|||
});
|
||||
|
||||
connect(this, &QLineEdit::textEdited, [this] {
|
||||
if (!Settings::the()->enable_autocomplete()) {
|
||||
m_autocomplete->clear_suggestions();
|
||||
return;
|
||||
}
|
||||
|
||||
auto cursor_position = cursorPosition();
|
||||
|
||||
m_autocomplete->get_search_suggestions(ak_string_from_qstring(text()));
|
||||
setCursorPosition(cursor_position);
|
||||
m_autocomplete->query_autocomplete_engine(ak_string_from_qstring(text()));
|
||||
});
|
||||
|
||||
connect(this, &QLineEdit::textChanged, this, &LocationEdit::highlight_location);
|
||||
|
@ -68,12 +60,15 @@ void LocationEdit::focusInEvent(QFocusEvent* event)
|
|||
{
|
||||
QLineEdit::focusInEvent(event);
|
||||
highlight_location();
|
||||
QTimer::singleShot(0, this, &QLineEdit::selectAll);
|
||||
|
||||
if (event->reason() != Qt::PopupFocusReason)
|
||||
QTimer::singleShot(0, this, &QLineEdit::selectAll);
|
||||
}
|
||||
|
||||
void LocationEdit::focusOutEvent(QFocusEvent* event)
|
||||
{
|
||||
QLineEdit::focusOutEvent(event);
|
||||
|
||||
if (m_url_is_hidden) {
|
||||
m_url_is_hidden = false;
|
||||
if (text().isEmpty())
|
||||
|
@ -142,13 +137,14 @@ void LocationEdit::highlight_location()
|
|||
QCoreApplication::sendEvent(this, &event);
|
||||
}
|
||||
|
||||
void LocationEdit::set_url(URL::URL const& url)
|
||||
void LocationEdit::set_url(URL::URL url)
|
||||
{
|
||||
m_url = url;
|
||||
m_url = AK::move(url);
|
||||
|
||||
if (m_url_is_hidden) {
|
||||
clear();
|
||||
} else {
|
||||
setText(qstring_from_ak_string(url.serialize()));
|
||||
setText(qstring_from_ak_string(m_url.serialize()));
|
||||
setCursorPosition(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <LibWebView/Settings.h>
|
||||
#include <UI/Qt/AutoComplete.h>
|
||||
|
||||
#include <QLineEdit>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
class Autocomplete;
|
||||
|
||||
class LocationEdit final
|
||||
: public QLineEdit
|
||||
, public WebView::SettingsObserver {
|
||||
|
@ -22,8 +23,8 @@ class LocationEdit final
|
|||
public:
|
||||
explicit LocationEdit(QWidget*);
|
||||
|
||||
URL::URL url() const { return m_url; }
|
||||
void set_url(URL::URL const&);
|
||||
URL::URL const& url() const { return m_url; }
|
||||
void set_url(URL::URL);
|
||||
|
||||
bool url_is_hidden() const { return m_url_is_hidden; }
|
||||
void set_url_is_hidden(bool url_is_hidden) { m_url_is_hidden = url_is_hidden; }
|
||||
|
@ -36,7 +37,8 @@ private:
|
|||
|
||||
void update_placeholder();
|
||||
void highlight_location();
|
||||
AK::OwnPtr<AutoComplete> m_autocomplete;
|
||||
|
||||
Autocomplete* m_autocomplete { nullptr };
|
||||
|
||||
URL::URL m_url;
|
||||
bool m_url_is_hidden { false };
|
||||
|
|
|
@ -65,30 +65,6 @@ void Settings::set_preferred_languages(QStringList const& languages)
|
|||
emit preferred_languages_changed(languages);
|
||||
}
|
||||
|
||||
Settings::EngineProvider Settings::autocomplete_engine()
|
||||
{
|
||||
EngineProvider engine_provider;
|
||||
engine_provider.name = m_qsettings->value("autocomplete_engine_name", "Google").toString();
|
||||
engine_provider.url = m_qsettings->value("autocomplete_engine", "https://www.google.com/complete/search?client=chrome&q={}").toString();
|
||||
return engine_provider;
|
||||
}
|
||||
|
||||
void Settings::set_autocomplete_engine(EngineProvider const& engine_provider)
|
||||
{
|
||||
m_qsettings->setValue("autocomplete_engine_name", engine_provider.name);
|
||||
m_qsettings->setValue("autocomplete_engine", engine_provider.url);
|
||||
}
|
||||
|
||||
bool Settings::enable_autocomplete()
|
||||
{
|
||||
return m_qsettings->value("enable_autocomplete", false).toBool();
|
||||
}
|
||||
|
||||
void Settings::set_enable_autocomplete(bool enable)
|
||||
{
|
||||
m_qsettings->setValue("enable_autocomplete", enable);
|
||||
}
|
||||
|
||||
bool Settings::enable_do_not_track()
|
||||
{
|
||||
return m_qsettings->value("enable_do_not_track", false).toBool();
|
||||
|
|
|
@ -44,16 +44,6 @@ public:
|
|||
QStringList preferred_languages();
|
||||
void set_preferred_languages(QStringList const& languages);
|
||||
|
||||
struct EngineProvider {
|
||||
QString name;
|
||||
QString url;
|
||||
};
|
||||
EngineProvider autocomplete_engine();
|
||||
void set_autocomplete_engine(EngineProvider const& engine);
|
||||
|
||||
bool enable_autocomplete();
|
||||
void set_enable_autocomplete(bool enable);
|
||||
|
||||
bool enable_do_not_track();
|
||||
void set_enable_do_not_track(bool enable);
|
||||
|
||||
|
|
|
@ -32,13 +32,6 @@ SettingsDialog::SettingsDialog(QMainWindow* window)
|
|||
close();
|
||||
});
|
||||
|
||||
m_enable_autocomplete = new QCheckBox(this);
|
||||
m_enable_autocomplete->setChecked(Settings::the()->enable_autocomplete());
|
||||
|
||||
m_autocomplete_engine_dropdown = new QPushButton(this);
|
||||
m_autocomplete_engine_dropdown->setText(Settings::the()->autocomplete_engine().name);
|
||||
m_autocomplete_engine_dropdown->setMaximumWidth(200);
|
||||
|
||||
m_enable_do_not_track = new QCheckBox(this);
|
||||
m_enable_do_not_track->setChecked(Settings::the()->enable_do_not_track());
|
||||
#if (QT_VERSION > QT_VERSION_CHECK(6, 7, 0))
|
||||
|
@ -49,11 +42,7 @@ SettingsDialog::SettingsDialog(QMainWindow* window)
|
|||
Settings::the()->set_enable_do_not_track(state == Qt::Checked);
|
||||
});
|
||||
|
||||
setup_autocomplete_engine();
|
||||
|
||||
m_layout->addRow(new QLabel("Preferred Language(s)", this), m_preferred_languages);
|
||||
m_layout->addRow(new QLabel("Enable Autocomplete", this), m_enable_autocomplete);
|
||||
m_layout->addRow(new QLabel("Autocomplete Engine", this), m_autocomplete_engine_dropdown);
|
||||
m_layout->addRow(new QLabel("Send web sites a \"Do Not Track\" request", this), m_enable_do_not_track);
|
||||
|
||||
setWindowTitle("Settings");
|
||||
|
@ -61,35 +50,4 @@ SettingsDialog::SettingsDialog(QMainWindow* window)
|
|||
resize(600, 250);
|
||||
}
|
||||
|
||||
void SettingsDialog::setup_autocomplete_engine()
|
||||
{
|
||||
// FIXME: These should be centralized in LibWebView.
|
||||
Vector<Settings::EngineProvider> autocomplete_engines = {
|
||||
{ "DuckDuckGo", "https://duckduckgo.com/ac/?q={}" },
|
||||
{ "Google", "https://www.google.com/complete/search?client=chrome&q={}" },
|
||||
{ "Yahoo", "https://search.yahoo.com/sugg/gossip/gossip-us-ura/?output=sd1&command={}" },
|
||||
};
|
||||
|
||||
QMenu* autocomplete_engine_menu = new QMenu(this);
|
||||
for (auto& autocomplete_engine : autocomplete_engines) {
|
||||
QAction* action = new QAction(autocomplete_engine.name, this);
|
||||
connect(action, &QAction::triggered, this, [&, autocomplete_engine] {
|
||||
Settings::the()->set_autocomplete_engine(autocomplete_engine);
|
||||
m_autocomplete_engine_dropdown->setText(autocomplete_engine.name);
|
||||
});
|
||||
autocomplete_engine_menu->addAction(action);
|
||||
}
|
||||
m_autocomplete_engine_dropdown->setMenu(autocomplete_engine_menu);
|
||||
m_autocomplete_engine_dropdown->setEnabled(Settings::the()->enable_autocomplete());
|
||||
|
||||
#if (QT_VERSION > QT_VERSION_CHECK(6, 7, 0))
|
||||
connect(m_enable_autocomplete, &QCheckBox::checkStateChanged, this, [&](int state) {
|
||||
#else
|
||||
connect(m_enable_autocomplete, &QCheckBox::stateChanged, this, [&](int state) {
|
||||
#endif
|
||||
Settings::the()->set_enable_autocomplete(state == Qt::Checked);
|
||||
m_autocomplete_engine_dropdown->setEnabled(state == Qt::Checked);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,13 +23,9 @@ public:
|
|||
explicit SettingsDialog(QMainWindow* window);
|
||||
|
||||
private:
|
||||
void setup_autocomplete_engine();
|
||||
|
||||
QFormLayout* m_layout;
|
||||
QMainWindow* m_window { nullptr };
|
||||
QLineEdit* m_preferred_languages { nullptr };
|
||||
QCheckBox* m_enable_autocomplete { nullptr };
|
||||
QPushButton* m_autocomplete_engine_dropdown { nullptr };
|
||||
QCheckBox* m_enable_do_not_track { nullptr };
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue