| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/gtk/options/general_page_gtk.h" | |
| 6 | |
| 7 #include <set> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "app/l10n_util.h" | |
| 11 #include "base/callback.h" | |
| 12 #include "base/command_line.h" | |
| 13 #include "base/utf_string_conversions.h" | |
| 14 #include "chrome/browser/custom_home_pages_table_model.h" | |
| 15 #include "chrome/browser/gtk/accessible_widget_helper_gtk.h" | |
| 16 #include "chrome/browser/gtk/gtk_chrome_link_button.h" | |
| 17 #include "chrome/browser/gtk/gtk_util.h" | |
| 18 #include "chrome/browser/gtk/keyword_editor_view.h" | |
| 19 #include "chrome/browser/gtk/options/managed_prefs_banner_gtk.h" | |
| 20 #include "chrome/browser/gtk/options/options_layout_gtk.h" | |
| 21 #include "chrome/browser/gtk/options/url_picker_dialog_gtk.h" | |
| 22 #include "chrome/browser/instant/instant_confirm_dialog.h" | |
| 23 #include "chrome/browser/instant/instant_controller.h" | |
| 24 #include "chrome/browser/net/url_fixer_upper.h" | |
| 25 #include "chrome/browser/prefs/pref_service.h" | |
| 26 #include "chrome/browser/prefs/session_startup_pref.h" | |
| 27 #include "chrome/browser/profiles/profile.h" | |
| 28 #include "chrome/browser/search_engines/template_url.h" | |
| 29 #include "chrome/browser/search_engines/template_url_model.h" | |
| 30 #include "chrome/browser/ui/options/show_options_url.h" | |
| 31 #include "chrome/common/pref_names.h" | |
| 32 #include "chrome/common/url_constants.h" | |
| 33 #include "gfx/gtk_util.h" | |
| 34 #include "grit/chromium_strings.h" | |
| 35 #include "grit/generated_resources.h" | |
| 36 | |
| 37 namespace { | |
| 38 | |
| 39 // Markup for the text showing the current state of the default browser | |
| 40 const char kDefaultBrowserLabelMarkup[] = "<span color='#%s'>%s</span>"; | |
| 41 | |
| 42 // Color of the default browser text when Chromium is the default browser | |
| 43 const char kDefaultBrowserLabelColor[] = "008700"; | |
| 44 | |
| 45 // Color of the default browser text when Chromium is not the default browser | |
| 46 const char kNotDefaultBrowserLabelColor[] = "870000"; | |
| 47 | |
| 48 // Column ids for |startup_custom_pages_store_|. | |
| 49 enum { | |
| 50 COL_FAVICON, | |
| 51 COL_URL, | |
| 52 COL_TOOLTIP, | |
| 53 COL_COUNT, | |
| 54 }; | |
| 55 | |
| 56 // Column ids for |default_search_engines_model_|. | |
| 57 enum { | |
| 58 SEARCH_ENGINES_COL_INDEX, | |
| 59 SEARCH_ENGINES_COL_TITLE, | |
| 60 SEARCH_ENGINES_COL_COUNT, | |
| 61 }; | |
| 62 | |
| 63 bool IsNewTabUIURLString(const GURL& url) { | |
| 64 return url == GURL(chrome::kChromeUINewTabURL); | |
| 65 } | |
| 66 | |
| 67 } // namespace | |
| 68 | |
| 69 /////////////////////////////////////////////////////////////////////////////// | |
| 70 // GeneralPageGtk, public: | |
| 71 | |
| 72 GeneralPageGtk::GeneralPageGtk(Profile* profile) | |
| 73 : OptionsPageBase(profile), | |
| 74 template_url_model_(NULL), | |
| 75 instant_checkbox_(NULL), | |
| 76 default_search_initializing_(true), | |
| 77 initializing_(true), | |
| 78 default_browser_worker_( | |
| 79 new ShellIntegration::DefaultBrowserWorker(this)), | |
| 80 managed_prefs_banner_(profile->GetPrefs(), OPTIONS_PAGE_GENERAL) { | |
| 81 scoped_ptr<OptionsLayoutBuilderGtk> | |
| 82 options_builder(OptionsLayoutBuilderGtk::CreateOptionallyCompactLayout()); | |
| 83 page_ = options_builder->get_page_widget(); | |
| 84 accessible_widget_helper_.reset(new AccessibleWidgetHelper(page_, profile)); | |
| 85 | |
| 86 options_builder->AddWidget(managed_prefs_banner_.banner_widget(), false); | |
| 87 options_builder->AddOptionGroup( | |
| 88 l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_GROUP_NAME), | |
| 89 InitStartupGroup(), true); | |
| 90 options_builder->AddOptionGroup( | |
| 91 l10n_util::GetStringUTF8(IDS_OPTIONS_HOMEPAGE_GROUP_NAME), | |
| 92 InitHomepageGroup(), false); | |
| 93 options_builder->AddOptionGroup( | |
| 94 l10n_util::GetStringUTF8(IDS_OPTIONS_DEFAULTSEARCH_GROUP_NAME), | |
| 95 InitDefaultSearchGroup(), false); | |
| 96 #if !defined(OS_CHROMEOS) | |
| 97 options_builder->AddOptionGroup( | |
| 98 l10n_util::GetStringUTF8(IDS_OPTIONS_DEFAULTBROWSER_GROUP_NAME), | |
| 99 InitDefaultBrowserGroup(), false); | |
| 100 #endif | |
| 101 | |
| 102 registrar_.Init(profile->GetPrefs()); | |
| 103 registrar_.Add(prefs::kRestoreOnStartup, this); | |
| 104 registrar_.Add(prefs::kURLsToRestoreOnStartup, this); | |
| 105 | |
| 106 new_tab_page_is_home_page_.Init(prefs::kHomePageIsNewTabPage, | |
| 107 profile->GetPrefs(), this); | |
| 108 homepage_.Init(prefs::kHomePage, profile->GetPrefs(), this); | |
| 109 show_home_button_.Init(prefs::kShowHomeButton, profile->GetPrefs(), this); | |
| 110 | |
| 111 instant_.Init(prefs::kInstantEnabled, profile->GetPrefs(), this); | |
| 112 | |
| 113 // Load initial values | |
| 114 NotifyPrefChanged(NULL); | |
| 115 } | |
| 116 | |
| 117 GeneralPageGtk::~GeneralPageGtk() { | |
| 118 if (template_url_model_) | |
| 119 template_url_model_->RemoveObserver(this); | |
| 120 | |
| 121 default_browser_worker_->ObserverDestroyed(); | |
| 122 } | |
| 123 | |
| 124 GtkWindow* GeneralPageGtk::GetWindow() { | |
| 125 return GTK_WINDOW(gtk_widget_get_toplevel(page_)); | |
| 126 } | |
| 127 | |
| 128 /////////////////////////////////////////////////////////////////////////////// | |
| 129 // GeneralPageGtk, OptionsPageBase overrides: | |
| 130 | |
| 131 void GeneralPageGtk::NotifyPrefChanged(const std::string* pref_name) { | |
| 132 initializing_ = true; | |
| 133 PrefService* prefs = profile()->GetPrefs(); | |
| 134 if (!pref_name || | |
| 135 *pref_name == prefs::kRestoreOnStartup || | |
| 136 *pref_name == prefs::kURLsToRestoreOnStartup) { | |
| 137 const SessionStartupPref startup_pref = | |
| 138 SessionStartupPref::GetStartupPref(prefs); | |
| 139 bool radio_buttons_enabled = !SessionStartupPref::TypeIsManaged(prefs); | |
| 140 bool restore_urls_enabled = !SessionStartupPref::URLsAreManaged(prefs); | |
| 141 switch (startup_pref.type) { | |
| 142 case SessionStartupPref::DEFAULT: | |
| 143 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(startup_homepage_radio_), | |
| 144 TRUE); | |
| 145 restore_urls_enabled = false; | |
| 146 break; | |
| 147 | |
| 148 case SessionStartupPref::LAST: | |
| 149 gtk_toggle_button_set_active( | |
| 150 GTK_TOGGLE_BUTTON(startup_last_session_radio_), TRUE); | |
| 151 restore_urls_enabled = false; | |
| 152 break; | |
| 153 | |
| 154 case SessionStartupPref::URLS: | |
| 155 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(startup_custom_radio_), | |
| 156 TRUE); | |
| 157 break; | |
| 158 } | |
| 159 gtk_widget_set_sensitive(startup_homepage_radio_, radio_buttons_enabled); | |
| 160 gtk_widget_set_sensitive(startup_last_session_radio_, | |
| 161 radio_buttons_enabled); | |
| 162 gtk_widget_set_sensitive(startup_custom_radio_, radio_buttons_enabled); | |
| 163 EnableCustomHomepagesControls(restore_urls_enabled); | |
| 164 startup_custom_pages_table_model_->SetURLs(startup_pref.urls); | |
| 165 } | |
| 166 | |
| 167 if (!pref_name || | |
| 168 *pref_name == prefs::kHomePageIsNewTabPage || | |
| 169 *pref_name == prefs::kHomePage) { | |
| 170 bool new_tab_page_is_home_page_managed = | |
| 171 new_tab_page_is_home_page_.IsManaged(); | |
| 172 bool homepage_managed = homepage_.IsManaged(); | |
| 173 bool homepage_url_is_new_tab = | |
| 174 IsNewTabUIURLString(GURL(homepage_.GetValue())); | |
| 175 bool homepage_is_new_tab = homepage_url_is_new_tab || | |
| 176 new_tab_page_is_home_page_.GetValue(); | |
| 177 // If HomepageIsNewTab is managed or | |
| 178 // Homepage is 'chrome://newtab' and managed, disable the radios. | |
| 179 bool disable_homepage_choice_buttons = | |
| 180 new_tab_page_is_home_page_managed || | |
| 181 (homepage_managed && homepage_url_is_new_tab); | |
| 182 if (!homepage_url_is_new_tab) { | |
| 183 gtk_entry_set_text(GTK_ENTRY(homepage_use_url_entry_), | |
| 184 homepage_.GetValue().c_str()); | |
| 185 } | |
| 186 UpdateHomepageIsNewTabRadio( | |
| 187 homepage_is_new_tab, !disable_homepage_choice_buttons); | |
| 188 EnableHomepageURLField(!homepage_is_new_tab); | |
| 189 } | |
| 190 | |
| 191 if (!pref_name || *pref_name == prefs::kShowHomeButton) { | |
| 192 gtk_toggle_button_set_active( | |
| 193 GTK_TOGGLE_BUTTON(homepage_show_home_button_checkbox_), | |
| 194 show_home_button_.GetValue()); | |
| 195 gtk_widget_set_sensitive( | |
| 196 homepage_show_home_button_checkbox_, | |
| 197 !show_home_button_.IsManaged()); | |
| 198 } | |
| 199 | |
| 200 if ((!pref_name || *pref_name == prefs::kInstantEnabled) && | |
| 201 instant_checkbox_) { | |
| 202 gtk_toggle_button_set_active( | |
| 203 GTK_TOGGLE_BUTTON(instant_checkbox_), instant_.GetValue()); | |
| 204 } | |
| 205 | |
| 206 initializing_ = false; | |
| 207 } | |
| 208 | |
| 209 void GeneralPageGtk::HighlightGroup(OptionsGroup highlight_group) { | |
| 210 // TODO(mattm): implement group highlighting | |
| 211 } | |
| 212 | |
| 213 /////////////////////////////////////////////////////////////////////////////// | |
| 214 // GeneralPageGtk, private: | |
| 215 | |
| 216 GtkWidget* GeneralPageGtk::InitStartupGroup() { | |
| 217 GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
| 218 | |
| 219 startup_homepage_radio_ = gtk_radio_button_new_with_label(NULL, | |
| 220 l10n_util::GetStringUTF8( | |
| 221 IDS_OPTIONS_STARTUP_SHOW_DEFAULT_AND_NEWTAB).c_str()); | |
| 222 g_signal_connect(startup_homepage_radio_, "toggled", | |
| 223 G_CALLBACK(OnStartupRadioToggledThunk), this); | |
| 224 gtk_box_pack_start(GTK_BOX(vbox), startup_homepage_radio_, FALSE, FALSE, 0); | |
| 225 | |
| 226 startup_last_session_radio_ = gtk_radio_button_new_with_label_from_widget( | |
| 227 GTK_RADIO_BUTTON(startup_homepage_radio_), | |
| 228 l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_SHOW_LAST_SESSION).c_str()); | |
| 229 g_signal_connect(startup_last_session_radio_, "toggled", | |
| 230 G_CALLBACK(OnStartupRadioToggledThunk), this); | |
| 231 gtk_box_pack_start(GTK_BOX(vbox), startup_last_session_radio_, | |
| 232 FALSE, FALSE, 0); | |
| 233 | |
| 234 startup_custom_radio_ = gtk_radio_button_new_with_label_from_widget( | |
| 235 GTK_RADIO_BUTTON(startup_homepage_radio_), | |
| 236 l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_SHOW_PAGES).c_str()); | |
| 237 g_signal_connect(startup_custom_radio_, "toggled", | |
| 238 G_CALLBACK(OnStartupRadioToggledThunk), this); | |
| 239 gtk_box_pack_start(GTK_BOX(vbox), startup_custom_radio_, FALSE, FALSE, 0); | |
| 240 | |
| 241 GtkWidget* url_list_container = gtk_hbox_new(FALSE, | |
| 242 gtk_util::kControlSpacing); | |
| 243 gtk_box_pack_start(GTK_BOX(vbox), url_list_container, TRUE, TRUE, 0); | |
| 244 | |
| 245 GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL); | |
| 246 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window), | |
| 247 GTK_POLICY_AUTOMATIC, | |
| 248 GTK_POLICY_AUTOMATIC); | |
| 249 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window), | |
| 250 GTK_SHADOW_ETCHED_IN); | |
| 251 gtk_container_add(GTK_CONTAINER(url_list_container), | |
| 252 scroll_window); | |
| 253 startup_custom_pages_store_ = gtk_list_store_new(COL_COUNT, | |
| 254 GDK_TYPE_PIXBUF, | |
| 255 G_TYPE_STRING, | |
| 256 G_TYPE_STRING); | |
| 257 startup_custom_pages_tree_ = gtk_tree_view_new_with_model( | |
| 258 GTK_TREE_MODEL(startup_custom_pages_store_)); | |
| 259 gtk_container_add(GTK_CONTAINER(scroll_window), startup_custom_pages_tree_); | |
| 260 | |
| 261 // Release |startup_custom_pages_store_| so that |startup_custom_pages_tree_| | |
| 262 // owns the model. | |
| 263 g_object_unref(startup_custom_pages_store_); | |
| 264 | |
| 265 gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(startup_custom_pages_tree_), | |
| 266 COL_TOOLTIP); | |
| 267 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(startup_custom_pages_tree_), | |
| 268 FALSE); | |
| 269 GtkTreeViewColumn* column = gtk_tree_view_column_new(); | |
| 270 GtkCellRenderer* renderer = gtk_cell_renderer_pixbuf_new(); | |
| 271 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
| 272 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", COL_FAVICON); | |
| 273 renderer = gtk_cell_renderer_text_new(); | |
| 274 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
| 275 gtk_tree_view_column_add_attribute(column, renderer, "text", COL_URL); | |
| 276 gtk_tree_view_append_column(GTK_TREE_VIEW(startup_custom_pages_tree_), | |
| 277 column); | |
| 278 startup_custom_pages_selection_ = gtk_tree_view_get_selection( | |
| 279 GTK_TREE_VIEW(startup_custom_pages_tree_)); | |
| 280 gtk_tree_selection_set_mode(startup_custom_pages_selection_, | |
| 281 GTK_SELECTION_MULTIPLE); | |
| 282 g_signal_connect(startup_custom_pages_selection_, "changed", | |
| 283 G_CALLBACK(OnStartupPagesSelectionChangedThunk), this); | |
| 284 | |
| 285 startup_custom_pages_table_model_.reset( | |
| 286 new CustomHomePagesTableModel(profile())); | |
| 287 startup_custom_pages_table_adapter_.reset( | |
| 288 new gtk_tree::TableAdapter(this, startup_custom_pages_store_, | |
| 289 startup_custom_pages_table_model_.get())); | |
| 290 | |
| 291 GtkWidget* url_list_buttons = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
| 292 gtk_box_pack_end(GTK_BOX(url_list_container), url_list_buttons, | |
| 293 FALSE, FALSE, 0); | |
| 294 | |
| 295 startup_add_custom_page_button_ = gtk_button_new_with_mnemonic( | |
| 296 gfx::ConvertAcceleratorsFromWindowsStyle( | |
| 297 l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_ADD_BUTTON)).c_str()); | |
| 298 g_signal_connect(startup_add_custom_page_button_, "clicked", | |
| 299 G_CALLBACK(OnStartupAddCustomPageClickedThunk), this); | |
| 300 gtk_box_pack_start(GTK_BOX(url_list_buttons), startup_add_custom_page_button_, | |
| 301 FALSE, FALSE, 0); | |
| 302 startup_remove_custom_page_button_ = gtk_button_new_with_mnemonic( | |
| 303 gfx::ConvertAcceleratorsFromWindowsStyle( | |
| 304 l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_REMOVE_BUTTON)).c_str()); | |
| 305 g_signal_connect(startup_remove_custom_page_button_, "clicked", | |
| 306 G_CALLBACK(OnStartupRemoveCustomPageClickedThunk), this); | |
| 307 gtk_box_pack_start(GTK_BOX(url_list_buttons), | |
| 308 startup_remove_custom_page_button_, FALSE, FALSE, 0); | |
| 309 startup_use_current_page_button_ = gtk_button_new_with_mnemonic( | |
| 310 gfx::ConvertAcceleratorsFromWindowsStyle( | |
| 311 l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_USE_CURRENT)).c_str()); | |
| 312 g_signal_connect(startup_use_current_page_button_, "clicked", | |
| 313 G_CALLBACK(OnStartupUseCurrentPageClickedThunk), this); | |
| 314 gtk_box_pack_start(GTK_BOX(url_list_buttons), | |
| 315 startup_use_current_page_button_, FALSE, FALSE, 0); | |
| 316 | |
| 317 return vbox; | |
| 318 } | |
| 319 | |
| 320 GtkWidget* GeneralPageGtk::InitHomepageGroup() { | |
| 321 GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
| 322 | |
| 323 homepage_use_newtab_radio_ = gtk_radio_button_new_with_label(NULL, | |
| 324 l10n_util::GetStringUTF8(IDS_OPTIONS_HOMEPAGE_USE_NEWTAB).c_str()); | |
| 325 g_signal_connect(homepage_use_newtab_radio_, "toggled", | |
| 326 G_CALLBACK(OnNewTabIsHomePageToggledThunk), this); | |
| 327 gtk_container_add(GTK_CONTAINER(vbox), homepage_use_newtab_radio_); | |
| 328 | |
| 329 GtkWidget* homepage_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing); | |
| 330 gtk_container_add(GTK_CONTAINER(vbox), homepage_hbox); | |
| 331 | |
| 332 homepage_use_url_radio_ = gtk_radio_button_new_with_label_from_widget( | |
| 333 GTK_RADIO_BUTTON(homepage_use_newtab_radio_), | |
| 334 l10n_util::GetStringUTF8(IDS_OPTIONS_HOMEPAGE_USE_URL).c_str()); | |
| 335 g_signal_connect(homepage_use_url_radio_, "toggled", | |
| 336 G_CALLBACK(OnNewTabIsHomePageToggledThunk), this); | |
| 337 gtk_box_pack_start(GTK_BOX(homepage_hbox), homepage_use_url_radio_, | |
| 338 FALSE, FALSE, 0); | |
| 339 | |
| 340 homepage_use_url_entry_ = gtk_entry_new(); | |
| 341 g_signal_connect(homepage_use_url_entry_, "changed", | |
| 342 G_CALLBACK(OnHomepageUseUrlEntryChangedThunk), this); | |
| 343 gtk_box_pack_start(GTK_BOX(homepage_hbox), homepage_use_url_entry_, | |
| 344 TRUE, TRUE, 0); | |
| 345 | |
| 346 homepage_show_home_button_checkbox_ = gtk_check_button_new_with_label( | |
| 347 l10n_util::GetStringUTF8(IDS_OPTIONS_HOMEPAGE_SHOW_BUTTON).c_str()); | |
| 348 g_signal_connect(homepage_show_home_button_checkbox_, "toggled", | |
| 349 G_CALLBACK(OnShowHomeButtonToggledThunk), this); | |
| 350 gtk_container_add(GTK_CONTAINER(vbox), homepage_show_home_button_checkbox_); | |
| 351 | |
| 352 return vbox; | |
| 353 } | |
| 354 | |
| 355 GtkWidget* GeneralPageGtk::InitDefaultSearchGroup() { | |
| 356 GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
| 357 GtkWidget* search_hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing); | |
| 358 gtk_box_pack_start(GTK_BOX(vbox), search_hbox, FALSE, FALSE, 0); | |
| 359 | |
| 360 default_search_engines_model_ = gtk_list_store_new(SEARCH_ENGINES_COL_COUNT, | |
| 361 G_TYPE_UINT, | |
| 362 G_TYPE_STRING); | |
| 363 default_search_engine_combobox_ = gtk_combo_box_new_with_model( | |
| 364 GTK_TREE_MODEL(default_search_engines_model_)); | |
| 365 g_object_unref(default_search_engines_model_); | |
| 366 g_signal_connect(default_search_engine_combobox_, "changed", | |
| 367 G_CALLBACK(OnDefaultSearchEngineChangedThunk), this); | |
| 368 gtk_container_add(GTK_CONTAINER(search_hbox), | |
| 369 default_search_engine_combobox_); | |
| 370 accessible_widget_helper_->SetWidgetName( | |
| 371 default_search_engine_combobox_, IDS_OPTIONS_DEFAULTSEARCH_GROUP_NAME); | |
| 372 | |
| 373 GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); | |
| 374 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(default_search_engine_combobox_), | |
| 375 renderer, TRUE); | |
| 376 gtk_cell_layout_set_attributes( | |
| 377 GTK_CELL_LAYOUT(default_search_engine_combobox_), renderer, | |
| 378 "text", SEARCH_ENGINES_COL_TITLE, | |
| 379 NULL); | |
| 380 | |
| 381 template_url_model_ = profile()->GetTemplateURLModel(); | |
| 382 if (template_url_model_) { | |
| 383 template_url_model_->Load(); | |
| 384 template_url_model_->AddObserver(this); | |
| 385 } | |
| 386 OnTemplateURLModelChanged(); | |
| 387 | |
| 388 default_search_manage_engines_button_ = gtk_button_new_with_label( | |
| 389 l10n_util::GetStringUTF8( | |
| 390 IDS_OPTIONS_DEFAULTSEARCH_MANAGE_ENGINES_LINK).c_str()); | |
| 391 g_signal_connect(default_search_manage_engines_button_, "clicked", | |
| 392 G_CALLBACK(OnDefaultSearchManageEnginesClickedThunk), this); | |
| 393 gtk_box_pack_start(GTK_BOX(search_hbox), | |
| 394 default_search_manage_engines_button_, FALSE, FALSE, 0); | |
| 395 | |
| 396 // When the instant lab is on, add some options for instant. We want the | |
| 397 // warning text and link to align with the pref's checkbox's label. | |
| 398 // Need a new vbox as we don't want any spacing between these labels. | |
| 399 GtkWidget* instant_vbox = gtk_vbox_new(FALSE, 0); | |
| 400 gtk_box_pack_start(GTK_BOX(vbox), instant_vbox, FALSE, FALSE, 0); | |
| 401 | |
| 402 instant_checkbox_ = gtk_check_button_new_with_label( | |
| 403 l10n_util::GetStringUTF8(IDS_INSTANT_PREF).c_str()); | |
| 404 g_signal_connect(instant_checkbox_, "toggled", | |
| 405 G_CALLBACK(OnInstantToggledThunk), this); | |
| 406 gtk_box_pack_start(GTK_BOX(instant_vbox), instant_checkbox_, FALSE, FALSE, 0); | |
| 407 | |
| 408 // Relies on knowledge of GTK+ internals to find the checkbox's label child | |
| 409 // and then make the indent below match its vertical spacing. | |
| 410 GtkWidget* instant_label = gtk_bin_get_child(GTK_BIN(instant_checkbox_)); | |
| 411 if (instant_label && GTK_IS_LABEL(instant_label)) { | |
| 412 g_signal_connect(instant_label, "size-allocate", | |
| 413 G_CALLBACK(OnInstantLabelSizeAllocateThunk), this); | |
| 414 } | |
| 415 | |
| 416 instant_indent_ = gtk_fixed_new(); | |
| 417 GtkWidget* explanation_box = gtk_hbox_new(FALSE, 0); | |
| 418 GtkWidget* explanation = gtk_label_new(( | |
| 419 l10n_util::GetStringUTF8(IDS_INSTANT_PREF_WARNING) + " ").c_str()); | |
| 420 GtkWidget* learn_more_link = gtk_chrome_link_button_new( | |
| 421 l10n_util::GetStringUTF8(IDS_LEARN_MORE).c_str()); | |
| 422 g_signal_connect(learn_more_link, "clicked", | |
| 423 G_CALLBACK(OnSearchLearnMoreClickedThunk), this); | |
| 424 gtk_box_pack_start(GTK_BOX(explanation_box), instant_indent_, | |
| 425 FALSE, FALSE, 0); | |
| 426 gtk_box_pack_start(GTK_BOX(explanation_box), explanation, | |
| 427 FALSE, FALSE, 0); | |
| 428 gtk_box_pack_start(GTK_BOX(explanation_box), learn_more_link, | |
| 429 FALSE, FALSE, 0); | |
| 430 gtk_box_pack_start(GTK_BOX(instant_vbox), explanation_box, FALSE, FALSE, 0); | |
| 431 | |
| 432 return vbox; | |
| 433 } | |
| 434 | |
| 435 GtkWidget* GeneralPageGtk::InitDefaultBrowserGroup() { | |
| 436 GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
| 437 | |
| 438 // TODO(mattm): the label should be created with a text like "checking for | |
| 439 // default" to be displayed while we wait for the check to complete. | |
| 440 default_browser_status_label_ = gtk_label_new(NULL); | |
| 441 gtk_box_pack_start(GTK_BOX(vbox), default_browser_status_label_, | |
| 442 FALSE, FALSE, 0); | |
| 443 | |
| 444 default_browser_use_as_default_button_ = gtk_button_new_with_label( | |
| 445 l10n_util::GetStringFUTF8(IDS_OPTIONS_DEFAULTBROWSER_USEASDEFAULT, | |
| 446 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)).c_str()); | |
| 447 g_signal_connect(default_browser_use_as_default_button_, "clicked", | |
| 448 G_CALLBACK(OnBrowserUseAsDefaultClickedThunk), this); | |
| 449 | |
| 450 gtk_box_pack_start(GTK_BOX(vbox), default_browser_use_as_default_button_, | |
| 451 FALSE, FALSE, 0); | |
| 452 | |
| 453 GtkWidget* vbox_alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); | |
| 454 gtk_container_add(GTK_CONTAINER(vbox_alignment), vbox); | |
| 455 | |
| 456 default_browser_worker_->StartCheckDefaultBrowser(); | |
| 457 | |
| 458 return vbox_alignment; | |
| 459 } | |
| 460 | |
| 461 void GeneralPageGtk::OnStartupRadioToggled(GtkWidget* toggle_button) { | |
| 462 if (initializing_) | |
| 463 return; | |
| 464 | |
| 465 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button))) { | |
| 466 // When selecting a radio button, we get two signals (one for the old radio | |
| 467 // being toggled off, one for the new one being toggled on.) Ignore the | |
| 468 // signal for toggling off the old button. | |
| 469 return; | |
| 470 } | |
| 471 SaveStartupPref(); | |
| 472 if (toggle_button == startup_homepage_radio_) { | |
| 473 UserMetricsRecordAction(UserMetricsAction("Options_Startup_Homepage"), | |
| 474 profile()->GetPrefs()); | |
| 475 } else if (toggle_button == startup_last_session_radio_) { | |
| 476 UserMetricsRecordAction(UserMetricsAction("Options_Startup_LastSession"), | |
| 477 profile()->GetPrefs()); | |
| 478 } else if (toggle_button == startup_custom_radio_) { | |
| 479 UserMetricsRecordAction(UserMetricsAction("Options_Startup_Custom"), | |
| 480 profile()->GetPrefs()); | |
| 481 } | |
| 482 } | |
| 483 | |
| 484 void GeneralPageGtk::OnStartupAddCustomPageClicked(GtkWidget* button) { | |
| 485 new UrlPickerDialogGtk( | |
| 486 NewCallback(this, &GeneralPageGtk::OnAddCustomUrl), | |
| 487 profile(), | |
| 488 GetWindow()); | |
| 489 } | |
| 490 | |
| 491 void GeneralPageGtk::OnStartupRemoveCustomPageClicked(GtkWidget* button) { | |
| 492 RemoveSelectedCustomUrls(); | |
| 493 } | |
| 494 | |
| 495 void GeneralPageGtk::OnStartupUseCurrentPageClicked(GtkWidget* button) { | |
| 496 SetCustomUrlListFromCurrentPages(); | |
| 497 } | |
| 498 | |
| 499 void GeneralPageGtk::OnStartupPagesSelectionChanged( | |
| 500 GtkTreeSelection* selection) { | |
| 501 EnableCustomHomepagesControls(true); | |
| 502 } | |
| 503 | |
| 504 void GeneralPageGtk::OnNewTabIsHomePageToggled(GtkWidget* toggle_button) { | |
| 505 if (initializing_) | |
| 506 return; | |
| 507 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button))) { | |
| 508 // Ignore the signal for toggling off the old button. | |
| 509 return; | |
| 510 } | |
| 511 if (toggle_button == homepage_use_newtab_radio_) { | |
| 512 UserMetricsRecordAction(UserMetricsAction("Options_Homepage_UseNewTab"), | |
| 513 profile()->GetPrefs()); | |
| 514 UpdateHomepagePrefs(); | |
| 515 EnableHomepageURLField(false); | |
| 516 } else if (toggle_button == homepage_use_url_radio_) { | |
| 517 UserMetricsRecordAction(UserMetricsAction("Options_Homepage_UseURL"), | |
| 518 profile()->GetPrefs()); | |
| 519 UpdateHomepagePrefs(); | |
| 520 EnableHomepageURLField(true); | |
| 521 } | |
| 522 } | |
| 523 | |
| 524 void GeneralPageGtk::OnHomepageUseUrlEntryChanged(GtkWidget* editable) { | |
| 525 if (initializing_) | |
| 526 return; | |
| 527 UpdateHomepagePrefs(); | |
| 528 } | |
| 529 | |
| 530 void GeneralPageGtk::OnShowHomeButtonToggled(GtkWidget* toggle_button) { | |
| 531 if (initializing_) | |
| 532 return; | |
| 533 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)); | |
| 534 show_home_button_.SetValue(enabled); | |
| 535 if (enabled) { | |
| 536 UserMetricsRecordAction( | |
| 537 UserMetricsAction("Options_Homepage_ShowHomeButton"), | |
| 538 profile()->GetPrefs()); | |
| 539 } else { | |
| 540 UserMetricsRecordAction( | |
| 541 UserMetricsAction("Options_Homepage_HideHomeButton"), | |
| 542 profile()->GetPrefs()); | |
| 543 } | |
| 544 } | |
| 545 | |
| 546 void GeneralPageGtk::OnInstantToggled(GtkWidget* toggle_button) { | |
| 547 if (initializing_) | |
| 548 return; | |
| 549 | |
| 550 bool enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)); | |
| 551 | |
| 552 if (enabled) { | |
| 553 if (!instant_.GetValue()) | |
| 554 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(instant_checkbox_), false); | |
| 555 browser::ShowInstantConfirmDialogIfNecessary(GetWindow(), profile()); | |
| 556 } else { | |
| 557 InstantController::Disable(profile()); | |
| 558 } | |
| 559 | |
| 560 // TODO(estade): UMA? | |
| 561 } | |
| 562 | |
| 563 void GeneralPageGtk::OnDefaultSearchEngineChanged(GtkWidget* combo_box) { | |
| 564 if (default_search_initializing_) | |
| 565 return; | |
| 566 SetDefaultSearchEngineFromComboBox(); | |
| 567 } | |
| 568 | |
| 569 void GeneralPageGtk::OnDefaultSearchManageEnginesClicked(GtkWidget* button) { | |
| 570 KeywordEditorView::Show(profile()); | |
| 571 } | |
| 572 | |
| 573 void GeneralPageGtk::OnBrowserUseAsDefaultClicked(GtkWidget* button) { | |
| 574 default_browser_worker_->StartSetAsDefaultBrowser(); | |
| 575 // If the user made Chrome the default browser, then he/she arguably wants | |
| 576 // to be notified when that changes. | |
| 577 profile()->GetPrefs()->SetBoolean(prefs::kCheckDefaultBrowser, true); | |
| 578 UserMetricsRecordAction(UserMetricsAction("Options_SetAsDefaultBrowser"), | |
| 579 profile()->GetPrefs()); | |
| 580 } | |
| 581 | |
| 582 void GeneralPageGtk::SaveStartupPref() { | |
| 583 SessionStartupPref pref; | |
| 584 | |
| 585 if (gtk_toggle_button_get_active( | |
| 586 GTK_TOGGLE_BUTTON(startup_last_session_radio_))) { | |
| 587 pref.type = SessionStartupPref::LAST; | |
| 588 } else if (gtk_toggle_button_get_active( | |
| 589 GTK_TOGGLE_BUTTON(startup_custom_radio_))) { | |
| 590 pref.type = SessionStartupPref::URLS; | |
| 591 } | |
| 592 | |
| 593 pref.urls = startup_custom_pages_table_model_->GetURLs(); | |
| 594 | |
| 595 SessionStartupPref::SetStartupPref(profile()->GetPrefs(), pref); | |
| 596 } | |
| 597 | |
| 598 void GeneralPageGtk::SetColumnValues(int row, GtkTreeIter* iter) { | |
| 599 SkBitmap bitmap = startup_custom_pages_table_model_->GetIcon(row); | |
| 600 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap); | |
| 601 string16 text = startup_custom_pages_table_model_->GetText(row, 0); | |
| 602 std::string tooltip = | |
| 603 UTF16ToUTF8(startup_custom_pages_table_model_->GetTooltip(row)); | |
| 604 gchar* escaped_tooltip = g_markup_escape_text(tooltip.c_str(), | |
| 605 tooltip.size()); | |
| 606 gtk_list_store_set(startup_custom_pages_store_, iter, | |
| 607 COL_FAVICON, pixbuf, | |
| 608 COL_URL, UTF16ToUTF8(text).c_str(), | |
| 609 COL_TOOLTIP, escaped_tooltip, | |
| 610 -1); | |
| 611 g_object_unref(pixbuf); | |
| 612 g_free(escaped_tooltip); | |
| 613 } | |
| 614 | |
| 615 void GeneralPageGtk::SetCustomUrlListFromCurrentPages() { | |
| 616 startup_custom_pages_table_model_->SetToCurrentlyOpenPages(); | |
| 617 | |
| 618 SaveStartupPref(); | |
| 619 } | |
| 620 | |
| 621 void GeneralPageGtk::OnAddCustomUrl(const GURL& url) { | |
| 622 // The restore URLs policy might have become managed while the dialog is | |
| 623 // displayed. While the model makes sure that no changes are made in this | |
| 624 // condition, we should still avoid the rest of the method otherwise | |
| 625 // graphic elements will become enabled. | |
| 626 if (SessionStartupPref::URLsAreManaged(profile()->GetPrefs())) | |
| 627 return; | |
| 628 std::set<int> indices; | |
| 629 gtk_tree::GetSelectedIndices(startup_custom_pages_selection_, &indices); | |
| 630 int index; | |
| 631 if (indices.empty()) | |
| 632 index = startup_custom_pages_table_model_->RowCount(); | |
| 633 else | |
| 634 index = *indices.begin() + 1; | |
| 635 startup_custom_pages_table_model_->Add(index, url); | |
| 636 | |
| 637 SaveStartupPref(); | |
| 638 | |
| 639 gtk_tree::SelectAndFocusRowNum(index, | |
| 640 GTK_TREE_VIEW(startup_custom_pages_tree_)); | |
| 641 } | |
| 642 | |
| 643 void GeneralPageGtk::RemoveSelectedCustomUrls() { | |
| 644 std::set<int> indices; | |
| 645 gtk_tree::GetSelectedIndices(startup_custom_pages_selection_, &indices); | |
| 646 | |
| 647 int selected_row = 0; | |
| 648 for (std::set<int>::reverse_iterator i = indices.rbegin(); | |
| 649 i != indices.rend(); ++i) { | |
| 650 startup_custom_pages_table_model_->Remove(*i); | |
| 651 selected_row = *i; | |
| 652 } | |
| 653 | |
| 654 SaveStartupPref(); | |
| 655 | |
| 656 // Select the next row after the last row deleted, or the above item if the | |
| 657 // latest item was deleted or nothing when the table doesn't have any items. | |
| 658 int row_count = startup_custom_pages_table_model_->RowCount(); | |
| 659 if (selected_row >= row_count) | |
| 660 selected_row = row_count - 1; | |
| 661 if (selected_row >= 0) { | |
| 662 gtk_tree::SelectAndFocusRowNum(selected_row, | |
| 663 GTK_TREE_VIEW(startup_custom_pages_tree_)); | |
| 664 } | |
| 665 } | |
| 666 | |
| 667 void GeneralPageGtk::OnTemplateURLModelChanged() { | |
| 668 if (!template_url_model_ || !template_url_model_->loaded()) { | |
| 669 EnableDefaultSearchEngineComboBox(false); | |
| 670 return; | |
| 671 } | |
| 672 default_search_initializing_ = true; | |
| 673 gtk_list_store_clear(default_search_engines_model_); | |
| 674 const TemplateURL* default_search_provider = | |
| 675 template_url_model_->GetDefaultSearchProvider(); | |
| 676 std::vector<const TemplateURL*> model_urls = | |
| 677 template_url_model_->GetTemplateURLs(); | |
| 678 bool populated = false; | |
| 679 for (size_t i = 0; i < model_urls.size(); ++i) { | |
| 680 if (!model_urls[i]->ShowInDefaultList()) | |
| 681 continue; | |
| 682 populated = true; | |
| 683 GtkTreeIter iter; | |
| 684 gtk_list_store_append(default_search_engines_model_, &iter); | |
| 685 gtk_list_store_set( | |
| 686 default_search_engines_model_, &iter, | |
| 687 SEARCH_ENGINES_COL_INDEX, i, | |
| 688 SEARCH_ENGINES_COL_TITLE, | |
| 689 WideToUTF8(model_urls[i]->short_name()).c_str(), | |
| 690 -1); | |
| 691 if (model_urls[i] == default_search_provider) { | |
| 692 gtk_combo_box_set_active_iter( | |
| 693 GTK_COMBO_BOX(default_search_engine_combobox_), &iter); | |
| 694 } | |
| 695 } | |
| 696 EnableDefaultSearchEngineComboBox(populated && | |
| 697 !template_url_model_->is_default_search_managed()); | |
| 698 default_search_initializing_ = false; | |
| 699 } | |
| 700 | |
| 701 void GeneralPageGtk::SetDefaultSearchEngineFromComboBox() { | |
| 702 GtkTreeIter iter; | |
| 703 if (!gtk_combo_box_get_active_iter( | |
| 704 GTK_COMBO_BOX(default_search_engine_combobox_), &iter)) { | |
| 705 return; | |
| 706 } | |
| 707 guint index; | |
| 708 gtk_tree_model_get(GTK_TREE_MODEL(default_search_engines_model_), &iter, | |
| 709 SEARCH_ENGINES_COL_INDEX, &index, | |
| 710 -1); | |
| 711 std::vector<const TemplateURL*> model_urls = | |
| 712 template_url_model_->GetTemplateURLs(); | |
| 713 if (index < model_urls.size()) | |
| 714 template_url_model_->SetDefaultSearchProvider(model_urls[index]); | |
| 715 else | |
| 716 NOTREACHED(); | |
| 717 } | |
| 718 | |
| 719 void GeneralPageGtk::EnableDefaultSearchEngineComboBox(bool enable) { | |
| 720 gtk_widget_set_sensitive(default_search_engine_combobox_, enable); | |
| 721 } | |
| 722 | |
| 723 void GeneralPageGtk::UpdateHomepagePrefs() { | |
| 724 const GURL& homepage = URLFixerUpper::FixupURL( | |
| 725 gtk_entry_get_text(GTK_ENTRY(homepage_use_url_entry_)), std::string()); | |
| 726 bool new_tab_page_is_home_page = | |
| 727 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(homepage_use_newtab_radio_)); | |
| 728 if (IsNewTabUIURLString(homepage)) { | |
| 729 new_tab_page_is_home_page = true; | |
| 730 homepage_.SetValueIfNotManaged(std::string()); | |
| 731 } else if (!homepage.is_valid()) { | |
| 732 new_tab_page_is_home_page = true; | |
| 733 if (!homepage.has_host()) | |
| 734 homepage_.SetValueIfNotManaged(std::string()); | |
| 735 } else { | |
| 736 homepage_.SetValueIfNotManaged(homepage.spec()); | |
| 737 } | |
| 738 new_tab_page_is_home_page_.SetValueIfNotManaged(new_tab_page_is_home_page); | |
| 739 } | |
| 740 | |
| 741 void GeneralPageGtk::UpdateHomepageIsNewTabRadio(bool homepage_is_new_tab, | |
| 742 bool enabled) { | |
| 743 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(homepage_use_newtab_radio_), | |
| 744 homepage_is_new_tab); | |
| 745 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(homepage_use_url_radio_), | |
| 746 !homepage_is_new_tab); | |
| 747 gtk_widget_set_sensitive(homepage_use_newtab_radio_, enabled); | |
| 748 gtk_widget_set_sensitive(homepage_use_url_radio_, enabled); | |
| 749 } | |
| 750 | |
| 751 void GeneralPageGtk::EnableHomepageURLField(bool enabled) { | |
| 752 if (homepage_.IsManaged()) | |
| 753 enabled = false; | |
| 754 gtk_widget_set_sensitive(homepage_use_url_entry_, enabled); | |
| 755 } | |
| 756 | |
| 757 void GeneralPageGtk::EnableCustomHomepagesControls(bool enable) { | |
| 758 gtk_widget_set_sensitive(startup_add_custom_page_button_, enable); | |
| 759 gtk_widget_set_sensitive(startup_remove_custom_page_button_, | |
| 760 enable && | |
| 761 gtk_tree_selection_count_selected_rows(startup_custom_pages_selection_)); | |
| 762 gtk_widget_set_sensitive(startup_use_current_page_button_, enable); | |
| 763 gtk_widget_set_sensitive(startup_custom_pages_tree_, enable); | |
| 764 } | |
| 765 | |
| 766 void GeneralPageGtk::SetDefaultBrowserUIState( | |
| 767 ShellIntegration::DefaultBrowserUIState state) { | |
| 768 const char* color = NULL; | |
| 769 std::string text; | |
| 770 if (state == ShellIntegration::STATE_IS_DEFAULT) { | |
| 771 color = kDefaultBrowserLabelColor; | |
| 772 text = l10n_util::GetStringFUTF8(IDS_OPTIONS_DEFAULTBROWSER_DEFAULT, | |
| 773 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); | |
| 774 } else if (state == ShellIntegration::STATE_NOT_DEFAULT) { | |
| 775 color = kNotDefaultBrowserLabelColor; | |
| 776 text = l10n_util::GetStringFUTF8(IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT, | |
| 777 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); | |
| 778 } else if (state == ShellIntegration::STATE_UNKNOWN) { | |
| 779 color = kNotDefaultBrowserLabelColor; | |
| 780 text = l10n_util::GetStringFUTF8(IDS_OPTIONS_DEFAULTBROWSER_UNKNOWN, | |
| 781 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); | |
| 782 } | |
| 783 if (color) { | |
| 784 char* markup = g_markup_printf_escaped(kDefaultBrowserLabelMarkup, | |
| 785 color, text.c_str()); | |
| 786 gtk_label_set_markup(GTK_LABEL(default_browser_status_label_), markup); | |
| 787 g_free(markup); | |
| 788 } | |
| 789 | |
| 790 gtk_widget_set_sensitive(default_browser_use_as_default_button_, | |
| 791 state == ShellIntegration::STATE_NOT_DEFAULT); | |
| 792 } | |
| 793 | |
| 794 void GeneralPageGtk::OnInstantLabelSizeAllocate(GtkWidget* sender, | |
| 795 GtkAllocation* allocation) { | |
| 796 int desired_width = allocation->x - sender->parent->allocation.x; | |
| 797 GtkRequisition req; | |
| 798 gtk_widget_size_request(instant_indent_, &req); | |
| 799 if (req.width != desired_width) | |
| 800 gtk_widget_set_size_request(instant_indent_, desired_width, -1); | |
| 801 } | |
| 802 | |
| 803 void GeneralPageGtk::OnSearchLearnMoreClicked(GtkWidget* sender) { | |
| 804 browser::ShowOptionsURL(profile(), browser::InstantLearnMoreURL()); | |
| 805 } | |
| OLD | NEW |