OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/gtk/options/content_exceptions_window_gtk.h" | 5 #include "chrome/browser/gtk/options/content_exceptions_window_gtk.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "app/l10n_util.h" | 9 #include "app/l10n_util.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
11 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
12 #include "chrome/browser/gtk/gtk_util.h" | 12 #include "chrome/browser/gtk/gtk_util.h" |
13 #include "chrome/browser/gtk/options/content_exception_editor.h" | 13 #include "chrome/browser/gtk/options/content_exception_editor.h" |
14 #include "gfx/gtk_util.h" | 14 #include "gfx/gtk_util.h" |
15 #include "grit/generated_resources.h" | 15 #include "grit/generated_resources.h" |
16 #include "grit/locale_settings.h" | 16 #include "grit/locale_settings.h" |
17 | 17 |
18 namespace { | 18 namespace { |
19 | 19 |
20 // Singletons for each possible exception window. | 20 // Singletons for each possible exception window. |
21 ContentExceptionsWindowGtk* instances[CONTENT_SETTINGS_NUM_TYPES] = { NULL }; | 21 ContentExceptionsWindowGtk* instances[CONTENT_SETTINGS_NUM_TYPES] = { NULL }; |
22 | 22 |
23 } // namespace | 23 } // namespace |
24 | 24 |
25 // static | 25 // static |
26 void ContentExceptionsWindowGtk::ShowExceptionsWindow( | 26 void ContentExceptionsWindowGtk::ShowExceptionsWindow( |
27 GtkWindow* parent, | 27 GtkWindow* parent, |
28 HostContentSettingsMap* map, | 28 HostContentSettingsMap* map, |
| 29 HostContentSettingsMap* off_the_record_map, |
29 ContentSettingsType type) { | 30 ContentSettingsType type) { |
30 DCHECK(map); | 31 DCHECK(map); |
31 DCHECK(type < CONTENT_SETTINGS_NUM_TYPES); | 32 DCHECK(type < CONTENT_SETTINGS_NUM_TYPES); |
32 // Geolocation exceptions are handled by GeolocationContentExceptionsWindow. | 33 // Geolocation exceptions are handled by GeolocationContentExceptionsWindow. |
33 DCHECK(type != CONTENT_SETTINGS_TYPE_GEOLOCATION); | 34 DCHECK(type != CONTENT_SETTINGS_TYPE_GEOLOCATION); |
34 | 35 |
35 if (!instances[type]) { | 36 if (!instances[type]) { |
36 // Create the options window. | 37 // Create the options window. |
37 instances[type] = new ContentExceptionsWindowGtk(parent, map, type); | 38 instances[type] = |
| 39 new ContentExceptionsWindowGtk(parent, map, off_the_record_map, type); |
38 } else { | 40 } else { |
39 gtk_util::PresentWindow(instances[type]->dialog_, 0); | 41 gtk_util::PresentWindow(instances[type]->dialog_, 0); |
40 } | 42 } |
41 } | 43 } |
42 | 44 |
43 ContentExceptionsWindowGtk::~ContentExceptionsWindowGtk() { | 45 ContentExceptionsWindowGtk::~ContentExceptionsWindowGtk() { |
44 } | 46 } |
45 | 47 |
46 ContentExceptionsWindowGtk::ContentExceptionsWindowGtk( | 48 ContentExceptionsWindowGtk::ContentExceptionsWindowGtk( |
47 GtkWindow* parent, | 49 GtkWindow* parent, |
48 HostContentSettingsMap* map, | 50 HostContentSettingsMap* map, |
49 ContentSettingsType type) { | 51 HostContentSettingsMap* off_the_record_map, |
| 52 ContentSettingsType type) |
| 53 : allow_off_the_record_(off_the_record_map) { |
50 // Build the model adapters that translate views and TableModels into | 54 // Build the model adapters that translate views and TableModels into |
51 // something GTK can use. | 55 // something GTK can use. |
52 list_store_ = gtk_list_store_new(COL_COUNT, G_TYPE_STRING, G_TYPE_STRING); | 56 list_store_ = gtk_list_store_new( |
| 57 COL_COUNT, G_TYPE_STRING, G_TYPE_STRING, PANGO_TYPE_STYLE); |
53 treeview_ = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store_)); | 58 treeview_ = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store_)); |
54 g_object_unref(list_store_); | 59 g_object_unref(list_store_); |
55 | 60 |
56 // Set up the properties of the treeview | 61 // Set up the properties of the treeview |
57 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview_), TRUE); | 62 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview_), TRUE); |
58 g_signal_connect(treeview_, "row-activated", | 63 g_signal_connect(treeview_, "row-activated", |
59 G_CALLBACK(OnTreeViewRowActivateThunk), this); | 64 G_CALLBACK(OnTreeViewRowActivateThunk), this); |
60 | 65 |
61 GtkTreeViewColumn* pattern_column = gtk_tree_view_column_new_with_attributes( | 66 GtkTreeViewColumn* pattern_column = gtk_tree_view_column_new_with_attributes( |
62 l10n_util::GetStringUTF8(IDS_EXCEPTIONS_PATTERN_HEADER).c_str(), | 67 l10n_util::GetStringUTF8(IDS_EXCEPTIONS_PATTERN_HEADER).c_str(), |
63 gtk_cell_renderer_text_new(), | 68 gtk_cell_renderer_text_new(), |
64 "text", COL_PATTERN, | 69 "text", COL_PATTERN, |
| 70 "style", COL_OTR, |
65 NULL); | 71 NULL); |
66 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_), pattern_column); | 72 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_), pattern_column); |
67 gtk_tree_view_column_set_sort_column_id(pattern_column, COL_PATTERN); | 73 gtk_tree_view_column_set_sort_column_id(pattern_column, COL_PATTERN); |
68 | 74 |
69 GtkTreeViewColumn* action_column = gtk_tree_view_column_new_with_attributes( | 75 GtkTreeViewColumn* action_column = gtk_tree_view_column_new_with_attributes( |
70 l10n_util::GetStringUTF8(IDS_EXCEPTIONS_ACTION_HEADER).c_str(), | 76 l10n_util::GetStringUTF8(IDS_EXCEPTIONS_ACTION_HEADER).c_str(), |
71 gtk_cell_renderer_text_new(), | 77 gtk_cell_renderer_text_new(), |
72 "text", COL_ACTION, | 78 "text", COL_ACTION, |
| 79 "style", COL_OTR, |
73 NULL); | 80 NULL); |
74 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_), action_column); | 81 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_), action_column); |
75 gtk_tree_view_column_set_sort_column_id(action_column, COL_ACTION); | 82 gtk_tree_view_column_set_sort_column_id(action_column, COL_ACTION); |
76 | 83 |
77 treeview_selection_ = gtk_tree_view_get_selection( | 84 treeview_selection_ = gtk_tree_view_get_selection( |
78 GTK_TREE_VIEW(treeview_)); | 85 GTK_TREE_VIEW(treeview_)); |
79 gtk_tree_selection_set_mode(treeview_selection_, GTK_SELECTION_MULTIPLE); | 86 gtk_tree_selection_set_mode(treeview_selection_, GTK_SELECTION_MULTIPLE); |
80 g_signal_connect(treeview_selection_, "changed", | 87 g_signal_connect(treeview_selection_, "changed", |
81 G_CALLBACK(OnTreeSelectionChangedThunk), this); | 88 G_CALLBACK(OnTreeSelectionChangedThunk), this); |
82 | 89 |
83 // Bind |list_store_| to our C++ model. | 90 // Bind |list_store_| to our C++ model. |
84 model_.reset(new ContentExceptionsTableModel(map, type)); | 91 model_.reset(new ContentExceptionsTableModel(map, off_the_record_map, type)); |
85 model_adapter_.reset(new gtk_tree::TableAdapter(this, list_store_, | 92 model_adapter_.reset(new gtk_tree::TableAdapter(this, list_store_, |
86 model_.get())); | 93 model_.get())); |
87 // Force a reload of everything to copy data into |list_store_|. | 94 // Force a reload of everything to copy data into |list_store_|. |
88 model_adapter_->OnModelChanged(); | 95 model_adapter_->OnModelChanged(); |
89 | 96 |
90 dialog_ = gtk_dialog_new_with_buttons( | 97 dialog_ = gtk_dialog_new_with_buttons( |
91 GetWindowTitle().c_str(), | 98 GetWindowTitle().c_str(), |
92 parent, | 99 parent, |
93 static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR), | 100 static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR), |
94 GTK_STOCK_CLOSE, | 101 GTK_STOCK_CLOSE, |
95 GTK_RESPONSE_CLOSE, | 102 GTK_RESPONSE_CLOSE, |
96 NULL); | 103 NULL); |
97 gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, -1); | 104 gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, -1); |
98 // Allow browser windows to go in front of the options dialog in metacity. | 105 // Allow browser windows to go in front of the options dialog in metacity. |
99 gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL); | 106 gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL); |
100 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox), | 107 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox), |
101 gtk_util::kContentAreaSpacing); | 108 gtk_util::kContentAreaSpacing); |
102 | 109 |
103 GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing); | 110 GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing); |
104 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), hbox); | 111 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), hbox); |
105 | 112 |
| 113 GtkWidget* treeview_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); |
| 114 |
106 // Create a scrolled window to wrap the treeview widget. | 115 // Create a scrolled window to wrap the treeview widget. |
107 GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL); | 116 GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL); |
108 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), | 117 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), |
109 GTK_SHADOW_ETCHED_IN); | 118 GTK_SHADOW_ETCHED_IN); |
110 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), | 119 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), |
111 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | 120 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
112 gtk_container_add(GTK_CONTAINER(scrolled), treeview_); | 121 gtk_container_add(GTK_CONTAINER(scrolled), treeview_); |
113 gtk_box_pack_start(GTK_BOX(hbox), scrolled, TRUE, TRUE, 0); | 122 gtk_box_pack_start(GTK_BOX(treeview_box), scrolled, TRUE, TRUE, 0); |
| 123 |
| 124 // If we also have an OTR profile, inform the user that OTR exceptions are |
| 125 // displayed in italics. |
| 126 if (allow_off_the_record_) { |
| 127 GtkWidget* incognito_label = gtk_label_new( |
| 128 l10n_util::GetStringUTF8(IDS_EXCEPTIONS_OTR_IN_ITALICS).c_str()); |
| 129 PangoAttrList* attributes = pango_attr_list_new(); |
| 130 pango_attr_list_insert(attributes, |
| 131 pango_attr_style_new(PANGO_STYLE_ITALIC)); |
| 132 gtk_label_set_attributes(GTK_LABEL(incognito_label), attributes); |
| 133 pango_attr_list_unref(attributes); |
| 134 gtk_misc_set_alignment(GTK_MISC(incognito_label), 0, 0); |
| 135 gtk_box_pack_start(GTK_BOX(treeview_box), incognito_label, FALSE, FALSE, 0); |
| 136 } |
| 137 |
| 138 gtk_box_pack_start(GTK_BOX(hbox), treeview_box, TRUE, TRUE, 0); |
114 | 139 |
115 GtkWidget* button_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | 140 GtkWidget* button_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); |
116 | 141 |
117 GtkWidget* add_button = gtk_util::BuildDialogButton(dialog_, | 142 GtkWidget* add_button = gtk_util::BuildDialogButton(dialog_, |
118 IDS_EXCEPTIONS_ADD_BUTTON, | 143 IDS_EXCEPTIONS_ADD_BUTTON, |
119 GTK_STOCK_ADD); | 144 GTK_STOCK_ADD); |
120 g_signal_connect(add_button, "clicked", G_CALLBACK(AddThunk), this); | 145 g_signal_connect(add_button, "clicked", G_CALLBACK(AddThunk), this); |
121 gtk_box_pack_start(GTK_BOX(button_box), add_button, FALSE, FALSE, 0); | 146 gtk_box_pack_start(GTK_BOX(button_box), add_button, FALSE, FALSE, 0); |
122 | 147 |
123 edit_button_ = gtk_util::BuildDialogButton(dialog_, | 148 edit_button_ = gtk_util::BuildDialogButton(dialog_, |
(...skipping 30 matching lines...) Expand all Loading... |
154 } | 179 } |
155 | 180 |
156 void ContentExceptionsWindowGtk::SetColumnValues(int row, GtkTreeIter* iter) { | 181 void ContentExceptionsWindowGtk::SetColumnValues(int row, GtkTreeIter* iter) { |
157 std::wstring pattern = model_->GetText(row, IDS_EXCEPTIONS_PATTERN_HEADER); | 182 std::wstring pattern = model_->GetText(row, IDS_EXCEPTIONS_PATTERN_HEADER); |
158 gtk_list_store_set(list_store_, iter, COL_PATTERN, | 183 gtk_list_store_set(list_store_, iter, COL_PATTERN, |
159 WideToUTF8(pattern).c_str(), -1); | 184 WideToUTF8(pattern).c_str(), -1); |
160 | 185 |
161 std::wstring action = model_->GetText(row, IDS_EXCEPTIONS_ACTION_HEADER); | 186 std::wstring action = model_->GetText(row, IDS_EXCEPTIONS_ACTION_HEADER); |
162 gtk_list_store_set(list_store_, iter, COL_ACTION, | 187 gtk_list_store_set(list_store_, iter, COL_ACTION, |
163 WideToUTF8(action).c_str(), -1); | 188 WideToUTF8(action).c_str(), -1); |
| 189 |
| 190 bool is_off_the_record = model_->entry_is_off_the_record(row); |
| 191 PangoStyle style = |
| 192 is_off_the_record ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL; |
| 193 gtk_list_store_set(list_store_, iter, COL_OTR, style, -1); |
164 } | 194 } |
165 | 195 |
166 void ContentExceptionsWindowGtk::AcceptExceptionEdit( | 196 void ContentExceptionsWindowGtk::AcceptExceptionEdit( |
167 const HostContentSettingsMap::Pattern& pattern, | 197 const HostContentSettingsMap::Pattern& pattern, |
168 ContentSetting setting, | 198 ContentSetting setting, |
| 199 bool is_off_the_record, |
169 int index, | 200 int index, |
170 bool is_new) { | 201 bool is_new) { |
| 202 DCHECK(!is_off_the_record || allow_off_the_record_); |
| 203 |
171 if (!is_new) | 204 if (!is_new) |
172 model_->RemoveException(index); | 205 model_->RemoveException(index); |
173 | 206 |
174 model_->AddException(pattern, setting); | 207 model_->AddException(pattern, setting, is_off_the_record); |
175 | 208 |
176 int new_index = model_->IndexOfExceptionByPattern(pattern); | 209 int new_index = model_->IndexOfExceptionByPattern(pattern, is_off_the_record); |
177 DCHECK_NE(-1, new_index); | 210 DCHECK_NE(-1, new_index); |
178 | 211 |
179 gtk_tree::SelectAndFocusRowNum(new_index, GTK_TREE_VIEW(treeview_)); | 212 gtk_tree::SelectAndFocusRowNum(new_index, GTK_TREE_VIEW(treeview_)); |
180 | 213 |
181 UpdateButtonState(); | 214 UpdateButtonState(); |
182 } | 215 } |
183 | 216 |
184 void ContentExceptionsWindowGtk::UpdateButtonState() { | 217 void ContentExceptionsWindowGtk::UpdateButtonState() { |
185 int num_selected = gtk_tree_selection_count_selected_rows( | 218 int num_selected = gtk_tree_selection_count_selected_rows( |
186 treeview_selection_); | 219 treeview_selection_); |
187 int row_count = gtk_tree_model_iter_n_children( | 220 int row_count = gtk_tree_model_iter_n_children( |
188 GTK_TREE_MODEL(list_store_), NULL); | 221 GTK_TREE_MODEL(list_store_), NULL); |
189 | 222 |
190 // TODO(erg): http://crbug.com/34177 , support editing of more than one entry | 223 // TODO(erg): http://crbug.com/34177 , support editing of more than one entry |
191 // at a time. | 224 // at a time. |
192 gtk_widget_set_sensitive(edit_button_, num_selected == 1); | 225 gtk_widget_set_sensitive(edit_button_, num_selected == 1); |
193 gtk_widget_set_sensitive(remove_button_, num_selected >= 1); | 226 gtk_widget_set_sensitive(remove_button_, num_selected >= 1); |
194 gtk_widget_set_sensitive(remove_all_button_, row_count > 0); | 227 gtk_widget_set_sensitive(remove_all_button_, row_count > 0); |
195 } | 228 } |
196 | 229 |
197 void ContentExceptionsWindowGtk::Add(GtkWidget* widget) { | 230 void ContentExceptionsWindowGtk::Add(GtkWidget* widget) { |
198 new ContentExceptionEditor(GTK_WINDOW(dialog_), | 231 new ContentExceptionEditor(GTK_WINDOW(dialog_), |
199 this, model_.get(), -1, | 232 this, model_.get(), allow_off_the_record_, -1, |
200 HostContentSettingsMap::Pattern(), | 233 HostContentSettingsMap::Pattern(), |
201 CONTENT_SETTING_BLOCK); | 234 CONTENT_SETTING_BLOCK, false); |
202 } | 235 } |
203 | 236 |
204 void ContentExceptionsWindowGtk::Edit(GtkWidget* widget) { | 237 void ContentExceptionsWindowGtk::Edit(GtkWidget* widget) { |
205 std::set<int> indices; | 238 std::set<int> indices; |
206 gtk_tree::GetSelectedIndices(treeview_selection_, &indices); | 239 gtk_tree::GetSelectedIndices(treeview_selection_, &indices); |
207 DCHECK_GT(indices.size(), 0u); | 240 DCHECK_GT(indices.size(), 0u); |
208 int index = *indices.begin(); | 241 int index = *indices.begin(); |
209 const HostContentSettingsMap::PatternSettingPair& entry = | 242 const HostContentSettingsMap::PatternSettingPair& entry = |
210 model_->entry_at(index); | 243 model_->entry_at(index); |
211 new ContentExceptionEditor(GTK_WINDOW(dialog_), this, model_.get(), index, | 244 new ContentExceptionEditor(GTK_WINDOW(dialog_), this, model_.get(), |
212 entry.first, entry.second); | 245 allow_off_the_record_, index, |
| 246 entry.first, entry.second, |
| 247 model_->entry_is_off_the_record(index)); |
213 } | 248 } |
214 | 249 |
215 void ContentExceptionsWindowGtk::Remove(GtkWidget* widget) { | 250 void ContentExceptionsWindowGtk::Remove(GtkWidget* widget) { |
216 std::set<int> selected_indices; | 251 std::set<int> selected_indices; |
217 gtk_tree::GetSelectedIndices(treeview_selection_, &selected_indices); | 252 gtk_tree::GetSelectedIndices(treeview_selection_, &selected_indices); |
218 | 253 |
219 int selected_row = 0; | 254 int selected_row = 0; |
220 for (std::set<int>::reverse_iterator i = selected_indices.rbegin(); | 255 for (std::set<int>::reverse_iterator i = selected_indices.rbegin(); |
221 i != selected_indices.rend(); ++i) { | 256 i != selected_indices.rend(); ++i) { |
222 model_->RemoveException(*i); | 257 model_->RemoveException(*i); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 | 301 |
267 void ContentExceptionsWindowGtk::OnWindowDestroy(GtkWidget* widget) { | 302 void ContentExceptionsWindowGtk::OnWindowDestroy(GtkWidget* widget) { |
268 instances[model_->content_type()] = NULL; | 303 instances[model_->content_type()] = NULL; |
269 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 304 MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
270 } | 305 } |
271 | 306 |
272 void ContentExceptionsWindowGtk::OnTreeSelectionChanged( | 307 void ContentExceptionsWindowGtk::OnTreeSelectionChanged( |
273 GtkWidget* selection) { | 308 GtkWidget* selection) { |
274 UpdateButtonState(); | 309 UpdateButtonState(); |
275 } | 310 } |
OLD | NEW |