Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Side by Side Diff: chrome/browser/gtk/options/cookies_view.cc

Issue 159187: Gtk cookie manager part 1.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/gtk/options/cookies_view.h ('k') | chrome/browser/views/options/cookies_view.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Name: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/gtk/options/cookies_view.h"
6
7 #include "app/l10n_util.h"
8 #include "base/gfx/gtk_util.h"
9 #include "base/message_loop.h"
10 #include "base/string_util.h"
11 #include "chrome/browser/cookies_table_model.h"
12 #include "chrome/common/gtk_util.h"
13 #include "grit/generated_resources.h"
14 #include "third_party/skia/include/core/SkBitmap.h"
15
16 namespace {
17
18 // Initial size for dialog.
19 const int kDialogDefaultWidth = 450;
20 const int kDialogDefaultHeight = 450;
21
22 // Delay after entering filter text before filtering occurs.
23 const int kSearchFilterDelayMs = 500;
24
25 // Response ids for our custom buttons.
26 enum {
27 RESPONSE_REMOVE = 1,
28 RESPONSE_REMOVE_ALL
29 };
30
31 // Column ids for |list_store_|.
32 enum {
33 COL_ICON,
34 COL_SITE,
35 COL_COOKIE_NAME,
36 COL_COUNT,
37 };
38
39 // The currently open cookie manager, if any.
40 CookiesView* instance_ = NULL;
41
42 // TODO(mattm): These functions are also in url_picker_dialog_gtk. Move them to
43 // some sort of gtk table model helper?
44 // Get the row number corresponding to |path|.
45 gint GetRowNumForPath(GtkTreePath* path) {
46 gint* indices = gtk_tree_path_get_indices(path);
47 if (!indices) {
48 NOTREACHED();
49 return -1;
50 }
51 return indices[0];
52 }
53
54 // Get the row number corresponding to |iter|.
55 gint GetRowNumForIter(GtkTreeModel* model, GtkTreeIter* iter) {
56 GtkTreePath* path = gtk_tree_model_get_path(model, iter);
57 int row = GetRowNumForPath(path);
58 gtk_tree_path_free(path);
59 return row;
60 }
61
62 // Get the row number in the child tree model corresponding to |sort_path| in
63 // the parent tree model.
64 gint GetTreeSortChildRowNumForPath(GtkTreeModel* sort_model,
65 GtkTreePath* sort_path) {
66 GtkTreePath *child_path = gtk_tree_model_sort_convert_path_to_child_path(
67 GTK_TREE_MODEL_SORT(sort_model), sort_path);
68 int row = GetRowNumForPath(child_path);
69 gtk_tree_path_free(child_path);
70 return row;
71 }
72
73 } // namespace
74
75 CookiesView::~CookiesView() {
76 }
77
78 // static
79 void CookiesView::Show(Profile* profile) {
80 DCHECK(profile);
81
82 // If there's already an existing editor window, activate it.
83 if (instance_) {
84 gtk_window_present(GTK_WINDOW(instance_->dialog_));
85 } else {
86 instance_ = new CookiesView(profile);
87 }
88 }
89
90 CookiesView::CookiesView(Profile* profile)
91 : profile_(profile),
92 filter_update_factory_(this) {
93 Init();
94 }
95
96 void CookiesView::Init() {
97 dialog_ = gtk_dialog_new_with_buttons(
98 l10n_util::GetStringUTF8(IDS_COOKIES_WINDOW_TITLE).c_str(),
99 NULL,
100 GTK_DIALOG_NO_SEPARATOR,
101 GTK_STOCK_CLOSE,
102 GTK_RESPONSE_CLOSE,
103 NULL);
104
105 remove_button_ = gtk_dialog_add_button(
106 GTK_DIALOG(dialog_),
107 gtk_util::ConvertAcceleratorsFromWindowsStyle(
108 l10n_util::GetStringUTF8(IDS_COOKIES_REMOVE_LABEL)).c_str(),
109 RESPONSE_REMOVE);
110 gtk_button_box_set_child_secondary(
111 GTK_BUTTON_BOX(GTK_DIALOG(dialog_)->action_area),
112 remove_button_,
113 TRUE);
114
115 remove_all_button_ = gtk_dialog_add_button(
116 GTK_DIALOG(dialog_),
117 gtk_util::ConvertAcceleratorsFromWindowsStyle(
118 l10n_util::GetStringUTF8(IDS_COOKIES_REMOVE_ALL_LABEL)).c_str(),
119 RESPONSE_REMOVE_ALL);
120 gtk_button_box_set_child_secondary(
121 GTK_BUTTON_BOX(GTK_DIALOG(dialog_)->action_area),
122 remove_all_button_,
123 TRUE);
124
125 gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_CLOSE);
126 gtk_window_set_default_size(GTK_WINDOW(dialog_), kDialogDefaultWidth,
127 kDialogDefaultHeight);
128 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
129 gtk_util::kContentAreaSpacing);
130 g_signal_connect(dialog_, "response", G_CALLBACK(OnResponse), this);
131 g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this);
132
133 // Filtering controls.
134 GtkWidget* filter_hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
135 filter_entry_ = gtk_entry_new();
136 g_signal_connect(G_OBJECT(filter_entry_), "activate",
137 G_CALLBACK(OnFilterEntryActivated), this);
138 g_signal_connect(G_OBJECT(filter_entry_), "changed",
139 G_CALLBACK(OnFilterEntryChanged), this);
140 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_entry_,
141 TRUE, TRUE, 0);
142 filter_clear_button_ = gtk_button_new_with_mnemonic(
143 gtk_util::ConvertAcceleratorsFromWindowsStyle(
144 l10n_util::GetStringUTF8(IDS_COOKIES_CLEAR_SEARCH_LABEL)).c_str());
145 g_signal_connect(G_OBJECT(filter_clear_button_), "clicked",
146 G_CALLBACK(OnFilterClearButtonClicked), this);
147 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_clear_button_,
148 FALSE, FALSE, 0);
149
150 GtkWidget* filter_controls = gtk_util::CreateLabeledControlsGroup(NULL,
151 l10n_util::GetStringUTF8(IDS_COOKIES_SEARCH_LABEL).c_str(), filter_hbox,
152 NULL);
153 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), filter_controls,
154 FALSE, FALSE, 0);
155
156 // Cookie list.
157 GtkWidget* cookie_list_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
158 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), cookie_list_vbox,
159 TRUE, TRUE, 0);
160
161 GtkWidget* description_label = gtk_label_new(
162 l10n_util::GetStringUTF8(IDS_COOKIES_INFO_LABEL).c_str());
163 GtkWidget* description_label_alignment = gtk_alignment_new(
164 0.0, 0.5, 0.0, 0.0);
165 gtk_container_add(GTK_CONTAINER(description_label_alignment),
166 description_label);
167 gtk_box_pack_start(GTK_BOX(cookie_list_vbox), description_label_alignment,
168 FALSE, FALSE, 0);
169
170 GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
171 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
172 GTK_POLICY_AUTOMATIC,
173 GTK_POLICY_AUTOMATIC);
174 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
175 GTK_SHADOW_ETCHED_IN);
176 gtk_box_pack_start(GTK_BOX(cookie_list_vbox), scroll_window, TRUE, TRUE, 0);
177
178 list_store_ = gtk_list_store_new(COL_COUNT,
179 GDK_TYPE_PIXBUF,
180 G_TYPE_STRING,
181 G_TYPE_STRING);
182 list_sort_ = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(list_store_));
183 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(list_sort_),
184 COL_SITE, CompareSite, this, NULL);
185 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(list_sort_),
186 COL_COOKIE_NAME, CompareCookieName, this,
187 NULL);
188 tree_ = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_sort_));
189 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_), TRUE);
190 gtk_container_add(GTK_CONTAINER(scroll_window), tree_);
191
192 GtkTreeViewColumn* site_column = gtk_tree_view_column_new();
193 GtkCellRenderer* pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
194 gtk_tree_view_column_pack_start(site_column, pixbuf_renderer, FALSE);
195 gtk_tree_view_column_add_attribute(site_column, pixbuf_renderer, "pixbuf",
196 COL_ICON);
197 GtkCellRenderer* site_renderer = gtk_cell_renderer_text_new();
198 gtk_tree_view_column_pack_start(site_column, site_renderer, TRUE);
199 gtk_tree_view_column_add_attribute(site_column, site_renderer, "text",
200 COL_SITE);
201 gtk_tree_view_column_set_title(
202 site_column, l10n_util::GetStringUTF8(
203 IDS_COOKIES_DOMAIN_COLUMN_HEADER).c_str());
204 gtk_tree_view_column_set_sort_column_id(site_column, COL_SITE);
205 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), site_column);
206
207 GtkTreeViewColumn* name_column = gtk_tree_view_column_new_with_attributes(
208 l10n_util::GetStringUTF8(
209 IDS_COOKIES_NAME_COLUMN_HEADER).c_str(),
210 gtk_cell_renderer_text_new(),
211 "text", COL_COOKIE_NAME,
212 NULL);
213 gtk_tree_view_column_set_sort_column_id(name_column, COL_COOKIE_NAME);
214 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), name_column);
215
216 selection_ = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_));
217 gtk_tree_selection_set_mode(selection_, GTK_SELECTION_MULTIPLE);
218 g_signal_connect(G_OBJECT(selection_), "changed",
219 G_CALLBACK(OnSelectionChanged), this);
220
221 // Initialize model.
222 cookies_table_model_.reset(new CookiesTableModel(profile_));
223 cookies_table_model_->SetObserver(this);
224 OnModelChanged();
225
226 // Show dialog.
227 EnableControls();
228 gtk_widget_show_all(dialog_);
229 }
230
231 void CookiesView::EnableControls() {
232 gtk_widget_set_sensitive(
233 remove_button_, gtk_tree_selection_count_selected_rows(selection_) > 0);
234 gtk_widget_set_sensitive(
235 remove_all_button_, cookies_table_model_->RowCount() > 0);
236
237 const gchar* filter_text = gtk_entry_get_text(GTK_ENTRY(filter_entry_));
238 gtk_widget_set_sensitive(filter_clear_button_, filter_text && *filter_text);
239 }
240
241 void CookiesView::RemoveSelectedCookies() {
242 GList* list = gtk_tree_selection_get_selected_rows(selection_, NULL);
243 std::vector<int> selected_rows(
244 gtk_tree_selection_count_selected_rows(selection_));
245 GList* node;
246 size_t i;
247 for (i = 0, node = list; node != NULL; ++i, node = node->next) {
248 selected_rows[i] = GetTreeSortChildRowNumForPath(
249 list_sort_, static_cast<GtkTreePath*>(node->data));
250 }
251 g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL);
252 g_list_free(list);
253
254 for (std::vector<int>::reverse_iterator selected = selected_rows.rbegin();
255 selected != selected_rows.rend(); ++selected) {
256 cookies_table_model_->RemoveCookies(*selected, 1);
257 }
258 }
259
260 void CookiesView::SetColumnValues(int row, GtkTreeIter* iter) {
261 SkBitmap bitmap = cookies_table_model_->GetIcon(row);
262 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
263 std::wstring site = cookies_table_model_->GetText(
264 row, IDS_COOKIES_DOMAIN_COLUMN_HEADER);
265 std::wstring name = cookies_table_model_->GetText(
266 row, IDS_COOKIES_NAME_COLUMN_HEADER);
267 gtk_list_store_set(list_store_, iter,
268 COL_ICON, pixbuf,
269 COL_SITE, WideToUTF8(site).c_str(),
270 COL_COOKIE_NAME, WideToUTF8(name).c_str(),
271 -1);
272 g_object_unref(pixbuf);
273 }
274
275 void CookiesView::AddNodeToList(int row) {
276 GtkTreeIter iter;
277 if (row == 0) {
278 gtk_list_store_prepend(list_store_, &iter);
279 } else {
280 GtkTreeIter sibling;
281 gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &sibling,
282 NULL, row - 1);
283 gtk_list_store_insert_after(list_store_, &iter, &sibling);
284 }
285
286 SetColumnValues(row, &iter);
287 }
288
289 void CookiesView::OnModelChanged() {
290 gtk_list_store_clear(list_store_);
291 for (int i = 0; i < cookies_table_model_->RowCount(); ++i)
292 AddNodeToList(i);
293 }
294
295 void CookiesView::OnItemsChanged(int start, int length) {
296 GtkTreeIter iter;
297 bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_),
298 &iter, NULL, start);
299 for (int i = 0; i < length; ++i) {
300 if (!rv) {
301 NOTREACHED();
302 return;
303 }
304 SetColumnValues(start + i, &iter);
305 rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter);
306 }
307 }
308
309 void CookiesView::OnItemsAdded(int start, int length) {
310 NOTREACHED();
311 }
312
313 void CookiesView::OnItemsRemoved(int start, int length) {
314 for (int i = 0; i < length; ++i) {
315 GtkTreeIter iter;
316 if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &iter,
317 NULL, start)) {
318 NOTREACHED();
319 return;
320 }
321 gtk_list_store_remove(list_store_, &iter);
322 }
323 }
324
325 // static
326 gint CookiesView::CompareSite(GtkTreeModel* model, GtkTreeIter* a,
327 GtkTreeIter* b, gpointer window) {
328 int row1 = GetRowNumForIter(model, a);
329 int row2 = GetRowNumForIter(model, b);
330 return reinterpret_cast<CookiesView*>(window)->cookies_table_model_->
331 CompareValues(row1, row2, IDS_COOKIES_DOMAIN_COLUMN_HEADER);
332 }
333
334 // static
335 gint CookiesView::CompareCookieName(GtkTreeModel* model, GtkTreeIter* a,
336 GtkTreeIter* b, gpointer window) {
337 int row1 = GetRowNumForIter(model, a);
338 int row2 = GetRowNumForIter(model, b);
339 return reinterpret_cast<CookiesView*>(window)->cookies_table_model_->
340 CompareValues(row1, row2, IDS_COOKIES_NAME_COLUMN_HEADER);
341 }
342
343 // static
344 void CookiesView::OnResponse(GtkDialog* dialog, int response_id,
345 CookiesView* window) {
346 if (response_id == RESPONSE_REMOVE) {
347 window->RemoveSelectedCookies();
348 } else if (response_id == RESPONSE_REMOVE_ALL) {
349 window->cookies_table_model_->RemoveAllShownCookies();
350 } else {
351 gtk_widget_destroy(window->dialog_);
352 }
353 }
354
355 // static
356 void CookiesView::OnWindowDestroy(GtkWidget* widget, CookiesView* window) {
357 instance_ = NULL;
358 MessageLoop::current()->DeleteSoon(FROM_HERE, window);
359 }
360
361 // static
362 void CookiesView::OnSelectionChanged(GtkTreeSelection *selection,
363 CookiesView* window) {
364 window->EnableControls();
365 }
366
367 void CookiesView::UpdateFilterResults() {
368 const gchar* text = gtk_entry_get_text(GTK_ENTRY(filter_entry_));
369 if (text)
370 cookies_table_model_->UpdateSearchResults(UTF8ToWide(text));
371 }
372
373 // static
374 void CookiesView::OnFilterEntryActivated(GtkEntry* entry, CookiesView* window) {
375 window->filter_update_factory_.RevokeAll();
376 window->UpdateFilterResults();
377 }
378
379 // static
380 void CookiesView::OnFilterEntryChanged(GtkEditable* editable,
381 CookiesView* window) {
382 window->filter_update_factory_.RevokeAll();
383 MessageLoop::current()->PostDelayedTask(FROM_HERE,
384 window->filter_update_factory_.NewRunnableMethod(
385 &CookiesView::UpdateFilterResults), kSearchFilterDelayMs);
386 window->EnableControls();
387 }
388
389 // static
390 void CookiesView::OnFilterClearButtonClicked(GtkButton* button,
391 CookiesView* window) {
392 gtk_entry_set_text(GTK_ENTRY(window->filter_entry_), "");
393 window->filter_update_factory_.RevokeAll();
394 window->UpdateFilterResults();
395 }
OLDNEW
« no previous file with comments | « chrome/browser/gtk/options/cookies_view.h ('k') | chrome/browser/views/options/cookies_view.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698