diff options
author | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-19 04:48:24 +0000 |
---|---|---|
committer | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-19 04:48:24 +0000 |
commit | 65705eaa06155250c255ecdb766ebfeb081025f7 (patch) | |
tree | c49d0fc18479349f09643423c5b2f5862a0a33c6 /chrome | |
parent | 1a6b30a619cba771cb9c4ed4da9c3778634567ad (diff) | |
download | chromium_src-65705eaa06155250c255ecdb766ebfeb081025f7.zip chromium_src-65705eaa06155250c255ecdb766ebfeb081025f7.tar.gz chromium_src-65705eaa06155250c255ecdb766ebfeb081025f7.tar.bz2 |
Gtk languages options page part 1: accept-languages configuration.
Move accept_language_list to l10n_util, use it for LanguagesPageGtk.
BUG=13524
TEST=You can view, reorder, remove and add accept-languages.
Review URL: http://codereview.chromium.org/174043
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23695 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/gtk/options/fonts_languages_window_gtk.cc | 9 | ||||
-rw-r--r-- | chrome/browser/gtk/options/languages_page_gtk.cc | 342 | ||||
-rw-r--r-- | chrome/browser/gtk/options/languages_page_gtk.h | 115 | ||||
-rw-r--r-- | chrome/browser/gtk/options/languages_page_gtk_unittest.cc | 226 | ||||
-rw-r--r-- | chrome/browser/language_order_table_model.cc | 7 | ||||
-rw-r--r-- | chrome/browser/language_order_table_model.h | 4 | ||||
-rw-r--r-- | chrome/browser/views/options/languages_page_view.cc | 159 | ||||
-rw-r--r-- | chrome/chrome.gyp | 3 | ||||
-rw-r--r-- | chrome/test/data/valgrind/unit_tests.gtest_linux.txt | 1 |
9 files changed, 707 insertions, 159 deletions
diff --git a/chrome/browser/gtk/options/fonts_languages_window_gtk.cc b/chrome/browser/gtk/options/fonts_languages_window_gtk.cc index ef3a7cf..af0242e 100644 --- a/chrome/browser/gtk/options/fonts_languages_window_gtk.cc +++ b/chrome/browser/gtk/options/fonts_languages_window_gtk.cc @@ -10,6 +10,7 @@ #include "base/message_loop.h" #include "chrome/browser/profile.h" #include "chrome/browser/gtk/options/fonts_page_gtk.h" +#include "chrome/browser/gtk/options/languages_page_gtk.h" #include "chrome/common/gtk_util.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" @@ -43,6 +44,9 @@ class FontsLanguagesWindowGtk { // The fonts page. FontsPageGtk fonts_page_; + // The languages page. + LanguagesPageGtk languages_page_; + DISALLOW_COPY_AND_ASSIGN(FontsLanguagesWindowGtk); }; @@ -56,7 +60,8 @@ FontsLanguagesWindowGtk::FontsLanguagesWindowGtk(Profile* profile) // the record comes from the original profile, but we explicitly use // the original profile to avoid potential problems. : profile_(profile->GetOriginalProfile()), - fonts_page_(profile_) { + fonts_page_(profile_), + languages_page_(profile_) { dialog_ = gtk_dialog_new_with_buttons( l10n_util::GetStringFUTF8(IDS_FONT_LANGUAGE_SETTING_WINDOWS_TITLE, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)).c_str(), @@ -87,7 +92,7 @@ FontsLanguagesWindowGtk::FontsLanguagesWindowGtk(Profile* profile) // Langauges tab. gtk_notebook_append_page( GTK_NOTEBOOK(notebook_), - gtk_label_new("TODO content"), + languages_page_.get_page_widget(), gtk_label_new( l10n_util::GetStringUTF8( IDS_FONT_LANGUAGE_SETTING_LANGUAGES_TAB_TITLE).c_str())); diff --git a/chrome/browser/gtk/options/languages_page_gtk.cc b/chrome/browser/gtk/options/languages_page_gtk.cc new file mode 100644 index 0000000..cfa466b --- /dev/null +++ b/chrome/browser/gtk/options/languages_page_gtk.cc @@ -0,0 +1,342 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/gtk/options/languages_page_gtk.h" + +#include <set> +#include <string> + +#include "app/l10n_util.h" +#include "base/message_loop.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/language_combobox_model.h" +#include "chrome/browser/language_order_table_model.h" +#include "chrome/common/gtk_util.h" +#include "chrome/common/pref_names.h" +#include "grit/generated_resources.h" + +namespace { + +const int kWrapWidth = 475; + +GtkWidget* NewComboboxFromModel(ComboboxModel* model) { + GtkWidget* combobox = gtk_combo_box_new_text(); + int count = model->GetItemCount(); + for (int i = 0; i < count; ++i) + gtk_combo_box_append_text(GTK_COMBO_BOX(combobox), + WideToUTF8(model->GetItemAt(i)).c_str()); + return combobox; +} + +//////////////////////////////////////////////////////////////////////////////// +// AddLanguageDialog + +class AddLanguageDialog { + public: + AddLanguageDialog(Profile* profile, LanguagesPageGtk* delegate); + private: + // Callback for dialog buttons. + static void OnResponse(GtkDialog* dialog, int response_id, + AddLanguageDialog* window); + + // Callback for window destruction. + static void OnWindowDestroy(GtkWidget* widget, AddLanguageDialog* window); + + // The dialog window. + GtkWidget* dialog_; + + // The language chooser combobox. + GtkWidget* combobox_; + scoped_ptr<LanguageComboboxModel> accept_language_combobox_model_; + + // Used for call back to LanguagePageGtk that language has been selected. + LanguagesPageGtk* language_delegate_; + + DISALLOW_COPY_AND_ASSIGN(AddLanguageDialog); +}; + +AddLanguageDialog::AddLanguageDialog(Profile* profile, + LanguagesPageGtk* delegate) + : language_delegate_(delegate) { + GtkWindow* parent = GTK_WINDOW( + gtk_widget_get_toplevel(delegate->get_page_widget())); + + dialog_ = gtk_dialog_new_with_buttons( + l10n_util::GetStringUTF8( + IDS_FONT_LANGUAGE_SETTING_LANGUAGES_TAB_TITLE).c_str(), + parent, + static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR), + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + GTK_STOCK_ADD, + GTK_RESPONSE_OK, + NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK); + gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox), + gtk_util::kContentAreaSpacing); + + const std::string app_locale = g_browser_process->GetApplicationLocale(); + std::vector<std::string> locale_codes; + l10n_util::GetAcceptLanguagesForLocale(app_locale, &locale_codes); + accept_language_combobox_model_.reset( + new LanguageComboboxModel(profile, locale_codes)); + combobox_ = NewComboboxFromModel(accept_language_combobox_model_.get()); + gtk_combo_box_set_active(GTK_COMBO_BOX(combobox_), 0); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), combobox_); + + g_signal_connect(dialog_, "response", G_CALLBACK(OnResponse), this); + g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this); + + gtk_widget_show_all(dialog_); +} + +// static +void AddLanguageDialog::OnResponse(GtkDialog* dialog, + int response_id, + AddLanguageDialog* window) { + if (response_id == GTK_RESPONSE_OK) { + int selected = gtk_combo_box_get_active(GTK_COMBO_BOX(window->combobox_)); + window->language_delegate_->OnAddLanguage( + window->accept_language_combobox_model_->GetLocaleFromIndex(selected)); + } + gtk_widget_destroy(window->dialog_); +} + +// static +void AddLanguageDialog::OnWindowDestroy(GtkWidget* widget, + AddLanguageDialog* window) { + MessageLoop::current()->DeleteSoon(FROM_HERE, window); +} + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// LanguagesPageGtk + +LanguagesPageGtk::LanguagesPageGtk(Profile* profile) + : OptionsPageBase(profile), initializing_(true) { + Init(); +} + +LanguagesPageGtk::~LanguagesPageGtk() { +} + +void LanguagesPageGtk::Init() { + page_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing); + gtk_container_set_border_width(GTK_CONTAINER(page_), + gtk_util::kContentAreaBorder); + + // Languages order controls. + GtkWidget* languages_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); + gtk_box_pack_start(GTK_BOX(page_), languages_vbox, + TRUE, TRUE, 0); + + GtkWidget* languages_instructions_label = gtk_label_new( + l10n_util::GetStringUTF8( + IDS_FONT_LANGUAGE_SETTING_LANGUAGES_INSTRUCTIONS).c_str()); + gtk_misc_set_alignment(GTK_MISC(languages_instructions_label), 0, .5); + gtk_label_set_line_wrap(GTK_LABEL(languages_instructions_label), TRUE); + gtk_widget_set_size_request(languages_instructions_label, kWrapWidth, -1); + gtk_box_pack_start(GTK_BOX(languages_vbox), languages_instructions_label, + FALSE, FALSE, 0); + + GtkWidget* languages_list_hbox = gtk_hbox_new(FALSE, + gtk_util::kControlSpacing); + gtk_box_pack_start(GTK_BOX(languages_vbox), languages_list_hbox, + TRUE, TRUE, 0); + + // Languages order tree. + language_order_store_ = gtk_list_store_new(COL_COUNT, + G_TYPE_STRING); + language_order_tree_ = gtk_tree_view_new_with_model( + GTK_TREE_MODEL(language_order_store_)); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(language_order_tree_), FALSE); + GtkTreeViewColumn* lang_column = gtk_tree_view_column_new_with_attributes( + "", + gtk_cell_renderer_text_new(), + "text", COL_LANG, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(language_order_tree_), lang_column); + language_order_selection_ = gtk_tree_view_get_selection( + GTK_TREE_VIEW(language_order_tree_)); + gtk_tree_selection_set_mode(language_order_selection_, + GTK_SELECTION_MULTIPLE); + g_signal_connect(G_OBJECT(language_order_selection_), "changed", + G_CALLBACK(OnSelectionChanged), this); + GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window), + GTK_SHADOW_ETCHED_IN); + gtk_container_add(GTK_CONTAINER(scroll_window), language_order_tree_); + gtk_box_pack_start(GTK_BOX(languages_list_hbox), scroll_window, + TRUE, TRUE, 0); + + language_order_table_model_.reset(new LanguageOrderTableModel); + language_order_table_adapter_.reset( + new gtk_tree::ModelAdapter(this, language_order_store_, + language_order_table_model_.get())); + + // Languages order buttons. + GtkWidget* languages_buttons_vbox = gtk_vbox_new(FALSE, + gtk_util::kControlSpacing); + gtk_box_pack_start(GTK_BOX(languages_list_hbox), languages_buttons_vbox, + FALSE, FALSE, 0); + + add_button_ = gtk_button_new_with_label(l10n_util::GetStringUTF8( + IDS_FONT_LANGUAGE_SETTING_LANGUAGES_SELECTOR_ADD_BUTTON_LABEL).c_str()); + g_signal_connect(G_OBJECT(add_button_), "clicked", + G_CALLBACK(OnAddButtonClicked), this); + gtk_box_pack_start(GTK_BOX(languages_buttons_vbox), add_button_, + FALSE, FALSE, 0); + + std::string remove_button_text = l10n_util::GetStringUTF8( + IDS_FONT_LANGUAGE_SETTING_LANGUAGES_SELECTOR_REMOVE_BUTTON_LABEL); + remove_button_ = gtk_button_new_with_label(remove_button_text.c_str()); + g_signal_connect(G_OBJECT(remove_button_), "clicked", + G_CALLBACK(OnRemoveButtonClicked), this); + gtk_box_pack_start(GTK_BOX(languages_buttons_vbox), remove_button_, + FALSE, FALSE, 0); + + std::string move_up_button_text = l10n_util::GetStringUTF8( + IDS_FONT_LANGUAGE_SETTING_LANGUAGES_SELECTOR_MOVEUP_BUTTON_LABEL); + move_up_button_ = gtk_button_new_with_label(move_up_button_text.c_str()); + g_signal_connect(G_OBJECT(move_up_button_), "clicked", + G_CALLBACK(OnMoveUpButtonClicked), this); + gtk_box_pack_start(GTK_BOX(languages_buttons_vbox), move_up_button_, + FALSE, FALSE, 0); + + std::string move_down_button_text = l10n_util::GetStringUTF8( + IDS_FONT_LANGUAGE_SETTING_LANGUAGES_SELECTOR_MOVEDOWN_BUTTON_LABEL); + move_down_button_ = gtk_button_new_with_label(move_down_button_text.c_str()); + g_signal_connect(G_OBJECT(move_down_button_), "clicked", + G_CALLBACK(OnMoveDownButtonClicked), this); + gtk_box_pack_start(GTK_BOX(languages_buttons_vbox), move_down_button_, + FALSE, FALSE, 0); + + GtkWidget* spellchecker_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); + gtk_box_pack_start(GTK_BOX(page_), spellchecker_vbox, + FALSE, FALSE, 0); + + // TODO(mattm): Spell checker controls. + + // Initialize. + accept_languages_.Init(prefs::kAcceptLanguages, + profile()->GetPrefs(), this); + dictionary_language_.Init(prefs::kSpellCheckDictionary, + profile()->GetPrefs(), this); + enable_spellcheck_.Init(prefs::kEnableSpellCheck, + profile()->GetPrefs(), this); + enable_autospellcorrect_.Init(prefs::kEnableAutoSpellCorrect, + profile()->GetPrefs(), this); + NotifyPrefChanged(NULL); + EnableControls(); +} + +void LanguagesPageGtk::SetColumnValues(int row, GtkTreeIter* iter) { + std::wstring lang = language_order_table_model_->GetText(row, 0); + gtk_list_store_set(language_order_store_, iter, + COL_LANG, WideToUTF8(lang).c_str(), + -1); +} + +void LanguagesPageGtk::OnAnyModelUpdate() { + if (!initializing_) { + accept_languages_.SetValue(ASCIIToWide( + language_order_table_model_->GetLanguageList())); + } + EnableControls(); +} + +void LanguagesPageGtk::EnableControls() { + int num_selected = gtk_tree_selection_count_selected_rows( + language_order_selection_); + int row_count = gtk_tree_model_iter_n_children( + GTK_TREE_MODEL(language_order_store_), NULL); + gtk_widget_set_sensitive(move_up_button_, + num_selected == 1 && FirstSelectedRowNum() > 0); + gtk_widget_set_sensitive(move_down_button_, + num_selected == 1 && + FirstSelectedRowNum() < row_count - 1); + gtk_widget_set_sensitive(remove_button_, num_selected > 0); +} + +int LanguagesPageGtk::FirstSelectedRowNum() { + int row_num = -1; + GList* list = gtk_tree_selection_get_selected_rows(language_order_selection_, + NULL); + if (list) { + row_num = gtk_tree::GetRowNumForPath(static_cast<GtkTreePath*>(list->data)); + g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL); + g_list_free(list); + } + return row_num; +} + +void LanguagesPageGtk::NotifyPrefChanged(const std::wstring* pref_name) { + initializing_ = true; + if (!pref_name || *pref_name == prefs::kAcceptLanguages) { + language_order_table_model_->SetAcceptLanguagesString( + WideToASCII(accept_languages_.GetValue())); + } + // TODO(mattm): Spell checker prefs. + initializing_ = false; +} + +void LanguagesPageGtk::OnAddLanguage(const std::string& new_language) { + if (language_order_table_model_->Add(new_language)) + gtk_tree::SelectAndFocusRowNum(language_order_table_model_->RowCount() - 1, + GTK_TREE_VIEW(language_order_tree_)); +} + +// static +void LanguagesPageGtk::OnSelectionChanged(GtkTreeSelection *selection, + LanguagesPageGtk* languages_page) { + languages_page->EnableControls(); +} + +// static +void LanguagesPageGtk::OnAddButtonClicked(GtkButton* button, + LanguagesPageGtk* languages_page) { + new AddLanguageDialog(languages_page->profile(), languages_page); +} + +// static +void LanguagesPageGtk::OnRemoveButtonClicked(GtkButton* button, + LanguagesPageGtk* languages_page) { + GList* list = gtk_tree_selection_get_selected_rows( + languages_page->language_order_selection_, NULL); + std::set<int> selected_rows; + GList* node; + for (node = list; node != NULL; node = node->next) { + selected_rows.insert( + gtk_tree::GetRowNumForPath(static_cast<GtkTreePath*>(node->data))); + } + g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL); + g_list_free(list); + + for (std::set<int>::reverse_iterator selected = selected_rows.rbegin(); + selected != selected_rows.rend(); ++selected) { + languages_page->language_order_table_model_->Remove(*selected); + } +} + +// static +void LanguagesPageGtk::OnMoveUpButtonClicked(GtkButton* button, + LanguagesPageGtk* languages_page) { + int item_selected = languages_page->FirstSelectedRowNum(); + languages_page->language_order_table_model_->MoveUp(item_selected); + gtk_tree::SelectAndFocusRowNum( + item_selected - 1, GTK_TREE_VIEW(languages_page->language_order_tree_)); +} + +// static +void LanguagesPageGtk::OnMoveDownButtonClicked( + GtkButton* button, LanguagesPageGtk* languages_page) { + int item_selected = languages_page->FirstSelectedRowNum(); + languages_page->language_order_table_model_->MoveDown(item_selected); + gtk_tree::SelectAndFocusRowNum( + item_selected + 1, GTK_TREE_VIEW(languages_page->language_order_tree_)); +} diff --git a/chrome/browser/gtk/options/languages_page_gtk.h b/chrome/browser/gtk/options/languages_page_gtk.h new file mode 100644 index 0000000..a81161a --- /dev/null +++ b/chrome/browser/gtk/options/languages_page_gtk.h @@ -0,0 +1,115 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// The languages page of the Languages & languages options dialog, which +// contains accept-languages and spellchecker language options. + +#ifndef CHROME_BROWSER_GTK_OPTIONS_LANGUAGES_PAGE_GTK_H_ +#define CHROME_BROWSER_GTK_OPTIONS_LANGUAGES_PAGE_GTK_H_ + +#include <gtk/gtk.h> + +#include "base/scoped_ptr.h" +#include "chrome/browser/options_page_base.h" +#include "chrome/common/gtk_tree.h" +#include "chrome/common/pref_member.h" +#include "testing/gtest/include/gtest/gtest_prod.h" + +class LanguageOrderTableModel; + +class LanguagesPageGtk + : public OptionsPageBase, + public gtk_tree::ModelAdapter::Delegate { + public: + explicit LanguagesPageGtk(Profile* profile); + virtual ~LanguagesPageGtk(); + + GtkWidget* get_page_widget() const { + return page_; + } + + // gtk_tree::ModelAdapter::Delegate implementation. + virtual void OnAnyModelUpdate(); + virtual void SetColumnValues(int row, GtkTreeIter* iter); + + // Callback from AddLanguageDialog. + void OnAddLanguage(const std::string& new_language); + + private: + // Column ids for |language_order_store_|. + enum { + COL_LANG, + COL_COUNT, + }; + + void Init(); + + // Enable buttons based on selection state. + void EnableControls(); + + // Get the row number of the first selected row or -1 if no row is selected. + int FirstSelectedRowNum(); + + // Overridden from OptionsPageBase. + virtual void NotifyPrefChanged(const std::wstring* pref_name); + + // Callbacks for accept languages widgets. + static void OnSelectionChanged(GtkTreeSelection *selection, + LanguagesPageGtk* languages_page); + static void OnAddButtonClicked(GtkButton* button, + LanguagesPageGtk* languages_page); + static void OnRemoveButtonClicked(GtkButton* button, + LanguagesPageGtk* languages_page); + static void OnMoveUpButtonClicked(GtkButton* button, + LanguagesPageGtk* languages_page); + static void OnMoveDownButtonClicked(GtkButton* button, + LanguagesPageGtk* languages_page); + + // The accept languages widgets. + GtkListStore* language_order_store_; + GtkWidget* language_order_tree_; + GtkTreeSelection* language_order_selection_; + GtkWidget* move_up_button_; + GtkWidget* move_down_button_; + GtkWidget* add_button_; + GtkWidget* remove_button_; + + // The spell checking widgets. + GtkWidget* dictionary_language_combobox_; + GtkWidget* enable_autospellcorrect_checkbox_; + GtkWidget* enable_spellchecking_checkbox_; + + // The widget containing the options for this page. + GtkWidget* page_; + + // The model for |language_order_store_|. + scoped_ptr<LanguageOrderTableModel> language_order_table_model_; + scoped_ptr<gtk_tree::ModelAdapter> language_order_table_adapter_; + + // Accept languages pref. + StringPrefMember accept_languages_; + + // The spellchecker "dictionary language" pref. + StringPrefMember dictionary_language_; + + // SpellChecker enable pref. + BooleanPrefMember enable_spellcheck_; + + // Auto spell correction pref. + BooleanPrefMember enable_autospellcorrect_; + + // Flag to ignore gtk callbacks while we are loading prefs, to avoid + // then turning around and saving them again. + bool initializing_; + + friend class LanguagesPageGtkTest; + FRIEND_TEST(LanguagesPageGtkTest, RemoveAcceptLang); + FRIEND_TEST(LanguagesPageGtkTest, RemoveMultipleAcceptLang); + FRIEND_TEST(LanguagesPageGtkTest, MoveAcceptLang); + FRIEND_TEST(LanguagesPageGtkTest, AddAcceptLang); + + DISALLOW_COPY_AND_ASSIGN(LanguagesPageGtk); +}; + +#endif // CHROME_BROWSER_GTK_OPTIONS_LANGUAGES_PAGE_GTK_H_ diff --git a/chrome/browser/gtk/options/languages_page_gtk_unittest.cc b/chrome/browser/gtk/options/languages_page_gtk_unittest.cc new file mode 100644 index 0000000..1ce49a5 --- /dev/null +++ b/chrome/browser/gtk/options/languages_page_gtk_unittest.cc @@ -0,0 +1,226 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/gtk/options/languages_page_gtk.h" + +#include <gtk/gtk.h> + +#include "base/string_util.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/testing_profile.h" +#include "testing/gtest/include/gtest/gtest.h" + +class LanguagesPageGtkTest : public testing::Test { + public: + virtual void SetUp() { + profile_.reset(new TestingProfile()); + } + + // Get the accept languages displayed in the dialog in the order they are + // displayed, as a comma seperated string. + // Ex: EXPECT_STREQ("en,ja", GetDisplayedLangs(page).c_str()); + std::string GetDisplayedLangs(const LanguagesPageGtk& page) { + std::vector<std::string> parts; + GtkTreeModel* tree_model = GTK_TREE_MODEL(page.language_order_store_); + GtkTreeIter iter; + if (!gtk_tree_model_get_iter_first(tree_model, &iter)) + return std::string(); + while (true) { + gchar* name; + gtk_tree_model_get(tree_model, &iter, LanguagesPageGtk::COL_LANG, &name, + -1); + parts.push_back(name); + g_free(name); + if (!gtk_tree_model_iter_next(tree_model, &iter)) + break; + } + return JoinString(parts, ','); + } + + protected: + MessageLoopForUI message_loop_; + scoped_ptr<TestingProfile> profile_; +}; + +TEST_F(LanguagesPageGtkTest, RemoveAcceptLang) { + //profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, L"en,ja,es,fr,it"); + profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, L"en,ja,es"); + LanguagesPageGtk page(profile_.get()); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_)); + + GtkTreeIter iter; + gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_), + &iter, NULL, 1); + gtk_tree_selection_select_iter(page.language_order_selection_, &iter); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_)); + + gtk_button_clicked(GTK_BUTTON(page.remove_button_)); + EXPECT_STREQ("English,Spanish", GetDisplayedLangs(page).c_str()); + EXPECT_STREQ("en,es", WideToASCII( + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)).c_str()); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_)); + + gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_), + &iter, NULL, 1); + gtk_tree_selection_select_iter(page.language_order_selection_, &iter); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_)); + + gtk_button_clicked(GTK_BUTTON(page.remove_button_)); + EXPECT_STREQ("English", GetDisplayedLangs(page).c_str()); + EXPECT_STREQ("en", WideToASCII( + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)).c_str()); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_)); + + gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_), + &iter, NULL, 0); + gtk_tree_selection_select_iter(page.language_order_selection_, &iter); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_)); + + gtk_button_clicked(GTK_BUTTON(page.remove_button_)); + EXPECT_STREQ("", GetDisplayedLangs(page).c_str()); + EXPECT_STREQ("", WideToASCII( + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)).c_str()); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_)); +} + +TEST_F(LanguagesPageGtkTest, RemoveMultipleAcceptLang) { + profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, L"en,ja,es,fr,it"); + LanguagesPageGtk page(profile_.get()); + GtkTreeIter iter; + gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_), + &iter, NULL, 1); + gtk_tree_selection_select_iter(page.language_order_selection_, &iter); + gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_), + &iter, NULL, 3); + gtk_tree_selection_select_iter(page.language_order_selection_, &iter); + gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_), + &iter, NULL, 4); + gtk_tree_selection_select_iter(page.language_order_selection_, &iter); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_)); + + gtk_button_clicked(GTK_BUTTON(page.remove_button_)); + EXPECT_STREQ("English,Spanish", GetDisplayedLangs(page).c_str()); + EXPECT_STREQ("en,es", WideToASCII( + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)).c_str()); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_)); + + gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_), + &iter, NULL, 1); + gtk_tree_selection_select_iter(page.language_order_selection_, &iter); + gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_), + &iter, NULL, 0); + gtk_tree_selection_select_iter(page.language_order_selection_, &iter); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_)); + + gtk_button_clicked(GTK_BUTTON(page.remove_button_)); + EXPECT_STREQ("", GetDisplayedLangs(page).c_str()); + EXPECT_STREQ("", WideToASCII( + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)).c_str()); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_)); +} + +TEST_F(LanguagesPageGtkTest, MoveAcceptLang) { + profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, L"en,ja,es"); + LanguagesPageGtk page(profile_.get()); + EXPECT_STREQ("English,Japanese,Spanish", GetDisplayedLangs(page).c_str()); + GtkTreeIter iter; + + gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(page.language_order_store_), + &iter, NULL, 0); + gtk_tree_selection_select_iter(page.language_order_selection_, &iter); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + + gtk_button_clicked(GTK_BUTTON(page.move_down_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_STREQ("Japanese,English,Spanish", GetDisplayedLangs(page).c_str()); + EXPECT_STREQ("ja,en,es", WideToASCII( + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)).c_str()); + + gtk_button_clicked(GTK_BUTTON(page.move_down_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_STREQ("Japanese,Spanish,English", GetDisplayedLangs(page).c_str()); + EXPECT_STREQ("ja,es,en", WideToASCII( + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)).c_str()); + + gtk_button_clicked(GTK_BUTTON(page.move_up_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_STREQ("Japanese,English,Spanish", GetDisplayedLangs(page).c_str()); + EXPECT_STREQ("ja,en,es", WideToASCII( + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)).c_str()); + + gtk_button_clicked(GTK_BUTTON(page.move_up_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_STREQ("English,Japanese,Spanish", GetDisplayedLangs(page).c_str()); + EXPECT_STREQ("en,ja,es", WideToASCII( + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)).c_str()); +} + +TEST_F(LanguagesPageGtkTest, AddAcceptLang) { + profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, L""); + LanguagesPageGtk page(profile_.get()); + EXPECT_STREQ("", GetDisplayedLangs(page).c_str()); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_)); + + page.OnAddLanguage("en"); + EXPECT_STREQ("English", GetDisplayedLangs(page).c_str()); + EXPECT_STREQ("en", WideToASCII( + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)).c_str()); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_)); + EXPECT_EQ(0, page.FirstSelectedRowNum()); + + page.OnAddLanguage("es"); + EXPECT_STREQ("English,Spanish", GetDisplayedLangs(page).c_str()); + EXPECT_STREQ("en,es", WideToASCII( + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)).c_str()); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.remove_button_)); + EXPECT_EQ(1, page.FirstSelectedRowNum()); + + // Duplicates should be ignored and selection should not be changed. + gtk_tree_selection_unselect_all(page.language_order_selection_); + page.OnAddLanguage("en"); + EXPECT_STREQ("English,Spanish", GetDisplayedLangs(page).c_str()); + EXPECT_STREQ("en,es", WideToASCII( + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)).c_str()); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(page.add_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_up_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.move_down_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(page.remove_button_)); + EXPECT_EQ(0, gtk_tree_selection_count_selected_rows( + page.language_order_selection_)); +} diff --git a/chrome/browser/language_order_table_model.cc b/chrome/browser/language_order_table_model.cc index 50799d2..e5bd403e 100644 --- a/chrome/browser/language_order_table_model.cc +++ b/chrome/browser/language_order_table_model.cc @@ -32,17 +32,18 @@ std::wstring LanguageOrderTableModel::GetText(int row, int column_id) { true)); } -void LanguageOrderTableModel::Add(const std::string& language) { +bool LanguageOrderTableModel::Add(const std::string& language) { if (language.empty()) - return; + return false; // Check for selecting duplicated language. for (std::vector<std::string>::const_iterator cit = languages_.begin(); cit != languages_.end(); ++cit) if (*cit == language) - return; + return false; languages_.push_back(language); if (observer_) observer_->OnItemsAdded(RowCount() - 1, 1); + return true; } void LanguageOrderTableModel::Remove(int index) { diff --git a/chrome/browser/language_order_table_model.h b/chrome/browser/language_order_table_model.h index 327fe67..911d55e 100644 --- a/chrome/browser/language_order_table_model.h +++ b/chrome/browser/language_order_table_model.h @@ -18,8 +18,8 @@ class LanguageOrderTableModel : public TableModel { // Set Language List. void SetAcceptLanguagesString(const std::string& language_list); - // Add at the end. - void Add(const std::string& language); + // Add at the end. Return true if the language was added. + bool Add(const std::string& language); // Removes the entry at the specified index. void Remove(int index); diff --git a/chrome/browser/views/options/languages_page_view.cc b/chrome/browser/views/options/languages_page_view.cc index abb2490..2fdc786 100644 --- a/chrome/browser/views/options/languages_page_view.cc +++ b/chrome/browser/views/options/languages_page_view.cc @@ -39,140 +39,6 @@ #include "views/widget/widget.h" #include "views/window/window.h" -static const char* const accept_language_list[] = { - "af", // Afrikaans - "am", // Amharic - "ar", // Arabic - "az", // Azerbaijani - "be", // Belarusian - "bg", // Bulgarian - "bh", // Bihari - "bn", // Bengali - "br", // Breton - "bs", // Bosnian - "ca", // Catalan - "co", // Corsican - "cs", // Czech - "cy", // Welsh - "da", // Danish - "de", // German - "de-AT", // German (Austria) - "de-CH", // German (Switzerland) - "de-DE", // German (Germany) - "el", // Greek - "en", // English - "en-AU", // English (Austrailia) - "en-CA", // English (Canada) - "en-GB", // English (UK) - "en-NZ", // English (New Zealand) - "en-US", // English (US) - "en-ZA", // English (South Africa) - "eo", // Esperanto - // TODO(jungshik) : Do we want to list all es-Foo for Latin-American - // Spanish speaking countries? - "es", // Spanish - "et", // Estonian - "eu", // Basque - "fa", // Persian - "fi", // Finnish - "fil", // Filipino - "fo", // Faroese - "fr", // French - "fr-CA", // French (Canada) - "fr-CH", // French (Switzerland) - "fr-FR", // French (France) - "fy", // Frisian - "ga", // Irish - "gd", // Scots Gaelic - "gl", // Galician - "gn", // Guarani - "gu", // Gujarati - "he", // Hebrew - "hi", // Hindi - "hr", // Croatian - "hu", // Hungarian - "hy", // Armenian - "ia", // Interlingua - "id", // Indonesian - "is", // Icelandic - "it", // Italian - "it-CH", // Italian (Switzerland) - "it-IT", // Italian (Italy) - "ja", // Japanese - "jw", // Javanese - "ka", // Georgian - "kk", // Kazakh - "km", // Cambodian - "kn", // Kannada - "ko", // Korean - "ku", // Kurdish - "ky", // Kyrgyz - "la", // Latin - "ln", // Lingala - "lo", // Laothian - "lt", // Lithuanian - "lv", // Latvian - "mk", // Macedonian - "ml", // Malayalam - "mn", // Mongolian - "mo", // Moldavian - "mr", // Marathi - "ms", // Malay - "mt", // Maltese - "nb", // Norwegian (Bokmal) - "ne", // Nepali - "nl", // Dutch - "nn", // Norwegian (Nynorsk) - "no", // Norwegian - "oc", // Occitan - "or", // Oriya - "pa", // Punjabi - "pl", // Polish - "ps", // Pashto - "pt", // Portuguese - "pt-BR", // Portuguese (Brazil) - "pt-PT", // Portuguese (Portugal) - "qu", // Quechua - "rm", // Romansh - "ro", // Romanian - "ru", // Russian - "sd", // Sindhi - "sh", // Serbo-Croatian - "si", // Sinhalese - "sk", // Slovak - "sl", // Slovenian - "sn", // Shona - "so", // Somali - "sq", // Albanian - "sr", // Serbian - "st", // Sesotho - "su", // Sundanese - "sv", // Swedish - "sw", // Swahili - "ta", // Tamil - "te", // Telugu - "tg", // Tajik - "th", // Thai - "ti", // Tigrinya - "tk", // Turkmen - "to", // Tonga - "tr", // Turkish - "tt", // Tatar - "tw", // Twi - "ug", // Uighur - "uk", // Ukrainian - "ur", // Urdu - "uz", // Uzbek - "vi", // Vietnamese - "xh", // Xhosa - "yi", // Yiddish - "yo", // Yoruba - "zh", // Chinese - "zh-CN", // Chinese (Simplified) - "zh-TW", // Chinese (Traditional) - "zu", // Zulu -}; - /////////////////////////////////////////////////////////////////////////////// // AddLanguageWindowView // @@ -289,22 +155,10 @@ void AddLanguageWindowView::ViewHierarchyChanged(bool is_add, void AddLanguageWindowView::Init() { // Determine Locale Codes. - std::vector<std::string> locale_codes; const std::string app_locale = g_browser_process->GetApplicationLocale(); - for (size_t i = 0; i < arraysize(accept_language_list); ++i) { - string16 display_name = - l10n_util::GetDisplayNameForLocale(accept_language_list[i], - app_locale, false); - // This is a hack. If ICU doesn't have a translated name for - // this language, GetDisplayNameForLocale will just return the - // language code. In that case, we skip it. - // TODO(jungshik) : Put them at the of the list with language codes - // enclosed by brackets. - if (IsStringASCII(display_name) && - UTF16ToASCII(display_name) == accept_language_list[i]) - continue; - locale_codes.push_back(accept_language_list[i]); - } + std::vector<std::string> locale_codes; + l10n_util::GetAcceptLanguagesForLocale(app_locale, &locale_codes); + accept_language_combobox_model_.reset(new LanguageComboboxModel( profile_, locale_codes)); accept_language_combobox_ = new views::Combobox( @@ -375,9 +229,10 @@ void LanguagesPageView::ButtonPressed(views::Button* sender) { } void LanguagesPageView::OnAddLanguage(const std::string& new_language) { - language_order_table_model_->Add(new_language); - language_order_table_->Select(language_order_table_model_->RowCount() - 1); - OnSelectionChanged(); + if (language_order_table_model_->Add(new_language)) { + language_order_table_->Select(language_order_table_model_->RowCount() - 1); + OnSelectionChanged(); + } } void LanguagesPageView::InitControlLayout() { diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index a28eb1d..69700e7 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1226,6 +1226,8 @@ 'browser/gtk/options/fonts_page_gtk.h', 'browser/gtk/options/general_page_gtk.cc', 'browser/gtk/options/general_page_gtk.h', + 'browser/gtk/options/languages_page_gtk.cc', + 'browser/gtk/options/languages_page_gtk.h', 'browser/gtk/options/options_layout_gtk.cc', 'browser/gtk/options/options_layout_gtk.h', 'browser/gtk/options/options_window_gtk.cc', @@ -3877,6 +3879,7 @@ 'browser/gtk/bookmark_editor_gtk_unittest.cc', 'browser/gtk/go_button_gtk_unittest.cc', 'browser/gtk/options/cookies_view_unittest.cc', + 'browser/gtk/options/languages_page_gtk_unittest.cc', 'browser/gtk/tabs/tab_renderer_gtk_unittest.cc', 'browser/gtk/view_id_util_unittest.cc', 'browser/history/expire_history_backend_unittest.cc', diff --git a/chrome/test/data/valgrind/unit_tests.gtest_linux.txt b/chrome/test/data/valgrind/unit_tests.gtest_linux.txt index 58220ef..f52ecf8 100644 --- a/chrome/test/data/valgrind/unit_tests.gtest_linux.txt +++ b/chrome/test/data/valgrind/unit_tests.gtest_linux.txt @@ -2,3 +2,4 @@ # Only fails on the bots? BookmarkEditorGtkTest.* CookiesViewTest.* +LanguagesPageGtkTest.* |