BrowserSettingsWidget.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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/Defaults.h>
  9. #include <LibConfig/Client.h>
  10. #include <LibGUI/Label.h>
  11. #include <LibGUI/MessageBox.h>
  12. #include <LibGUI/Model.h>
  13. #include <LibWebView/SearchEngine.h>
  14. namespace BrowserSettings {
  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<void> BrowserSettingsWidget::initialize()
  79. {
  80. m_homepage_url_textbox = find_descendant_of_type_named<GUI::TextBox>("homepage_url_textbox");
  81. m_homepage_url_textbox->set_text(Config::read_string("Browser"sv, "Preferences"sv, "Home"sv, Browser::default_homepage_url), GUI::AllowCallback::No);
  82. m_homepage_url_textbox->on_change = [&]() { set_modified(true); };
  83. m_new_tab_url_textbox = find_descendant_of_type_named<GUI::TextBox>("new_tab_url_textbox");
  84. m_new_tab_url_textbox->set_text(Config::read_string("Browser"sv, "Preferences"sv, "NewTab"sv, Browser::default_new_tab_url), GUI::AllowCallback::No);
  85. m_new_tab_url_textbox->on_change = [&]() { set_modified(true); };
  86. m_color_scheme_combobox = find_descendant_of_type_named<GUI::ComboBox>("color_scheme_combobox");
  87. m_color_scheme_combobox->set_only_allow_values_from_model(true);
  88. m_color_scheme_combobox->set_model(adopt_ref(*new ColorSchemeModel()));
  89. m_color_scheme_combobox->set_selected_index(0, GUI::AllowCallback::No);
  90. set_color_scheme(Config::read_string("Browser"sv, "Preferences"sv, "ColorScheme"sv, Browser::default_color_scheme));
  91. m_color_scheme_combobox->on_change = [&](auto, auto) { set_modified(true); };
  92. m_show_bookmarks_bar_checkbox = find_descendant_of_type_named<GUI::CheckBox>("show_bookmarks_bar_checkbox");
  93. m_show_bookmarks_bar_checkbox->set_checked(Config::read_bool("Browser"sv, "Preferences"sv, "ShowBookmarksBar"sv, Browser::default_show_bookmarks_bar), GUI::AllowCallback::No);
  94. m_show_bookmarks_bar_checkbox->on_checked = [&](auto) { set_modified(true); };
  95. m_enable_search_engine_checkbox = find_descendant_of_type_named<GUI::CheckBox>("enable_search_engine_checkbox");
  96. m_search_engine_combobox_group = find_descendant_of_type_named<GUI::Widget>("search_engine_combobox_group");
  97. m_search_engine_combobox = find_descendant_of_type_named<GUI::ComboBox>("search_engine_combobox");
  98. m_custom_search_engine_group = find_descendant_of_type_named<GUI::Widget>("custom_search_engine_group");
  99. m_custom_search_engine_textbox = find_descendant_of_type_named<GUI::TextBox>("custom_search_engine_textbox");
  100. m_custom_search_engine_textbox->on_change = [&]() { set_modified(true); };
  101. m_enable_search_engine_checkbox->on_checked = [this](bool checked) {
  102. m_search_engine_combobox_group->set_enabled(checked);
  103. m_custom_search_engine_group->set_enabled(checked && m_is_custom_search_engine);
  104. set_modified(true);
  105. };
  106. m_search_engine_combobox->set_model(adopt_ref(*new SearchEngineModel()));
  107. m_search_engine_combobox->set_only_allow_values_from_model(true);
  108. m_search_engine_combobox->on_change = [this](AK::ByteString const&, GUI::ModelIndex const& cursor_index) {
  109. auto url_format = m_search_engine_combobox->model()->index(cursor_index.row(), 1).data().to_byte_string();
  110. m_is_custom_search_engine = url_format.is_empty();
  111. m_custom_search_engine_group->set_enabled(m_is_custom_search_engine);
  112. set_modified(true);
  113. };
  114. set_search_engine_url(Config::read_string("Browser"sv, "Preferences"sv, "SearchEngine"sv, WebView::default_search_engine().query_url));
  115. m_auto_close_download_windows_checkbox = find_descendant_of_type_named<GUI::CheckBox>("auto_close_download_windows_checkbox");
  116. 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);
  117. m_auto_close_download_windows_checkbox->on_checked = [&](auto) { set_modified(true); };
  118. return {};
  119. }
  120. void BrowserSettingsWidget::set_color_scheme(StringView color_scheme)
  121. {
  122. bool found_color_scheme = false;
  123. for (int item_index = 0; item_index < m_color_scheme_combobox->model()->row_count(); ++item_index) {
  124. auto scheme = m_color_scheme_combobox->model()->index(item_index, 1).data().to_byte_string();
  125. if (scheme == color_scheme) {
  126. m_color_scheme_combobox->set_selected_index(item_index, GUI::AllowCallback::No);
  127. found_color_scheme = true;
  128. break;
  129. }
  130. }
  131. if (!found_color_scheme)
  132. m_color_scheme_combobox->set_selected_index(0, GUI::AllowCallback::No);
  133. }
  134. void BrowserSettingsWidget::set_search_engine_url(StringView url)
  135. {
  136. if (url.is_empty()) {
  137. m_enable_search_engine_checkbox->set_checked(false, GUI::AllowCallback::No);
  138. m_search_engine_combobox_group->set_enabled(false);
  139. m_custom_search_engine_group->set_enabled(false);
  140. m_search_engine_combobox->set_selected_index(0, GUI::AllowCallback::No);
  141. } else {
  142. m_enable_search_engine_checkbox->set_checked(true, GUI::AllowCallback::No);
  143. m_search_engine_combobox_group->set_enabled(true);
  144. bool found_url = false;
  145. for (int item_index = 0; item_index < m_search_engine_combobox->model()->row_count(); ++item_index) {
  146. auto url_format = m_search_engine_combobox->model()->index(item_index, 1).data().to_byte_string();
  147. if (url_format == url) {
  148. m_search_engine_combobox->set_selected_index(item_index, GUI::AllowCallback::No);
  149. found_url = true;
  150. break;
  151. }
  152. }
  153. if (!found_url) {
  154. m_is_custom_search_engine = true;
  155. m_custom_search_engine_textbox->set_text(url, GUI::AllowCallback::No);
  156. // We assume that "Custom" is the last item
  157. m_search_engine_combobox->set_selected_index(m_search_engine_combobox->model()->row_count() - 1, GUI::AllowCallback::No);
  158. m_custom_search_engine_group->set_enabled(true);
  159. } else {
  160. m_custom_search_engine_group->set_enabled(false);
  161. }
  162. }
  163. }
  164. void BrowserSettingsWidget::apply_settings()
  165. {
  166. auto homepage_url = m_homepage_url_textbox->text();
  167. if (!URL::URL(homepage_url).is_valid()) {
  168. GUI::MessageBox::show_error(this->window(), "The homepage URL you have entered is not valid"sv);
  169. m_homepage_url_textbox->select_all();
  170. m_homepage_url_textbox->set_focus(true);
  171. return;
  172. }
  173. Config::write_string("Browser"sv, "Preferences"sv, "Home"sv, homepage_url);
  174. auto new_tab_url = m_new_tab_url_textbox->text();
  175. if (!URL::URL(new_tab_url).is_valid()) {
  176. GUI::MessageBox::show_error(this->window(), "The new tab URL you have entered is not valid"sv);
  177. m_new_tab_url_textbox->select_all();
  178. m_new_tab_url_textbox->set_focus(true);
  179. return;
  180. }
  181. Config::write_string("Browser"sv, "Preferences"sv, "NewTab"sv, new_tab_url);
  182. Config::write_bool("Browser"sv, "Preferences"sv, "ShowBookmarksBar"sv, m_show_bookmarks_bar_checkbox->is_checked());
  183. auto color_scheme_index = m_color_scheme_combobox->selected_index();
  184. auto color_scheme = m_color_scheme_combobox->model()->index(color_scheme_index, 1).data().to_byte_string();
  185. Config::write_string("Browser"sv, "Preferences"sv, "ColorScheme"sv, color_scheme);
  186. if (!m_enable_search_engine_checkbox->is_checked()) {
  187. Config::write_string("Browser"sv, "Preferences"sv, "SearchEngine"sv, {});
  188. } else if (m_is_custom_search_engine) {
  189. Config::write_string("Browser"sv, "Preferences"sv, "SearchEngine"sv, m_custom_search_engine_textbox->text());
  190. } else {
  191. auto selected_index = m_search_engine_combobox->selected_index();
  192. auto url = m_search_engine_combobox->model()->index(selected_index, 1).data().to_byte_string();
  193. Config::write_string("Browser"sv, "Preferences"sv, "SearchEngine"sv, url);
  194. }
  195. Config::write_bool("Browser"sv, "Preferences"sv, "CloseDownloadWidgetOnFinish"sv, m_auto_close_download_windows_checkbox->is_checked());
  196. }
  197. void BrowserSettingsWidget::reset_default_values()
  198. {
  199. m_homepage_url_textbox->set_text(Browser::default_homepage_url);
  200. m_new_tab_url_textbox->set_text(Browser::default_new_tab_url);
  201. m_show_bookmarks_bar_checkbox->set_checked(Browser::default_show_bookmarks_bar);
  202. set_color_scheme(Browser::default_color_scheme);
  203. m_auto_close_download_windows_checkbox->set_checked(Browser::default_close_download_widget_on_finish);
  204. set_search_engine_url(WebView::default_search_engine().query_url);
  205. }
  206. }