BrowserSettingsWidget.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
  3. * Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include "BrowserSettingsWidget.h"
  8. #include <Applications/BrowserSettings/BrowserSettingsWidgetGML.h>
  9. #include <Applications/BrowserSettings/Defaults.h>
  10. #include <LibConfig/Client.h>
  11. #include <LibGUI/Label.h>
  12. #include <LibGUI/MessageBox.h>
  13. #include <LibGUI/Model.h>
  14. #include <LibWebView/SearchEngine.h>
  15. struct ColorScheme {
  16. ByteString title;
  17. ByteString setting_value;
  18. };
  19. class ColorSchemeModel final : public GUI::Model {
  20. public:
  21. ColorSchemeModel()
  22. {
  23. m_color_schemes.empend("Follow system theme", "auto");
  24. m_color_schemes.empend("Dark", "dark");
  25. m_color_schemes.empend("Light", "light");
  26. }
  27. virtual ~ColorSchemeModel() = default;
  28. virtual int row_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return 3; }
  29. virtual int column_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return 2; }
  30. virtual GUI::Variant data(GUI::ModelIndex const& index, GUI::ModelRole role) const override
  31. {
  32. if (role == GUI::ModelRole::TextAlignment)
  33. return Gfx::TextAlignment::CenterLeft;
  34. if (role == GUI::ModelRole::Display) {
  35. if (index.column() == 0)
  36. return m_color_schemes[index.row()].title;
  37. else
  38. return m_color_schemes[index.row()].setting_value;
  39. }
  40. return {};
  41. }
  42. private:
  43. Vector<ColorScheme> m_color_schemes;
  44. };
  45. class SearchEngineModel final : public GUI::Model {
  46. enum class SearchEngineColumn : int {
  47. Name,
  48. QueryURL,
  49. };
  50. public:
  51. SearchEngineModel()
  52. {
  53. m_search_engines.ensure_capacity(WebView::search_engines().size() + 1);
  54. for (auto const& engine : WebView::search_engines())
  55. m_search_engines.append(engine);
  56. m_search_engines.empend("Custom..."sv, StringView {});
  57. }
  58. virtual int row_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return m_search_engines.size(); }
  59. virtual int column_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return 2; }
  60. virtual GUI::Variant data(GUI::ModelIndex const& index, GUI::ModelRole role) const override
  61. {
  62. if (role == GUI::ModelRole::TextAlignment)
  63. return Gfx::TextAlignment::CenterLeft;
  64. if (role == GUI::ModelRole::Display) {
  65. switch (static_cast<SearchEngineColumn>(index.column())) {
  66. case SearchEngineColumn::Name:
  67. return m_search_engines[index.row()].name;
  68. case SearchEngineColumn::QueryURL:
  69. return m_search_engines[index.row()].query_url;
  70. }
  71. VERIFY_NOT_REACHED();
  72. }
  73. return {};
  74. }
  75. private:
  76. Vector<WebView::SearchEngine> m_search_engines;
  77. };
  78. ErrorOr<NonnullRefPtr<BrowserSettingsWidget>> BrowserSettingsWidget::create()
  79. {
  80. auto widget = TRY(try_make_ref_counted<BrowserSettingsWidget>());
  81. TRY(widget->load_from_gml(browser_settings_widget_gml));
  82. TRY(widget->setup());
  83. return widget;
  84. }
  85. ErrorOr<void> BrowserSettingsWidget::setup()
  86. {
  87. m_homepage_url_textbox = find_descendant_of_type_named<GUI::TextBox>("homepage_url_textbox");
  88. m_homepage_url_textbox->set_text(Config::read_string("Browser"sv, "Preferences"sv, "Home"sv, Browser::default_homepage_url), GUI::AllowCallback::No);
  89. m_homepage_url_textbox->on_change = [&]() { set_modified(true); };
  90. m_new_tab_url_textbox = find_descendant_of_type_named<GUI::TextBox>("new_tab_url_textbox");
  91. m_new_tab_url_textbox->set_text(Config::read_string("Browser"sv, "Preferences"sv, "NewTab"sv, Browser::default_new_tab_url), GUI::AllowCallback::No);
  92. m_new_tab_url_textbox->on_change = [&]() { set_modified(true); };
  93. m_color_scheme_combobox = find_descendant_of_type_named<GUI::ComboBox>("color_scheme_combobox");
  94. m_color_scheme_combobox->set_only_allow_values_from_model(true);
  95. m_color_scheme_combobox->set_model(adopt_ref(*new ColorSchemeModel()));
  96. m_color_scheme_combobox->set_selected_index(0, GUI::AllowCallback::No);
  97. set_color_scheme(Config::read_string("Browser"sv, "Preferences"sv, "ColorScheme"sv, Browser::default_color_scheme));
  98. m_color_scheme_combobox->on_change = [&](auto, auto) { set_modified(true); };
  99. m_show_bookmarks_bar_checkbox = find_descendant_of_type_named<GUI::CheckBox>("show_bookmarks_bar_checkbox");
  100. m_show_bookmarks_bar_checkbox->set_checked(Config::read_bool("Browser"sv, "Preferences"sv, "ShowBookmarksBar"sv, Browser::default_show_bookmarks_bar), GUI::AllowCallback::No);
  101. m_show_bookmarks_bar_checkbox->on_checked = [&](auto) { set_modified(true); };
  102. m_enable_search_engine_checkbox = find_descendant_of_type_named<GUI::CheckBox>("enable_search_engine_checkbox");
  103. m_search_engine_combobox_group = find_descendant_of_type_named<GUI::Widget>("search_engine_combobox_group");
  104. m_search_engine_combobox = find_descendant_of_type_named<GUI::ComboBox>("search_engine_combobox");
  105. m_custom_search_engine_group = find_descendant_of_type_named<GUI::Widget>("custom_search_engine_group");
  106. m_custom_search_engine_textbox = find_descendant_of_type_named<GUI::TextBox>("custom_search_engine_textbox");
  107. m_custom_search_engine_textbox->on_change = [&]() { set_modified(true); };
  108. m_enable_search_engine_checkbox->on_checked = [this](bool checked) {
  109. m_search_engine_combobox_group->set_enabled(checked);
  110. m_custom_search_engine_group->set_enabled(checked && m_is_custom_search_engine);
  111. set_modified(true);
  112. };
  113. m_search_engine_combobox->set_model(adopt_ref(*new SearchEngineModel()));
  114. m_search_engine_combobox->set_only_allow_values_from_model(true);
  115. m_search_engine_combobox->on_change = [this](AK::ByteString const&, GUI::ModelIndex const& cursor_index) {
  116. auto url_format = m_search_engine_combobox->model()->index(cursor_index.row(), 1).data().to_byte_string();
  117. m_is_custom_search_engine = url_format.is_empty();
  118. m_custom_search_engine_group->set_enabled(m_is_custom_search_engine);
  119. set_modified(true);
  120. };
  121. set_search_engine_url(Config::read_string("Browser"sv, "Preferences"sv, "SearchEngine"sv, WebView::default_search_engine().query_url));
  122. m_auto_close_download_windows_checkbox = find_descendant_of_type_named<GUI::CheckBox>("auto_close_download_windows_checkbox");
  123. m_auto_close_download_windows_checkbox->set_checked(Config::read_bool("Browser"sv, "Preferences"sv, "CloseDownloadWidgetOnFinish"sv, Browser::default_close_download_widget_on_finish), GUI::AllowCallback::No);
  124. m_auto_close_download_windows_checkbox->on_checked = [&](auto) { set_modified(true); };
  125. return {};
  126. }
  127. void BrowserSettingsWidget::set_color_scheme(StringView color_scheme)
  128. {
  129. bool found_color_scheme = false;
  130. for (int item_index = 0; item_index < m_color_scheme_combobox->model()->row_count(); ++item_index) {
  131. auto scheme = m_color_scheme_combobox->model()->index(item_index, 1).data().to_byte_string();
  132. if (scheme == color_scheme) {
  133. m_color_scheme_combobox->set_selected_index(item_index, GUI::AllowCallback::No);
  134. found_color_scheme = true;
  135. break;
  136. }
  137. }
  138. if (!found_color_scheme)
  139. m_color_scheme_combobox->set_selected_index(0, GUI::AllowCallback::No);
  140. }
  141. void BrowserSettingsWidget::set_search_engine_url(StringView url)
  142. {
  143. if (url.is_empty()) {
  144. m_enable_search_engine_checkbox->set_checked(false, GUI::AllowCallback::No);
  145. m_search_engine_combobox_group->set_enabled(false);
  146. m_custom_search_engine_group->set_enabled(false);
  147. m_search_engine_combobox->set_selected_index(0, GUI::AllowCallback::No);
  148. } else {
  149. m_enable_search_engine_checkbox->set_checked(true, GUI::AllowCallback::No);
  150. m_search_engine_combobox_group->set_enabled(true);
  151. bool found_url = false;
  152. for (int item_index = 0; item_index < m_search_engine_combobox->model()->row_count(); ++item_index) {
  153. auto url_format = m_search_engine_combobox->model()->index(item_index, 1).data().to_byte_string();
  154. if (url_format == url) {
  155. m_search_engine_combobox->set_selected_index(item_index, GUI::AllowCallback::No);
  156. found_url = true;
  157. break;
  158. }
  159. }
  160. if (!found_url) {
  161. m_is_custom_search_engine = true;
  162. m_custom_search_engine_textbox->set_text(url, GUI::AllowCallback::No);
  163. // We assume that "Custom" is the last item
  164. m_search_engine_combobox->set_selected_index(m_search_engine_combobox->model()->row_count() - 1, GUI::AllowCallback::No);
  165. m_custom_search_engine_group->set_enabled(true);
  166. } else {
  167. m_custom_search_engine_group->set_enabled(false);
  168. }
  169. }
  170. }
  171. void BrowserSettingsWidget::apply_settings()
  172. {
  173. auto homepage_url = m_homepage_url_textbox->text();
  174. if (!URL(homepage_url).is_valid()) {
  175. GUI::MessageBox::show_error(this->window(), "The homepage URL you have entered is not valid"sv);
  176. m_homepage_url_textbox->select_all();
  177. m_homepage_url_textbox->set_focus(true);
  178. return;
  179. }
  180. Config::write_string("Browser"sv, "Preferences"sv, "Home"sv, homepage_url);
  181. auto new_tab_url = m_new_tab_url_textbox->text();
  182. if (!URL(new_tab_url).is_valid()) {
  183. GUI::MessageBox::show_error(this->window(), "The new tab URL you have entered is not valid"sv);
  184. m_new_tab_url_textbox->select_all();
  185. m_new_tab_url_textbox->set_focus(true);
  186. return;
  187. }
  188. Config::write_string("Browser"sv, "Preferences"sv, "NewTab"sv, new_tab_url);
  189. Config::write_bool("Browser"sv, "Preferences"sv, "ShowBookmarksBar"sv, m_show_bookmarks_bar_checkbox->is_checked());
  190. auto color_scheme_index = m_color_scheme_combobox->selected_index();
  191. auto color_scheme = m_color_scheme_combobox->model()->index(color_scheme_index, 1).data().to_byte_string();
  192. Config::write_string("Browser"sv, "Preferences"sv, "ColorScheme"sv, color_scheme);
  193. if (!m_enable_search_engine_checkbox->is_checked()) {
  194. Config::write_string("Browser"sv, "Preferences"sv, "SearchEngine"sv, {});
  195. } else if (m_is_custom_search_engine) {
  196. Config::write_string("Browser"sv, "Preferences"sv, "SearchEngine"sv, m_custom_search_engine_textbox->text());
  197. } else {
  198. auto selected_index = m_search_engine_combobox->selected_index();
  199. auto url = m_search_engine_combobox->model()->index(selected_index, 1).data().to_byte_string();
  200. Config::write_string("Browser"sv, "Preferences"sv, "SearchEngine"sv, url);
  201. }
  202. Config::write_bool("Browser"sv, "Preferences"sv, "CloseDownloadWidgetOnFinish"sv, m_auto_close_download_windows_checkbox->is_checked());
  203. }
  204. void BrowserSettingsWidget::reset_default_values()
  205. {
  206. m_homepage_url_textbox->set_text(Browser::default_homepage_url);
  207. m_new_tab_url_textbox->set_text(Browser::default_new_tab_url);
  208. m_show_bookmarks_bar_checkbox->set_checked(Browser::default_show_bookmarks_bar);
  209. set_color_scheme(Browser::default_color_scheme);
  210. m_auto_close_download_windows_checkbox->set_checked(Browser::default_close_download_widget_on_finish);
  211. set_search_engine_url(WebView::default_search_engine().query_url);
  212. }