| 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 |