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 |