| Index: chrome/browser/gtk/keyword_editor_view.cc
|
| diff --git a/chrome/browser/gtk/keyword_editor_view.cc b/chrome/browser/gtk/keyword_editor_view.cc
|
| index 8ce4156c4981019ad10d77e5d85ba37e49e1bd87..62e20b61a334cece316c17bb823be0888127c25e 100644
|
| --- a/chrome/browser/gtk/keyword_editor_view.cc
|
| +++ b/chrome/browser/gtk/keyword_editor_view.cc
|
| @@ -5,11 +5,14 @@
|
| #include "chrome/browser/gtk/keyword_editor_view.h"
|
|
|
| #include "app/l10n_util.h"
|
| +#include "base/gfx/gtk_util.h"
|
| #include "chrome/browser/gtk/edit_search_engine_dialog.h"
|
| #include "chrome/browser/profile.h"
|
| #include "chrome/browser/metrics/user_metrics.h"
|
| +#include "chrome/browser/search_engines/keyword_editor_controller.h"
|
| #include "chrome/browser/search_engines/template_url.h"
|
| #include "chrome/browser/search_engines/template_url_model.h"
|
| +#include "chrome/browser/search_engines/template_url_table_model.h"
|
| #include "chrome/common/gtk_util.h"
|
| #include "grit/generated_resources.h"
|
|
|
| @@ -19,11 +22,20 @@ namespace {
|
| const int kDialogDefaultWidth = 450;
|
| const int kDialogDefaultHeight = 450;
|
|
|
| +// How many rows should be added to an index into the |table_model_| to get the
|
| +// corresponding row in |list_store_|
|
| +const int kFirstGroupRowOffset = 2;
|
| +const int kSecondGroupRowOffset = 5;
|
| +
|
| // Column ids for |list_store_|.
|
| enum {
|
| COL_FAVICON,
|
| COL_TITLE,
|
| COL_KEYWORD,
|
| + COL_IS_HEADER,
|
| + COL_IS_SEPARATOR,
|
| + COL_WEIGHT,
|
| + COL_WEIGHT_SET,
|
| COL_COUNT,
|
| };
|
|
|
| @@ -49,24 +61,28 @@ void KeywordEditorView::OnEditedKeyword(const TemplateURL* template_url,
|
| const std::wstring& title,
|
| const std::wstring& keyword,
|
| const std::wstring& url) {
|
| - NOTIMPLEMENTED();
|
| + if (template_url) {
|
| + controller_->ModifyTemplateURL(template_url, title, keyword, url);
|
| +
|
| + // Force the make default button to update.
|
| + EnableControls();
|
| + } else {
|
| + SelectModelRow(controller_->AddTemplateURL(title, keyword, url));
|
| + }
|
| }
|
|
|
| KeywordEditorView::~KeywordEditorView() {
|
| - url_model_->RemoveObserver(this);
|
| + controller_->url_model()->RemoveObserver(this);
|
| }
|
|
|
| KeywordEditorView::KeywordEditorView(Profile* profile)
|
| : profile_(profile),
|
| - url_model_(profile->GetTemplateURLModel()) {
|
| + controller_(new KeywordEditorController(profile)),
|
| + table_model_(controller_->table_model()) {
|
| Init();
|
| }
|
|
|
| void KeywordEditorView::Init() {
|
| - DCHECK(url_model_);
|
| - url_model_->Load();
|
| - url_model_->AddObserver(this);
|
| -
|
| dialog_ = gtk_dialog_new_with_buttons(
|
| l10n_util::GetStringUTF8(IDS_SEARCH_ENGINES_EDITOR_WINDOW_TITLE).c_str(),
|
| NULL,
|
| @@ -95,9 +111,18 @@ void KeywordEditorView::Init() {
|
| list_store_ = gtk_list_store_new(COL_COUNT,
|
| GDK_TYPE_PIXBUF,
|
| G_TYPE_STRING,
|
| - G_TYPE_STRING);
|
| + G_TYPE_STRING,
|
| + G_TYPE_BOOLEAN,
|
| + G_TYPE_BOOLEAN,
|
| + G_TYPE_INT,
|
| + G_TYPE_BOOLEAN);
|
| tree_ = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store_));
|
| gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_), TRUE);
|
| + gtk_tree_view_set_row_separator_func(GTK_TREE_VIEW(tree_),
|
| + OnCheckRowIsSeparator,
|
| + NULL, NULL);
|
| + g_signal_connect(G_OBJECT(tree_), "row-activated",
|
| + G_CALLBACK(OnRowActivated), this);
|
| gtk_container_add(GTK_CONTAINER(scroll_window), tree_);
|
|
|
| GtkTreeViewColumn* title_column = gtk_tree_view_column_new();
|
| @@ -109,6 +134,10 @@ void KeywordEditorView::Init() {
|
| gtk_tree_view_column_pack_start(title_column, title_renderer, TRUE);
|
| gtk_tree_view_column_add_attribute(title_column, title_renderer, "text",
|
| COL_TITLE);
|
| + gtk_tree_view_column_add_attribute(title_column, title_renderer, "weight",
|
| + COL_WEIGHT);
|
| + gtk_tree_view_column_add_attribute(title_column, title_renderer, "weight-set",
|
| + COL_WEIGHT_SET);
|
| gtk_tree_view_column_set_title(
|
| title_column, l10n_util::GetStringUTF8(
|
| IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN).c_str());
|
| @@ -124,6 +153,8 @@ void KeywordEditorView::Init() {
|
|
|
| selection_ = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_));
|
| gtk_tree_selection_set_mode(selection_, GTK_SELECTION_SINGLE);
|
| + gtk_tree_selection_set_select_function(selection_, OnSelectionFilter,
|
| + NULL, NULL);
|
| g_signal_connect(G_OBJECT(selection_), "changed",
|
| G_CALLBACK(OnSelectionChanged), this);
|
|
|
| @@ -157,6 +188,10 @@ void KeywordEditorView::Init() {
|
| gtk_box_pack_start(GTK_BOX(button_box), make_default_button_, FALSE, FALSE,
|
| 0);
|
|
|
| + controller_->url_model()->AddObserver(this);
|
| + table_model_->SetObserver(this);
|
| + table_model_->Reload();
|
| +
|
| EnableControls();
|
|
|
| gtk_widget_show_all(dialog_);
|
| @@ -166,18 +201,198 @@ void KeywordEditorView::Init() {
|
| }
|
|
|
| void KeywordEditorView::EnableControls() {
|
| - bool enable = gtk_tree_selection_count_selected_rows(selection_) == 1;
|
| + bool can_edit = false;
|
| bool can_make_default = false;
|
| bool can_remove = false;
|
| - // TODO(mattm)
|
| - gtk_widget_set_sensitive(add_button_, url_model_->loaded());
|
| - gtk_widget_set_sensitive(edit_button_, enable);
|
| - gtk_widget_set_sensitive(remove_button_, can_make_default);
|
| - gtk_widget_set_sensitive(make_default_button_, can_remove);
|
| + int model_row = GetSelectedModelRow();
|
| + if (model_row != -1) {
|
| + can_edit = true;
|
| + const TemplateURL* selected_url = controller_->GetTemplateURL(model_row);
|
| + can_make_default = controller_->CanMakeDefault(selected_url);
|
| + can_remove = controller_->CanRemove(selected_url);
|
| + }
|
| + gtk_widget_set_sensitive(add_button_, controller_->loaded());
|
| + gtk_widget_set_sensitive(edit_button_, can_edit);
|
| + gtk_widget_set_sensitive(remove_button_, can_remove);
|
| + gtk_widget_set_sensitive(make_default_button_, can_make_default);
|
| +}
|
| +
|
| +void KeywordEditorView::SetColumnValues(int model_row, GtkTreeIter* iter) {
|
| + SkBitmap bitmap = table_model_->GetIcon(model_row);
|
| + GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
|
| + gtk_list_store_set(
|
| + list_store_, iter,
|
| + COL_FAVICON, pixbuf,
|
| + // Dunno why, even with COL_WEIGHT_SET to FALSE here, the weight still
|
| + // has an effect. So we just set it to normal.
|
| + COL_WEIGHT, PANGO_WEIGHT_NORMAL,
|
| + COL_WEIGHT_SET, TRUE,
|
| + COL_TITLE, WideToUTF8(table_model_->GetText(
|
| + model_row, IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN)).c_str(),
|
| + COL_KEYWORD, WideToUTF8(table_model_->GetText(
|
| + model_row, IDS_SEARCH_ENGINES_EDITOR_KEYWORD_COLUMN)).c_str(),
|
| + -1);
|
| +}
|
| +
|
| +int KeywordEditorView::GetListStoreRowForModelRow(int model_row) const {
|
| + if (model_row < model_second_group_index_)
|
| + return model_row + kFirstGroupRowOffset;
|
| + else
|
| + return model_row + kSecondGroupRowOffset;
|
| +}
|
| +
|
| +int KeywordEditorView::GetModelRowForPath(GtkTreePath* path) const {
|
| + gint* indices = gtk_tree_path_get_indices(path);
|
| + if (!indices) {
|
| + NOTREACHED();
|
| + return -1;
|
| + }
|
| + if (indices[0] >= model_second_group_index_ + kSecondGroupRowOffset)
|
| + return indices[0] - kSecondGroupRowOffset;
|
| + return indices[0] - kFirstGroupRowOffset;
|
| +}
|
| +
|
| +int KeywordEditorView::GetModelRowForIter(GtkTreeIter* iter) const {
|
| + GtkTreePath* path = gtk_tree_model_get_path(GTK_TREE_MODEL(list_store_),
|
| + iter);
|
| + int model_row = GetModelRowForPath(path);
|
| + gtk_tree_path_free(path);
|
| + return model_row;
|
| +}
|
| +
|
| +int KeywordEditorView::GetSelectedModelRow() const {
|
| + GtkTreeIter iter;
|
| + if (!gtk_tree_selection_get_selected(selection_, NULL, &iter))
|
| + return -1;
|
| + return GetModelRowForIter(&iter);
|
| +}
|
| +
|
| +void KeywordEditorView::SelectModelRow(int model_row) {
|
| + int row = GetListStoreRowForModelRow(model_row);
|
| + GtkTreeIter iter;
|
| + if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_),
|
| + &iter, NULL, row)) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| + GtkTreePath* path = gtk_tree_model_get_path(GTK_TREE_MODEL(list_store_),
|
| + &iter);
|
| + gtk_tree_view_set_cursor(GTK_TREE_VIEW(tree_), path, NULL, FALSE);
|
| + gtk_tree_path_free(path);
|
| +}
|
| +
|
| +void KeywordEditorView::AddNodeToList(int model_row) {
|
| + GtkTreeIter iter;
|
| + int row = GetListStoreRowForModelRow(model_row);
|
| + if (row == 0) {
|
| + gtk_list_store_prepend(list_store_, &iter);
|
| + } else {
|
| + GtkTreeIter sibling;
|
| + gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &sibling,
|
| + NULL, row - 1);
|
| + gtk_list_store_insert_after(list_store_, &iter, &sibling);
|
| + }
|
| +
|
| + SetColumnValues(model_row, &iter);
|
| +}
|
| +
|
| +void KeywordEditorView::OnModelChanged() {
|
| + model_second_group_index_ = table_model_->last_search_engine_index();
|
| + gtk_list_store_clear(list_store_);
|
| +
|
| + TableModel::Groups groups(table_model_->GetGroups());
|
| + if (groups.size() != 2) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| +
|
| + GtkTreeIter iter;
|
| + // First group title.
|
| + gtk_list_store_append(list_store_, &iter);
|
| + gtk_list_store_set(
|
| + list_store_, &iter,
|
| + COL_WEIGHT, PANGO_WEIGHT_BOLD,
|
| + COL_WEIGHT_SET, TRUE,
|
| + COL_TITLE, WideToUTF8(groups[0].title).c_str(),
|
| + COL_IS_HEADER, TRUE,
|
| + -1);
|
| + // First group separator.
|
| + gtk_list_store_append(list_store_, &iter);
|
| + gtk_list_store_set(
|
| + list_store_, &iter,
|
| + COL_IS_HEADER, TRUE,
|
| + COL_IS_SEPARATOR, TRUE,
|
| + -1);
|
| +
|
| + // Blank row between groups.
|
| + gtk_list_store_append(list_store_, &iter);
|
| + gtk_list_store_set(
|
| + list_store_, &iter,
|
| + COL_IS_HEADER, TRUE,
|
| + -1);
|
| + // Second group title.
|
| + gtk_list_store_append(list_store_, &iter);
|
| + gtk_list_store_set(
|
| + list_store_, &iter,
|
| + COL_WEIGHT, PANGO_WEIGHT_BOLD,
|
| + COL_WEIGHT_SET, TRUE,
|
| + COL_TITLE, WideToUTF8(groups[1].title).c_str(),
|
| + COL_IS_HEADER, TRUE,
|
| + -1);
|
| + // Second group separator.
|
| + gtk_list_store_append(list_store_, &iter);
|
| + gtk_list_store_set(
|
| + list_store_, &iter,
|
| + COL_IS_HEADER, TRUE,
|
| + COL_IS_SEPARATOR, TRUE,
|
| + -1);
|
| +
|
| + for (int i = 0; i < table_model_->RowCount(); ++i)
|
| + AddNodeToList(i);
|
| +}
|
| +
|
| +void KeywordEditorView::OnItemsChanged(int start, int length) {
|
| + DCHECK(model_second_group_index_ == table_model_->last_search_engine_index());
|
| + GtkTreeIter iter;
|
| + for (int i = 0; i < length; ++i) {
|
| + int row = GetListStoreRowForModelRow(start + i);
|
| + bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_),
|
| + &iter, NULL, row);
|
| + if (!rv) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| + SetColumnValues(start + i, &iter);
|
| + rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter);
|
| + }
|
| +}
|
| +
|
| +void KeywordEditorView::OnItemsAdded(int start, int length) {
|
| + model_second_group_index_ = table_model_->last_search_engine_index();
|
| + for (int i = 0; i < length; ++i) {
|
| + AddNodeToList(start + i);
|
| + }
|
| +}
|
| +
|
| +void KeywordEditorView::OnItemsRemoved(int start, int length) {
|
| + // This is quite likely not correct with removing multiple in one call, but
|
| + // that shouldn't happen since we only can select and modify/remove one at a
|
| + // time.
|
| + DCHECK(length == 1);
|
| + for (int i = 0; i < length; ++i) {
|
| + int row = GetListStoreRowForModelRow(start + i);
|
| + GtkTreeIter iter;
|
| + if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &iter,
|
| + NULL, row)) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| + gtk_list_store_remove(list_store_, &iter);
|
| + }
|
| + model_second_group_index_ = table_model_->last_search_engine_index();
|
| }
|
|
|
| void KeywordEditorView::OnTemplateURLModelChanged() {
|
| - // TODO(mattm): repopulate table
|
| EnableControls();
|
| }
|
|
|
| @@ -195,12 +410,45 @@ void KeywordEditorView::OnResponse(GtkDialog* dialog, int response_id,
|
| }
|
|
|
| // static
|
| +gboolean KeywordEditorView::OnCheckRowIsSeparator(GtkTreeModel* model,
|
| + GtkTreeIter* iter,
|
| + gpointer user_data) {
|
| + gboolean is_separator;
|
| + gtk_tree_model_get(model, iter, COL_IS_SEPARATOR, &is_separator, -1);
|
| + return is_separator;
|
| +}
|
| +
|
| +//static
|
| +gboolean KeywordEditorView::OnSelectionFilter(GtkTreeSelection *selection,
|
| + GtkTreeModel *model,
|
| + GtkTreePath *path,
|
| + gboolean path_currently_selected,
|
| + gpointer user_data) {
|
| + GtkTreeIter iter;
|
| + if (!gtk_tree_model_get_iter(model, &iter, path)) {
|
| + NOTREACHED();
|
| + return TRUE;
|
| + }
|
| + gboolean is_header;
|
| + gtk_tree_model_get(model, &iter, COL_IS_HEADER, &is_header, -1);
|
| + return !is_header;
|
| +}
|
| +
|
| +// static
|
| void KeywordEditorView::OnSelectionChanged(
|
| GtkTreeSelection *selection, KeywordEditorView* editor) {
|
| editor->EnableControls();
|
| }
|
|
|
| // static
|
| +void KeywordEditorView::OnRowActivated(GtkTreeView* tree_view,
|
| + GtkTreePath* path,
|
| + GtkTreeViewColumn* column,
|
| + KeywordEditorView* editor) {
|
| + OnEditButtonClicked(NULL, editor);
|
| +}
|
| +
|
| +// static
|
| void KeywordEditorView::OnAddButtonClicked(GtkButton* button,
|
| KeywordEditorView* editor) {
|
| new EditSearchEngineDialog(
|
| @@ -213,17 +461,43 @@ void KeywordEditorView::OnAddButtonClicked(GtkButton* button,
|
| // static
|
| void KeywordEditorView::OnEditButtonClicked(GtkButton* button,
|
| KeywordEditorView* editor) {
|
| - // TODO(mattm)
|
| + int model_row = editor->GetSelectedModelRow();
|
| + if (model_row == -1) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| + new EditSearchEngineDialog(
|
| + GTK_WINDOW(gtk_widget_get_toplevel(editor->dialog_)),
|
| + editor->controller_->GetTemplateURL(model_row),
|
| + editor,
|
| + editor->profile_);
|
| }
|
|
|
| // static
|
| void KeywordEditorView::OnRemoveButtonClicked(GtkButton* button,
|
| KeywordEditorView* editor) {
|
| - // TODO(mattm)
|
| + int model_row = editor->GetSelectedModelRow();
|
| + if (model_row == -1) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| + editor->controller_->RemoveTemplateURL(model_row);
|
| + if (model_row >= editor->table_model_->RowCount())
|
| + model_row = editor->table_model_->RowCount() - 1;
|
| + if (model_row >= 0)
|
| + editor->SelectModelRow(model_row);
|
| }
|
|
|
| // static
|
| void KeywordEditorView::OnMakeDefaultButtonClicked(GtkButton* button,
|
| KeywordEditorView* editor) {
|
| - // TODO(mattm)
|
| + int model_row = editor->GetSelectedModelRow();
|
| + if (model_row == -1) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| + int new_index = editor->controller_->MakeDefaultTemplateURL(model_row);
|
| + if (new_index > 0) {
|
| + editor->SelectModelRow(new_index);
|
| + }
|
| }
|
|
|