| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/gtk/keyword_editor_view.h" | |
| 6 | |
| 7 #include <string> | |
| 8 | |
| 9 #include "app/l10n_util.h" | |
| 10 #include "base/message_loop.h" | |
| 11 #include "base/utf_string_conversions.h" | |
| 12 #include "chrome/browser/gtk/accessible_widget_helper_gtk.h" | |
| 13 #include "chrome/browser/gtk/edit_search_engine_dialog.h" | |
| 14 #include "chrome/browser/gtk/gtk_tree.h" | |
| 15 #include "chrome/browser/gtk/gtk_util.h" | |
| 16 #include "chrome/browser/metrics/user_metrics.h" | |
| 17 #include "chrome/browser/profiles/profile.h" | |
| 18 #include "chrome/browser/search_engines/keyword_editor_controller.h" | |
| 19 #include "chrome/browser/search_engines/template_url.h" | |
| 20 #include "chrome/browser/search_engines/template_url_model.h" | |
| 21 #include "chrome/browser/search_engines/template_url_table_model.h" | |
| 22 #include "gfx/gtk_util.h" | |
| 23 #include "grit/generated_resources.h" | |
| 24 #include "grit/locale_settings.h" | |
| 25 #include "third_party/skia/include/core/SkBitmap.h" | |
| 26 | |
| 27 namespace { | |
| 28 | |
| 29 // How many rows should be added to an index into the |table_model_| to get the | |
| 30 // corresponding row in |list_store_| | |
| 31 const int kFirstGroupRowOffset = 2; | |
| 32 const int kSecondGroupRowOffset = 5; | |
| 33 | |
| 34 KeywordEditorView* instance_ = NULL; | |
| 35 | |
| 36 } // namespace | |
| 37 | |
| 38 // static | |
| 39 void KeywordEditorView::Show(Profile* profile) { | |
| 40 DCHECK(profile); | |
| 41 // If this panel is opened from an Incognito window, closing that window can | |
| 42 // leave this with a stale pointer. Use the original profile instead. | |
| 43 // See http://crbug.com/23359. | |
| 44 profile = profile->GetOriginalProfile(); | |
| 45 if (!profile->GetTemplateURLModel()) | |
| 46 return; | |
| 47 | |
| 48 // If there's already an existing editor window, activate it. | |
| 49 if (instance_) { | |
| 50 gtk_util::PresentWindow(instance_->dialog_, 0); | |
| 51 } else { | |
| 52 instance_ = new KeywordEditorView(profile); | |
| 53 gtk_util::ShowDialogWithLocalizedSize(instance_->dialog_, | |
| 54 IDS_SEARCHENGINES_DIALOG_WIDTH_CHARS, | |
| 55 IDS_SEARCHENGINES_DIALOG_HEIGHT_LINES, | |
| 56 true); | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 void KeywordEditorView::OnEditedKeyword(const TemplateURL* template_url, | |
| 61 const string16& title, | |
| 62 const string16& keyword, | |
| 63 const std::string& url) { | |
| 64 if (template_url) { | |
| 65 controller_->ModifyTemplateURL(template_url, title, keyword, url); | |
| 66 | |
| 67 // Force the make default button to update. | |
| 68 EnableControls(); | |
| 69 } else { | |
| 70 SelectModelRow(controller_->AddTemplateURL(title, keyword, url)); | |
| 71 } | |
| 72 } | |
| 73 | |
| 74 KeywordEditorView::~KeywordEditorView() { | |
| 75 controller_->url_model()->RemoveObserver(this); | |
| 76 } | |
| 77 | |
| 78 KeywordEditorView::KeywordEditorView(Profile* profile) | |
| 79 : profile_(profile), | |
| 80 controller_(new KeywordEditorController(profile)), | |
| 81 table_model_(controller_->table_model()) { | |
| 82 Init(); | |
| 83 } | |
| 84 | |
| 85 void KeywordEditorView::Init() { | |
| 86 std::string dialog_name = | |
| 87 l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_WINDOW_TITLE); | |
| 88 dialog_ = gtk_dialog_new_with_buttons( | |
| 89 dialog_name.c_str(), | |
| 90 NULL, | |
| 91 // Non-modal. | |
| 92 GTK_DIALOG_NO_SEPARATOR, | |
| 93 GTK_STOCK_CLOSE, | |
| 94 GTK_RESPONSE_CLOSE, | |
| 95 NULL); | |
| 96 | |
| 97 accessible_widget_helper_.reset(new AccessibleWidgetHelper( | |
| 98 dialog_, profile_)); | |
| 99 accessible_widget_helper_->SendOpenWindowNotification(dialog_name); | |
| 100 | |
| 101 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox), | |
| 102 gtk_util::kContentAreaSpacing); | |
| 103 | |
| 104 GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing); | |
| 105 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), hbox); | |
| 106 | |
| 107 GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL); | |
| 108 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window), | |
| 109 GTK_POLICY_AUTOMATIC, | |
| 110 GTK_POLICY_AUTOMATIC); | |
| 111 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window), | |
| 112 GTK_SHADOW_ETCHED_IN); | |
| 113 gtk_box_pack_start(GTK_BOX(hbox), scroll_window, TRUE, TRUE, 0); | |
| 114 | |
| 115 list_store_ = gtk_list_store_new(COL_COUNT, | |
| 116 GDK_TYPE_PIXBUF, | |
| 117 G_TYPE_STRING, | |
| 118 G_TYPE_STRING, | |
| 119 G_TYPE_BOOLEAN, | |
| 120 G_TYPE_BOOLEAN, | |
| 121 G_TYPE_INT, | |
| 122 G_TYPE_BOOLEAN); | |
| 123 tree_ = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store_)); | |
| 124 g_object_unref(list_store_); | |
| 125 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_), TRUE); | |
| 126 gtk_tree_view_set_row_separator_func(GTK_TREE_VIEW(tree_), | |
| 127 OnCheckRowIsSeparator, | |
| 128 NULL, NULL); | |
| 129 g_signal_connect(tree_, "row-activated", | |
| 130 G_CALLBACK(OnRowActivated), this); | |
| 131 gtk_container_add(GTK_CONTAINER(scroll_window), tree_); | |
| 132 | |
| 133 GtkTreeViewColumn* title_column = gtk_tree_view_column_new(); | |
| 134 GtkCellRenderer* pixbuf_renderer = gtk_cell_renderer_pixbuf_new(); | |
| 135 gtk_tree_view_column_pack_start(title_column, pixbuf_renderer, FALSE); | |
| 136 gtk_tree_view_column_add_attribute(title_column, pixbuf_renderer, "pixbuf", | |
| 137 COL_FAVICON); | |
| 138 GtkCellRenderer* title_renderer = gtk_cell_renderer_text_new(); | |
| 139 gtk_tree_view_column_pack_start(title_column, title_renderer, TRUE); | |
| 140 gtk_tree_view_column_add_attribute(title_column, title_renderer, "text", | |
| 141 COL_TITLE); | |
| 142 gtk_tree_view_column_add_attribute(title_column, title_renderer, "weight", | |
| 143 COL_WEIGHT); | |
| 144 gtk_tree_view_column_add_attribute(title_column, title_renderer, "weight-set", | |
| 145 COL_WEIGHT_SET); | |
| 146 gtk_tree_view_column_set_title( | |
| 147 title_column, l10n_util::GetStringUTF8( | |
| 148 IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN).c_str()); | |
| 149 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), title_column); | |
| 150 | |
| 151 GtkTreeViewColumn* keyword_column = gtk_tree_view_column_new_with_attributes( | |
| 152 l10n_util::GetStringUTF8( | |
| 153 IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN).c_str(), | |
| 154 gtk_cell_renderer_text_new(), | |
| 155 "text", COL_KEYWORD, | |
| 156 NULL); | |
| 157 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), keyword_column); | |
| 158 | |
| 159 selection_ = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_)); | |
| 160 gtk_tree_selection_set_mode(selection_, GTK_SELECTION_SINGLE); | |
| 161 gtk_tree_selection_set_select_function(selection_, OnSelectionFilter, | |
| 162 NULL, NULL); | |
| 163 g_signal_connect(selection_, "changed", | |
| 164 G_CALLBACK(OnSelectionChanged), this); | |
| 165 | |
| 166 GtkWidget* button_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
| 167 gtk_box_pack_start(GTK_BOX(hbox), button_box, FALSE, FALSE, 0); | |
| 168 | |
| 169 add_button_ = gtk_button_new_with_mnemonic( | |
| 170 gfx::ConvertAcceleratorsFromWindowsStyle( | |
| 171 l10n_util::GetStringUTF8( | |
| 172 IDS_SEARCH_ENGINES_EDITOR_NEW_BUTTON)).c_str()); | |
| 173 g_signal_connect(add_button_, "clicked", | |
| 174 G_CALLBACK(OnAddButtonClicked), this); | |
| 175 gtk_box_pack_start(GTK_BOX(button_box), add_button_, FALSE, FALSE, 0); | |
| 176 | |
| 177 edit_button_ = gtk_button_new_with_label( | |
| 178 l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_EDIT_BUTTON).c_str()); | |
| 179 g_signal_connect(edit_button_, "clicked", | |
| 180 G_CALLBACK(OnEditButtonClicked), this); | |
| 181 gtk_box_pack_start(GTK_BOX(button_box), edit_button_, FALSE, FALSE, 0); | |
| 182 | |
| 183 remove_button_ = gtk_button_new_with_mnemonic( | |
| 184 gfx::ConvertAcceleratorsFromWindowsStyle( | |
| 185 l10n_util::GetStringUTF8( | |
| 186 IDS_SEARCH_ENGINES_EDITOR_REMOVE_BUTTON)).c_str()); | |
| 187 g_signal_connect(remove_button_, "clicked", | |
| 188 G_CALLBACK(OnRemoveButtonClicked), this); | |
| 189 gtk_box_pack_start(GTK_BOX(button_box), remove_button_, FALSE, FALSE, 0); | |
| 190 | |
| 191 make_default_button_ = gtk_button_new_with_label( | |
| 192 l10n_util::GetStringUTF8( | |
| 193 IDS_SEARCH_ENGINES_EDITOR_MAKE_DEFAULT_BUTTON).c_str()); | |
| 194 g_signal_connect(make_default_button_, "clicked", | |
| 195 G_CALLBACK(OnMakeDefaultButtonClicked), this); | |
| 196 gtk_box_pack_start(GTK_BOX(button_box), make_default_button_, FALSE, FALSE, | |
| 197 0); | |
| 198 | |
| 199 controller_->url_model()->AddObserver(this); | |
| 200 table_model_->SetObserver(this); | |
| 201 table_model_->Reload(); | |
| 202 | |
| 203 EnableControls(); | |
| 204 | |
| 205 g_signal_connect(dialog_, "response", G_CALLBACK(OnResponse), this); | |
| 206 g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this); | |
| 207 } | |
| 208 | |
| 209 void KeywordEditorView::EnableControls() { | |
| 210 bool can_edit = false; | |
| 211 bool can_make_default = false; | |
| 212 bool can_remove = false; | |
| 213 int model_row = GetSelectedModelRow(); | |
| 214 if (model_row != -1) { | |
| 215 const TemplateURL* selected_url = controller_->GetTemplateURL(model_row); | |
| 216 can_edit = controller_->CanEdit(selected_url); | |
| 217 can_make_default = controller_->CanMakeDefault(selected_url); | |
| 218 can_remove = controller_->CanRemove(selected_url); | |
| 219 } | |
| 220 gtk_widget_set_sensitive(add_button_, controller_->loaded()); | |
| 221 gtk_widget_set_sensitive(edit_button_, can_edit); | |
| 222 gtk_widget_set_sensitive(remove_button_, can_remove); | |
| 223 gtk_widget_set_sensitive(make_default_button_, can_make_default); | |
| 224 } | |
| 225 | |
| 226 void KeywordEditorView::SetColumnValues(int model_row, GtkTreeIter* iter) { | |
| 227 SkBitmap bitmap = table_model_->GetIcon(model_row); | |
| 228 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap); | |
| 229 gtk_list_store_set( | |
| 230 list_store_, iter, | |
| 231 COL_FAVICON, pixbuf, | |
| 232 // Dunno why, even with COL_WEIGHT_SET to FALSE here, the weight still | |
| 233 // has an effect. So we just set it to normal. | |
| 234 COL_WEIGHT, PANGO_WEIGHT_NORMAL, | |
| 235 COL_WEIGHT_SET, TRUE, | |
| 236 COL_TITLE, UTF16ToUTF8(table_model_->GetText( | |
| 237 model_row, IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN)).c_str(), | |
| 238 COL_KEYWORD, UTF16ToUTF8(table_model_->GetText( | |
| 239 model_row, IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN)).c_str(), | |
| 240 -1); | |
| 241 g_object_unref(pixbuf); | |
| 242 } | |
| 243 | |
| 244 int KeywordEditorView::GetListStoreRowForModelRow(int model_row) const { | |
| 245 if (model_row < model_second_group_index_) | |
| 246 return model_row + kFirstGroupRowOffset; | |
| 247 else | |
| 248 return model_row + kSecondGroupRowOffset; | |
| 249 } | |
| 250 | |
| 251 int KeywordEditorView::GetModelRowForPath(GtkTreePath* path) const { | |
| 252 gint* indices = gtk_tree_path_get_indices(path); | |
| 253 if (!indices) { | |
| 254 NOTREACHED(); | |
| 255 return -1; | |
| 256 } | |
| 257 if (indices[0] >= model_second_group_index_ + kSecondGroupRowOffset) | |
| 258 return indices[0] - kSecondGroupRowOffset; | |
| 259 return indices[0] - kFirstGroupRowOffset; | |
| 260 } | |
| 261 | |
| 262 int KeywordEditorView::GetModelRowForIter(GtkTreeIter* iter) const { | |
| 263 GtkTreePath* path = gtk_tree_model_get_path(GTK_TREE_MODEL(list_store_), | |
| 264 iter); | |
| 265 int model_row = GetModelRowForPath(path); | |
| 266 gtk_tree_path_free(path); | |
| 267 return model_row; | |
| 268 } | |
| 269 | |
| 270 int KeywordEditorView::GetSelectedModelRow() const { | |
| 271 GtkTreeIter iter; | |
| 272 if (!gtk_tree_selection_get_selected(selection_, NULL, &iter)) | |
| 273 return -1; | |
| 274 return GetModelRowForIter(&iter); | |
| 275 } | |
| 276 | |
| 277 void KeywordEditorView::SelectModelRow(int model_row) { | |
| 278 int row = GetListStoreRowForModelRow(model_row); | |
| 279 gtk_tree::SelectAndFocusRowNum(row, GTK_TREE_VIEW(tree_)); | |
| 280 } | |
| 281 | |
| 282 void KeywordEditorView::AddNodeToList(int model_row) { | |
| 283 GtkTreeIter iter; | |
| 284 int row = GetListStoreRowForModelRow(model_row); | |
| 285 if (row == 0) { | |
| 286 gtk_list_store_prepend(list_store_, &iter); | |
| 287 } else { | |
| 288 GtkTreeIter sibling; | |
| 289 gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &sibling, | |
| 290 NULL, row - 1); | |
| 291 gtk_list_store_insert_after(list_store_, &iter, &sibling); | |
| 292 } | |
| 293 | |
| 294 SetColumnValues(model_row, &iter); | |
| 295 } | |
| 296 | |
| 297 void KeywordEditorView::OnModelChanged() { | |
| 298 model_second_group_index_ = table_model_->last_search_engine_index(); | |
| 299 gtk_list_store_clear(list_store_); | |
| 300 | |
| 301 TableModel::Groups groups(table_model_->GetGroups()); | |
| 302 if (groups.size() != 2) { | |
| 303 NOTREACHED(); | |
| 304 return; | |
| 305 } | |
| 306 | |
| 307 GtkTreeIter iter; | |
| 308 // First group title. | |
| 309 gtk_list_store_append(list_store_, &iter); | |
| 310 gtk_list_store_set( | |
| 311 list_store_, &iter, | |
| 312 COL_WEIGHT, PANGO_WEIGHT_BOLD, | |
| 313 COL_WEIGHT_SET, TRUE, | |
| 314 COL_TITLE, UTF16ToUTF8(groups[0].title).c_str(), | |
| 315 COL_IS_HEADER, TRUE, | |
| 316 -1); | |
| 317 // First group separator. | |
| 318 gtk_list_store_append(list_store_, &iter); | |
| 319 gtk_list_store_set( | |
| 320 list_store_, &iter, | |
| 321 COL_IS_HEADER, TRUE, | |
| 322 COL_IS_SEPARATOR, TRUE, | |
| 323 -1); | |
| 324 | |
| 325 // Blank row between groups. | |
| 326 gtk_list_store_append(list_store_, &iter); | |
| 327 gtk_list_store_set( | |
| 328 list_store_, &iter, | |
| 329 COL_IS_HEADER, TRUE, | |
| 330 -1); | |
| 331 // Second group title. | |
| 332 gtk_list_store_append(list_store_, &iter); | |
| 333 gtk_list_store_set( | |
| 334 list_store_, &iter, | |
| 335 COL_WEIGHT, PANGO_WEIGHT_BOLD, | |
| 336 COL_WEIGHT_SET, TRUE, | |
| 337 COL_TITLE, UTF16ToUTF8(groups[1].title).c_str(), | |
| 338 COL_IS_HEADER, TRUE, | |
| 339 -1); | |
| 340 // Second group separator. | |
| 341 gtk_list_store_append(list_store_, &iter); | |
| 342 gtk_list_store_set( | |
| 343 list_store_, &iter, | |
| 344 COL_IS_HEADER, TRUE, | |
| 345 COL_IS_SEPARATOR, TRUE, | |
| 346 -1); | |
| 347 | |
| 348 for (int i = 0; i < table_model_->RowCount(); ++i) | |
| 349 AddNodeToList(i); | |
| 350 } | |
| 351 | |
| 352 void KeywordEditorView::OnItemsChanged(int start, int length) { | |
| 353 DCHECK(model_second_group_index_ == table_model_->last_search_engine_index()); | |
| 354 GtkTreeIter iter; | |
| 355 for (int i = 0; i < length; ++i) { | |
| 356 int row = GetListStoreRowForModelRow(start + i); | |
| 357 bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), | |
| 358 &iter, NULL, row); | |
| 359 if (!rv) { | |
| 360 NOTREACHED(); | |
| 361 return; | |
| 362 } | |
| 363 SetColumnValues(start + i, &iter); | |
| 364 rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter); | |
| 365 } | |
| 366 } | |
| 367 | |
| 368 void KeywordEditorView::OnItemsAdded(int start, int length) { | |
| 369 model_second_group_index_ = table_model_->last_search_engine_index(); | |
| 370 for (int i = 0; i < length; ++i) { | |
| 371 AddNodeToList(start + i); | |
| 372 } | |
| 373 } | |
| 374 | |
| 375 void KeywordEditorView::OnItemsRemoved(int start, int length) { | |
| 376 // This is quite likely not correct with removing multiple in one call, but | |
| 377 // that shouldn't happen since we only can select and modify/remove one at a | |
| 378 // time. | |
| 379 DCHECK_EQ(length, 1); | |
| 380 for (int i = 0; i < length; ++i) { | |
| 381 int row = GetListStoreRowForModelRow(start + i); | |
| 382 GtkTreeIter iter; | |
| 383 if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &iter, | |
| 384 NULL, row)) { | |
| 385 NOTREACHED(); | |
| 386 return; | |
| 387 } | |
| 388 gtk_list_store_remove(list_store_, &iter); | |
| 389 } | |
| 390 model_second_group_index_ = table_model_->last_search_engine_index(); | |
| 391 } | |
| 392 | |
| 393 void KeywordEditorView::OnTemplateURLModelChanged() { | |
| 394 EnableControls(); | |
| 395 } | |
| 396 | |
| 397 // static | |
| 398 void KeywordEditorView::OnWindowDestroy(GtkWidget* widget, | |
| 399 KeywordEditorView* window) { | |
| 400 instance_ = NULL; | |
| 401 MessageLoop::current()->DeleteSoon(FROM_HERE, window); | |
| 402 } | |
| 403 | |
| 404 // static | |
| 405 void KeywordEditorView::OnResponse(GtkDialog* dialog, int response_id, | |
| 406 KeywordEditorView* window) { | |
| 407 gtk_widget_destroy(window->dialog_); | |
| 408 } | |
| 409 | |
| 410 // static | |
| 411 gboolean KeywordEditorView::OnCheckRowIsSeparator(GtkTreeModel* model, | |
| 412 GtkTreeIter* iter, | |
| 413 gpointer user_data) { | |
| 414 gboolean is_separator; | |
| 415 gtk_tree_model_get(model, iter, COL_IS_SEPARATOR, &is_separator, -1); | |
| 416 return is_separator; | |
| 417 } | |
| 418 | |
| 419 // static | |
| 420 gboolean KeywordEditorView::OnSelectionFilter(GtkTreeSelection* selection, | |
| 421 GtkTreeModel* model, | |
| 422 GtkTreePath* path, | |
| 423 gboolean path_currently_selected, | |
| 424 gpointer user_data) { | |
| 425 GtkTreeIter iter; | |
| 426 if (!gtk_tree_model_get_iter(model, &iter, path)) { | |
| 427 NOTREACHED(); | |
| 428 return TRUE; | |
| 429 } | |
| 430 gboolean is_header; | |
| 431 gtk_tree_model_get(model, &iter, COL_IS_HEADER, &is_header, -1); | |
| 432 return !is_header; | |
| 433 } | |
| 434 | |
| 435 // static | |
| 436 void KeywordEditorView::OnSelectionChanged( | |
| 437 GtkTreeSelection* selection, KeywordEditorView* editor) { | |
| 438 editor->EnableControls(); | |
| 439 } | |
| 440 | |
| 441 // static | |
| 442 void KeywordEditorView::OnRowActivated(GtkTreeView* tree_view, | |
| 443 GtkTreePath* path, | |
| 444 GtkTreeViewColumn* column, | |
| 445 KeywordEditorView* editor) { | |
| 446 OnEditButtonClicked(NULL, editor); | |
| 447 } | |
| 448 | |
| 449 // static | |
| 450 void KeywordEditorView::OnAddButtonClicked(GtkButton* button, | |
| 451 KeywordEditorView* editor) { | |
| 452 new EditSearchEngineDialog( | |
| 453 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET( | |
| 454 gtk_util::GetDialogWindow(editor->dialog_)))), | |
| 455 NULL, | |
| 456 editor, | |
| 457 editor->profile_); | |
| 458 } | |
| 459 | |
| 460 // static | |
| 461 void KeywordEditorView::OnEditButtonClicked(GtkButton* button, | |
| 462 KeywordEditorView* editor) { | |
| 463 int model_row = editor->GetSelectedModelRow(); | |
| 464 if (model_row == -1) | |
| 465 return; | |
| 466 | |
| 467 new EditSearchEngineDialog( | |
| 468 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET( | |
| 469 gtk_util::GetDialogWindow(editor->dialog_)))), | |
| 470 editor->controller_->GetTemplateURL(model_row), | |
| 471 editor, | |
| 472 editor->profile_); | |
| 473 } | |
| 474 | |
| 475 // static | |
| 476 void KeywordEditorView::OnRemoveButtonClicked(GtkButton* button, | |
| 477 KeywordEditorView* editor) { | |
| 478 int model_row = editor->GetSelectedModelRow(); | |
| 479 if (model_row == -1) { | |
| 480 NOTREACHED(); | |
| 481 return; | |
| 482 } | |
| 483 editor->controller_->RemoveTemplateURL(model_row); | |
| 484 if (model_row >= editor->table_model_->RowCount()) | |
| 485 model_row = editor->table_model_->RowCount() - 1; | |
| 486 if (model_row >= 0) | |
| 487 editor->SelectModelRow(model_row); | |
| 488 } | |
| 489 | |
| 490 // static | |
| 491 void KeywordEditorView::OnMakeDefaultButtonClicked(GtkButton* button, | |
| 492 KeywordEditorView* editor) { | |
| 493 int model_row = editor->GetSelectedModelRow(); | |
| 494 if (model_row == -1) { | |
| 495 NOTREACHED(); | |
| 496 return; | |
| 497 } | |
| 498 int new_index = editor->controller_->MakeDefaultTemplateURL(model_row); | |
| 499 if (new_index > 0) { | |
| 500 editor->SelectModelRow(new_index); | |
| 501 } | |
| 502 } | |
| OLD | NEW |