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