mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
Ladybird: Add autocomplete to LocationEdit
This commit is contained in:
parent
8fcf42f684
commit
d68433653a
Notes:
sideshowbarker
2024-07-16 23:52:22 +09:00
Author: https://github.com/cammo1123 Commit: https://github.com/SerenityOS/serenity/commit/d68433653a Pull-request: https://github.com/SerenityOS/serenity/pull/19064 Reviewed-by: https://github.com/AtkinsSJ
9 changed files with 453 additions and 8 deletions
|
@ -106,6 +106,7 @@ set(LADYBIRD_HEADERS
|
|||
if (ENABLE_QT)
|
||||
qt_add_executable(ladybird ${SOURCES})
|
||||
target_sources(ladybird PRIVATE
|
||||
Qt/AutoComplete.cpp
|
||||
Qt/BrowserWindow.cpp
|
||||
Qt/ConsoleWidget.cpp
|
||||
Qt/EventLoopImplementationQt.cpp
|
||||
|
@ -136,7 +137,7 @@ target_sources(ladybird PUBLIC FILE_SET ladybird TYPE HEADERS
|
|||
BASE_DIRS ${SERENITY_SOURCE_DIR}
|
||||
FILES ${LADYBIRD_HEADERS}
|
||||
)
|
||||
target_link_libraries(ladybird PRIVATE LibCore LibFileSystem LibGfx LibGUI LibIPC LibJS LibMain LibWeb LibWebView LibSQL LibProtocol)
|
||||
target_link_libraries(ladybird PRIVATE LibCore LibFileSystem LibGfx LibGUI LibIPC LibJS LibMain LibPublicSuffix LibWeb LibWebView LibSQL LibProtocol)
|
||||
|
||||
target_include_directories(ladybird PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_include_directories(ladybird PRIVATE ${SERENITY_SOURCE_DIR}/Userland/)
|
||||
|
|
156
Ladybird/Qt/AutoComplete.cpp
Normal file
156
Ladybird/Qt/AutoComplete.cpp
Normal file
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "AutoComplete.h"
|
||||
#include "Settings.h"
|
||||
#include <AK/JsonArray.h>
|
||||
#include <AK/JsonObject.h>
|
||||
#include <AK/JsonParser.h>
|
||||
#include <AK/URL.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<void> AutoComplete::parse_google_autocomplete(Vector<JsonValue> const& json)
|
||||
{
|
||||
if (json.size() != 5)
|
||||
return Error::from_string_view("Invalid JSON, expected 5 elements in array"sv);
|
||||
|
||||
if (!json[0].is_string())
|
||||
return Error::from_string_view("Invalid JSON, expected first element to be a string"sv);
|
||||
auto query = TRY(String::from_deprecated_string(json[0].as_string()));
|
||||
|
||||
if (!json[1].is_array())
|
||||
return Error::from_string_view("Invalid JSON, expected second element to be an array"sv);
|
||||
auto suggestions_array = json[1].as_array().values();
|
||||
|
||||
if (query != m_query)
|
||||
return Error::from_string_view("Invalid JSON, query does not match"sv);
|
||||
|
||||
for (auto& suggestion : suggestions_array) {
|
||||
m_auto_complete_model->add(TRY(String::from_deprecated_string(suggestion.as_string())));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> AutoComplete::parse_duckduckgo_autocomplete(Vector<JsonValue> const& json)
|
||||
{
|
||||
for (auto const& suggestion : json) {
|
||||
auto maybe_value = suggestion.as_object().get("phrase"sv);
|
||||
if (!maybe_value.has_value())
|
||||
continue;
|
||||
m_auto_complete_model->add(TRY(String::from_deprecated_string(maybe_value->as_string())));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> AutoComplete::parse_yahoo_autocomplete(JsonObject const& json)
|
||||
{
|
||||
if (!json.get("q"sv).has_value() || !json.get("q"sv)->is_string())
|
||||
return Error::from_string_view("Invalid JSON, expected \"q\" to be a string"sv);
|
||||
auto query = TRY(String::from_deprecated_string(json.get("q"sv)->as_string()));
|
||||
|
||||
if (!json.get("r"sv).has_value() || !json.get("r"sv)->is_array())
|
||||
return Error::from_string_view("Invalid JSON, expected \"r\" to be an object"sv);
|
||||
auto suggestions_object = json.get("r"sv)->as_array().values();
|
||||
|
||||
if (query != m_query)
|
||||
return Error::from_string_view("Invalid JSON, query does not match"sv);
|
||||
|
||||
for (auto& suggestion_object : suggestions_object) {
|
||||
if (!suggestion_object.is_object())
|
||||
return Error::from_string_view("Invalid JSON, expected value to be an object"sv);
|
||||
auto suggestion = suggestion_object.as_object();
|
||||
|
||||
if (!suggestion.get("k"sv).has_value() || !suggestion.get("k"sv)->is_string())
|
||||
return Error::from_string_view("Invalid JSON, expected \"k\" to be a string"sv);
|
||||
|
||||
m_auto_complete_model->add(TRY(String::from_deprecated_string(suggestion.get("k"sv)->as_string())));
|
||||
};
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> AutoComplete::got_network_response(QNetworkReply* reply)
|
||||
{
|
||||
if (reply->error() == QNetworkReply::NetworkError::OperationCanceledError)
|
||||
return {};
|
||||
|
||||
AK::JsonParser parser(ak_deprecated_string_from_qstring(reply->readAll()));
|
||||
auto json = TRY(parser.parse());
|
||||
|
||||
auto engine_name = Settings::the()->autocomplete_engine().name;
|
||||
if (engine_name == "Google")
|
||||
return parse_google_autocomplete(json.as_array().values());
|
||||
|
||||
if (engine_name == "DuckDuckGo")
|
||||
return parse_duckduckgo_autocomplete(json.as_array().values());
|
||||
|
||||
if (engine_name == "Yahoo")
|
||||
return parse_yahoo_autocomplete(json.as_object());
|
||||
|
||||
return Error::from_string_view("Invalid engine name"sv);
|
||||
}
|
||||
|
||||
ErrorOr<String> AutoComplete::search_url_from_query(StringView query)
|
||||
{
|
||||
auto search_engine = TRY(ak_string_from_qstring(Settings::the()->search_engine().url));
|
||||
return search_engine.replace("{}"sv, AK::URL::percent_encode(query), ReplaceMode::FirstOnly);
|
||||
}
|
||||
|
||||
ErrorOr<String> AutoComplete::auto_complete_url_from_query(StringView query)
|
||||
{
|
||||
auto autocomplete_engine = TRY(ak_string_from_qstring(Settings::the()->autocomplete_engine().url));
|
||||
return autocomplete_engine.replace("{}"sv, AK::URL::percent_encode(query), ReplaceMode::FirstOnly);
|
||||
}
|
||||
|
||||
void AutoComplete::clear_suggestions()
|
||||
{
|
||||
m_auto_complete_model->clear();
|
||||
}
|
||||
|
||||
ErrorOr<void> AutoComplete::get_search_suggestions(StringView search_string)
|
||||
{
|
||||
m_query = TRY(String::from_utf8(search_string));
|
||||
if (m_reply)
|
||||
m_reply->abort();
|
||||
|
||||
m_auto_complete_model->clear();
|
||||
m_auto_complete_model->add(m_query);
|
||||
|
||||
QNetworkRequest request { QUrl(qstring_from_ak_string(TRY(auto_complete_url_from_query(m_query)))) };
|
||||
m_reply = m_manager->get(request);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
85
Ladybird/Qt/AutoComplete.h
Normal file
85
Ladybird/Qt/AutoComplete.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StringUtils.h"
|
||||
#include <AK/Forward.h>
|
||||
#include <AK/String.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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
ErrorOr<void> get_search_suggestions(StringView);
|
||||
void clear_suggestions();
|
||||
static ErrorOr<String> search_url_from_query(StringView query);
|
||||
static ErrorOr<String> auto_complete_url_from_query(StringView query);
|
||||
|
||||
signals:
|
||||
void activated(QModelIndex const&);
|
||||
|
||||
private:
|
||||
ErrorOr<void> got_network_response(QNetworkReply* reply);
|
||||
|
||||
ErrorOr<void> parse_google_autocomplete(Vector<JsonValue> const&);
|
||||
ErrorOr<void> parse_duckduckgo_autocomplete(Vector<JsonValue> const&);
|
||||
ErrorOr<void> parse_yahoo_autocomplete(JsonObject const&);
|
||||
|
||||
QNetworkAccessManager* m_manager;
|
||||
AutoCompleteModel* m_auto_complete_model;
|
||||
QTreeView* m_tree_view;
|
||||
QNetworkReply* m_reply { nullptr };
|
||||
|
||||
String m_query;
|
||||
};
|
||||
|
||||
}
|
|
@ -5,9 +5,11 @@
|
|||
*/
|
||||
|
||||
#include "LocationEdit.h"
|
||||
#include "Settings.h"
|
||||
#include "StringUtils.h"
|
||||
#include <AK/URL.h>
|
||||
#include <QCoreApplication>
|
||||
#include <LibPublicSuffix/URL.h>
|
||||
#include <QApplication>
|
||||
#include <QPalette>
|
||||
#include <QTextLayout>
|
||||
#include <QTimer>
|
||||
|
@ -17,8 +19,50 @@ namespace Ladybird {
|
|||
LocationEdit::LocationEdit(QWidget* parent)
|
||||
: QLineEdit(parent)
|
||||
{
|
||||
setPlaceholderText("Enter web address");
|
||||
connect(this, &QLineEdit::editingFinished, this, &LocationEdit::clearFocus);
|
||||
setPlaceholderText("Search or enter web address");
|
||||
m_autocomplete = make<AutoComplete>(this);
|
||||
this->setCompleter(m_autocomplete);
|
||||
|
||||
connect(m_autocomplete, &AutoComplete::activated, [&](QModelIndex const&) {
|
||||
emit returnPressed();
|
||||
});
|
||||
|
||||
connect(this, &QLineEdit::returnPressed, [&] {
|
||||
clearFocus();
|
||||
if (!Settings::the()->enable_search())
|
||||
return;
|
||||
|
||||
auto query = ak_deprecated_string_from_qstring(text());
|
||||
if (auto result = PublicSuffix::absolute_url(query); !result.is_error())
|
||||
return;
|
||||
|
||||
auto search_url_or_error = AutoComplete::search_url_from_query(query);
|
||||
if (search_url_or_error.is_error()) {
|
||||
dbgln("LocationEdit::returnPressed: search_url_from_query failed: {}", search_url_or_error.error());
|
||||
return;
|
||||
}
|
||||
auto search_url = search_url_or_error.release_value();
|
||||
|
||||
setText(qstring_from_ak_string(search_url));
|
||||
});
|
||||
|
||||
connect(this, &QLineEdit::textEdited, [this] {
|
||||
if (!Settings::the()->enable_autocomplete()) {
|
||||
m_autocomplete->clear_suggestions();
|
||||
return;
|
||||
}
|
||||
|
||||
auto cursor_position = cursorPosition();
|
||||
|
||||
auto result = m_autocomplete->get_search_suggestions(ak_deprecated_string_from_qstring(text()));
|
||||
if (result.is_error()) {
|
||||
dbgln("LocationEdit::textEdited: get_search_suggestions failed: {}", result.error());
|
||||
return;
|
||||
}
|
||||
|
||||
setCursorPosition(cursor_position);
|
||||
});
|
||||
|
||||
connect(this, &QLineEdit::textChanged, this, &LocationEdit::highlight_location);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "AutoComplete.h"
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <QLineEdit>
|
||||
|
||||
namespace Ladybird {
|
||||
|
@ -20,6 +22,7 @@ private:
|
|||
virtual void focusOutEvent(QFocusEvent* event) override;
|
||||
|
||||
void highlight_location();
|
||||
AK::OwnPtr<AutoComplete> m_autocomplete;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Filiph Sandström <filiph.sandstrom@filfatstudios.com>
|
||||
* Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -71,9 +72,57 @@ QString Settings::new_tab_page()
|
|||
return m_qsettings->value("new_tab_page", default_new_tab_url).toString();
|
||||
}
|
||||
|
||||
Settings::EngineProvider Settings::search_engine()
|
||||
{
|
||||
EngineProvider engine_provider;
|
||||
engine_provider.name = m_qsettings->value("search_engine_name", "Google").toString();
|
||||
engine_provider.url = m_qsettings->value("search_engine", "https://www.google.com/search?q={}").toString();
|
||||
return engine_provider;
|
||||
}
|
||||
|
||||
void Settings::set_search_engine(EngineProvider const& engine_provider)
|
||||
{
|
||||
m_qsettings->setValue("search_engine_name", engine_provider.name);
|
||||
m_qsettings->setValue("search_engine", engine_provider.url);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void Settings::set_new_tab_page(QString const& page)
|
||||
{
|
||||
m_qsettings->setValue("new_tab_page", page);
|
||||
}
|
||||
|
||||
bool Settings::enable_autocomplete()
|
||||
{
|
||||
return m_qsettings->value("enable_autocomplete", true).toBool();
|
||||
}
|
||||
|
||||
void Settings::set_enable_autocomplete(bool enable)
|
||||
{
|
||||
m_qsettings->setValue("enable_autocomplete", enable);
|
||||
}
|
||||
|
||||
bool Settings::enable_search()
|
||||
{
|
||||
return m_qsettings->value("enable_search", true).toBool();
|
||||
}
|
||||
|
||||
void Settings::set_enable_search(bool enable)
|
||||
{
|
||||
m_qsettings->setValue("enable_search", enable);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Filiph Sandström <filiph.sandstrom@filfatstudios.com>
|
||||
* Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -37,6 +38,23 @@ public:
|
|||
QString new_tab_page();
|
||||
void set_new_tab_page(QString const& page);
|
||||
|
||||
struct EngineProvider {
|
||||
QString name;
|
||||
QString url;
|
||||
};
|
||||
|
||||
EngineProvider search_engine();
|
||||
void set_search_engine(EngineProvider const& engine);
|
||||
|
||||
EngineProvider autocomplete_engine();
|
||||
void set_autocomplete_engine(EngineProvider const& engine);
|
||||
|
||||
bool enable_autocomplete();
|
||||
void set_enable_autocomplete(bool enable);
|
||||
|
||||
bool enable_search();
|
||||
void set_enable_search(bool enable);
|
||||
|
||||
protected:
|
||||
Settings();
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Filiph Sandström <filiph.sandstrom@filfatstudios.com>
|
||||
* Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -10,6 +11,7 @@
|
|||
#include <AK/URL.h>
|
||||
#include <QCloseEvent>
|
||||
#include <QLabel>
|
||||
#include <QMenu>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
|
@ -17,11 +19,31 @@ SettingsDialog::SettingsDialog(QMainWindow* window)
|
|||
: m_window(window)
|
||||
{
|
||||
m_layout = new QFormLayout(this);
|
||||
m_new_tab_page = new QLineEdit(this);
|
||||
m_ok_button = new QPushButton("&Save", this);
|
||||
|
||||
m_enable_search = make<QCheckBox>(this);
|
||||
m_enable_search->setChecked(Settings::the()->enable_search());
|
||||
|
||||
m_search_engine_dropdown = make<QToolButton>(this);
|
||||
m_search_engine_dropdown->setText(Settings::the()->search_engine().name);
|
||||
|
||||
m_enable_autocomplete = make<QCheckBox>(this);
|
||||
m_enable_autocomplete->setChecked(Settings::the()->enable_autocomplete());
|
||||
|
||||
m_autocomplete_engine_dropdown = make<QToolButton>(this);
|
||||
m_autocomplete_engine_dropdown->setText(Settings::the()->autocomplete_engine().name);
|
||||
|
||||
m_new_tab_page = make<QLineEdit>(this);
|
||||
m_new_tab_page->setText(Settings::the()->new_tab_page());
|
||||
|
||||
setup_search_engines();
|
||||
|
||||
m_layout->addRow(new QLabel("Page on New Tab", this), m_new_tab_page);
|
||||
m_layout->addWidget(m_ok_button);
|
||||
m_layout->addRow(new QLabel("Enable Search", this), m_enable_search);
|
||||
m_layout->addRow(new QLabel("Search Engine", this), m_search_engine_dropdown);
|
||||
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(m_ok_button);
|
||||
|
||||
QObject::connect(m_ok_button, &QPushButton::released, this, [this] {
|
||||
close();
|
||||
|
@ -29,12 +51,69 @@ SettingsDialog::SettingsDialog(QMainWindow* window)
|
|||
|
||||
setWindowTitle("Settings");
|
||||
setFixedWidth(300);
|
||||
setFixedHeight(150);
|
||||
setFixedHeight(170);
|
||||
setLayout(m_layout);
|
||||
show();
|
||||
setFocus();
|
||||
}
|
||||
|
||||
void SettingsDialog::setup_search_engines()
|
||||
{
|
||||
// FIXME: These should be in a config file.
|
||||
Vector<Settings::EngineProvider> search_engines = {
|
||||
{ "Bing", "https://www.bing.com/search?q={}" },
|
||||
{ "Brave", "https://search.brave.com/search?q={}" },
|
||||
{ "DuckDuckGo", "https://duckduckgo.com/?q={}" },
|
||||
{ "GitHub", "https://github.com/search?q={}" },
|
||||
{ "Google", "https://google.com/search?q={}" },
|
||||
{ "Mojeek", "https://www.mojeek.com/search?q={}" },
|
||||
{ "Yahoo", "https://search.yahoo.com/search?p={}" },
|
||||
{ "Yandex", "https://yandex.com/search/?text={}" },
|
||||
};
|
||||
|
||||
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* search_engine_menu = new QMenu(this);
|
||||
for (auto& search_engine : search_engines) {
|
||||
QAction* action = new QAction(search_engine.name, this);
|
||||
connect(action, &QAction::triggered, this, [&, search_engine] {
|
||||
Settings::the()->set_search_engine(search_engine);
|
||||
m_search_engine_dropdown->setText(search_engine.name);
|
||||
});
|
||||
search_engine_menu->addAction(action);
|
||||
}
|
||||
m_search_engine_dropdown->setMenu(search_engine_menu);
|
||||
m_search_engine_dropdown->setPopupMode(QToolButton::InstantPopup);
|
||||
m_search_engine_dropdown->setEnabled(Settings::the()->enable_search());
|
||||
|
||||
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->setPopupMode(QToolButton::InstantPopup);
|
||||
m_autocomplete_engine_dropdown->setEnabled(Settings::the()->enable_autocomplete());
|
||||
|
||||
connect(m_enable_search, &QCheckBox::stateChanged, this, [&](int state) {
|
||||
Settings::the()->set_enable_search(state == Qt::Checked);
|
||||
m_search_engine_dropdown->setEnabled(state == Qt::Checked);
|
||||
});
|
||||
|
||||
connect(m_enable_autocomplete, &QCheckBox::stateChanged, this, [&](int state) {
|
||||
Settings::the()->set_enable_autocomplete(state == Qt::Checked);
|
||||
m_autocomplete_engine_dropdown->setEnabled(state == Qt::Checked);
|
||||
});
|
||||
}
|
||||
|
||||
void SettingsDialog::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
save();
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Filiph Sandström <filiph.sandstrom@filfatstudios.com>
|
||||
* Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <QCheckBox>
|
||||
#include <QDialog>
|
||||
#include <QFormLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QMainWindow>
|
||||
#include <QPushButton>
|
||||
#include <QToolButton>
|
||||
|
||||
#pragma once
|
||||
|
||||
|
@ -24,10 +28,16 @@ public:
|
|||
virtual void closeEvent(QCloseEvent*) override;
|
||||
|
||||
private:
|
||||
void setup_search_engines();
|
||||
|
||||
QFormLayout* m_layout;
|
||||
QPushButton* m_ok_button { nullptr };
|
||||
QLineEdit* m_new_tab_page { nullptr };
|
||||
QMainWindow* m_window { nullptr };
|
||||
OwnPtr<QLineEdit> m_new_tab_page;
|
||||
OwnPtr<QCheckBox> m_enable_search;
|
||||
OwnPtr<QToolButton> m_search_engine_dropdown;
|
||||
OwnPtr<QCheckBox> m_enable_autocomplete;
|
||||
OwnPtr<QToolButton> m_autocomplete_engine_dropdown;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue