diff --git a/panels/common/cc-language-chooser.c b/panels/common/cc-language-chooser.c index 684367b22623ceab7fd3f6fec39fcc8f5153773b..aa342d5064f7fe83c7b51d43169d7e8a2cbc9e66 100644 --- a/panels/common/cc-language-chooser.c +++ b/panels/common/cc-language-chooser.c @@ -21,6 +21,7 @@ #define _GNU_SOURCE #include #include "cc-language-chooser.h" +#include "cc-language-row.h" #include "cc-common-resources.h" #include @@ -39,12 +40,12 @@ struct _CcLanguageChooser { GtkDialog parent_instance; - GtkWidget *select_button; - GtkWidget *no_results; - GtkListBoxRow *more_item; - GtkWidget *search_bar; - GtkWidget *language_filter_entry; - GtkWidget *language_listbox; + GtkSearchEntry *language_filter_entry; + GtkListBox *language_listbox; + GtkListBoxRow *more_row; + GtkSearchBar *search_bar; + GtkButton *select_button; + gboolean showing_extra; gchar *language; gchar **filter_words; @@ -52,154 +53,27 @@ struct _CcLanguageChooser { G_DEFINE_TYPE (CcLanguageChooser, cc_language_chooser, GTK_TYPE_DIALOG) -static gchar * -get_language_label (const gchar *language_code, - const gchar *modifier, - const gchar *locale_id) -{ - g_autofree gchar *language = NULL; - - language = gnome_get_language_from_code (language_code, locale_id); - - if (modifier == NULL) - return g_steal_pointer (&language); - else { - g_autofree gchar *t_mod = gnome_get_translated_modifier (modifier, locale_id); - return g_strdup_printf ("%s — %s", language, t_mod); - } -} - -static GtkWidget * -language_widget_new (const gchar *locale_id, - gboolean is_extra) -{ - g_autofree gchar *language_code = NULL; - g_autofree gchar *country_code = NULL; - g_autofree gchar *language = NULL; - g_autofree gchar *country = NULL; - g_autofree gchar *language_local = NULL; - g_autofree gchar *country_local = NULL; - g_autofree gchar *modifier = NULL; - GtkWidget *row; - GtkWidget *box; - GtkWidget *language_label; - GtkWidget *check; - GtkWidget *country_label; - - gnome_parse_locale (locale_id, &language_code, &country_code, NULL, &modifier); - language = get_language_label (language_code, modifier, locale_id); - country = gnome_get_country_from_code (country_code, locale_id); - language_local = get_language_label (language_code, modifier, NULL); - country_local = gnome_get_country_from_code (country_code, NULL); - - row = gtk_list_box_row_new (); - - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); - gtk_widget_show (box); - gtk_widget_set_margin_top (box, 12); - gtk_widget_set_margin_bottom (box, 12); - gtk_widget_set_margin_start (box, 18); - gtk_widget_set_margin_end (box, 18); - gtk_container_add (GTK_CONTAINER (row), box); - - language_label = gtk_label_new (language); - gtk_widget_show (language_label); - gtk_label_set_xalign (GTK_LABEL (language_label), 0.0); - gtk_label_set_ellipsize (GTK_LABEL (language_label), PANGO_ELLIPSIZE_END); - gtk_box_pack_start (GTK_BOX (box), language_label, FALSE, TRUE, 0); - - check = gtk_image_new (); - gtk_widget_hide (check); - gtk_image_set_from_icon_name (GTK_IMAGE (check), "object-select-symbolic", GTK_ICON_SIZE_MENU); - g_object_set (check, "icon-size", GTK_ICON_SIZE_MENU, NULL); - gtk_box_pack_start (GTK_BOX (box), check, FALSE, FALSE, 0); - - country_label = gtk_label_new (country); - gtk_widget_show (country_label); - gtk_label_set_xalign (GTK_LABEL (country_label), 1.0); - gtk_label_set_ellipsize (GTK_LABEL (country_label), PANGO_ELLIPSIZE_END); - gtk_style_context_add_class (gtk_widget_get_style_context (country_label), "dim-label"); - gtk_box_pack_start (GTK_BOX (box), country_label, TRUE, TRUE, 0); - - g_object_set_data (G_OBJECT (row), "check", check); - g_object_set_data_full (G_OBJECT (row), "locale-id", g_strdup (locale_id), g_free); - g_object_set_data_full (G_OBJECT (row), "language", g_steal_pointer (&language), g_free); - g_object_set_data_full (G_OBJECT (row), "country", g_steal_pointer (&country), g_free); - g_object_set_data_full (G_OBJECT (row), "language-local", g_steal_pointer (&language_local), g_free); - g_object_set_data_full (G_OBJECT (row), "country-local", g_steal_pointer (&country_local), g_free); - g_object_set_data (G_OBJECT (row), "is-extra", GUINT_TO_POINTER (is_extra)); - - return row; -} - -static GtkListBoxRow * -more_widget_new (void) -{ - GtkWidget *box, *row; - GtkWidget *arrow; - - row = gtk_list_box_row_new (); - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); - gtk_widget_show (box); - gtk_container_add (GTK_CONTAINER (row), box); - gtk_widget_set_tooltip_text (box, _("More…")); - - arrow = gtk_image_new_from_icon_name ("view-more-symbolic", GTK_ICON_SIZE_MENU); - gtk_widget_show (arrow); - gtk_style_context_add_class (gtk_widget_get_style_context (arrow), "dim-label"); - gtk_widget_set_margin_top (box, 10); - gtk_widget_set_margin_bottom (box, 10); - gtk_box_pack_start (GTK_BOX (box), arrow, TRUE, TRUE, 0); - - return GTK_LIST_BOX_ROW (row); -} - -static GtkWidget * -no_results_widget_new (void) -{ - GtkWidget *widget; - - widget = gtk_label_new (_("No languages found")); - gtk_widget_set_sensitive (widget, FALSE); - return widget; -} - static void -add_languages (CcLanguageChooser *chooser, - gchar **locale_ids, - GHashTable *initial) +add_all_languages (CcLanguageChooser *self) { - while (*locale_ids) { - gchar *locale_id; - gboolean is_initial; - GtkWidget *widget; + g_auto(GStrv) locale_ids = NULL; + g_autoptr(GHashTable) initial = NULL; - locale_id = *locale_ids; - locale_ids ++; + locale_ids = gnome_get_all_locales (); + initial = cc_common_language_get_initial_languages (); + for (int i = 0; locale_ids[i] != NULL; i++) { + CcLanguageRow *row; + gboolean is_initial; - if (!cc_common_language_has_font (locale_id)) + if (!cc_common_language_has_font (locale_ids[i])) continue; - is_initial = (g_hash_table_lookup (initial, locale_id) != NULL); - widget = language_widget_new (locale_id, !is_initial); - gtk_widget_show (widget); - gtk_container_add (GTK_CONTAINER (chooser->language_listbox), widget); + row = cc_language_row_new (locale_ids[i]); + gtk_widget_show (GTK_WIDGET (row)); + is_initial = (g_hash_table_lookup (initial, locale_ids[i]) != NULL); + cc_language_row_set_is_extra (row, !is_initial); + gtk_list_box_prepend (self->language_listbox, GTK_WIDGET (row)); } - - gtk_container_add (GTK_CONTAINER (chooser->language_listbox), GTK_WIDGET (chooser->more_item)); -} - -static void -add_all_languages (CcLanguageChooser *chooser) -{ - gchar **locale_ids; - GHashTable *initial; - - locale_ids = gnome_get_all_locales (); - initial = cc_common_language_get_initial_languages (); - add_languages (chooser, locale_ids, initial); - g_hash_table_destroy (initial); - g_strfreev (locale_ids); } static gboolean @@ -222,46 +96,46 @@ static gboolean language_visible (GtkListBoxRow *row, gpointer user_data) { - CcLanguageChooser *chooser = user_data; + CcLanguageChooser *self = user_data; g_autofree gchar *language = NULL; g_autofree gchar *country = NULL; g_autofree gchar *language_local = NULL; g_autofree gchar *country_local = NULL; - gboolean is_extra; gboolean visible; - if (row == chooser->more_item) - return !chooser->showing_extra; + if (row == self->more_row) + return !self->showing_extra; - is_extra = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (row), "is-extra")); + if (!CC_IS_LANGUAGE_ROW (row)) + return TRUE; - if (!chooser->showing_extra && is_extra) + if (!self->showing_extra && cc_language_row_get_is_extra (CC_LANGUAGE_ROW (row))) return FALSE; - if (!chooser->filter_words) + if (!self->filter_words) return TRUE; language = - cc_util_normalize_casefold_and_unaccent (g_object_get_data (G_OBJECT (row), "language")); - visible = match_all (chooser->filter_words, language); + cc_util_normalize_casefold_and_unaccent (cc_language_row_get_language (CC_LANGUAGE_ROW (row))); + visible = match_all (self->filter_words, language); if (visible) return TRUE; country = - cc_util_normalize_casefold_and_unaccent (g_object_get_data (G_OBJECT (row), "country")); - visible = match_all (chooser->filter_words, country); + cc_util_normalize_casefold_and_unaccent (cc_language_row_get_country (CC_LANGUAGE_ROW (row))); + visible = match_all (self->filter_words, country); if (visible) return TRUE; language_local = - cc_util_normalize_casefold_and_unaccent (g_object_get_data (G_OBJECT (row), "language-local")); - visible = match_all (chooser->filter_words, language_local); + cc_util_normalize_casefold_and_unaccent (cc_language_row_get_language_local (CC_LANGUAGE_ROW (row))); + visible = match_all (self->filter_words, language_local); if (visible) return TRUE; country_local = - cc_util_normalize_casefold_and_unaccent (g_object_get_data (G_OBJECT (row), "country-local")); - return match_all (chooser->filter_words, country_local); + cc_util_normalize_casefold_and_unaccent (cc_language_row_get_country_local (CC_LANGUAGE_ROW (row))); + return match_all (self->filter_words, country_local); } static gint @@ -269,182 +143,153 @@ sort_languages (GtkListBoxRow *a, GtkListBoxRow *b, gpointer data) { - const gchar *la, *lb, *ca, *cb; int d; - if (g_object_get_data (G_OBJECT (a), "locale-id") == NULL) + if (!CC_IS_LANGUAGE_ROW (a)) return 1; - if (g_object_get_data (G_OBJECT (b), "locale-id") == NULL) + if (!CC_IS_LANGUAGE_ROW (b)) return -1; - la = g_object_get_data (G_OBJECT (a), "language"); - lb = g_object_get_data (G_OBJECT (b), "language"); - d = g_strcmp0 (la, lb); + d = g_strcmp0 (cc_language_row_get_language (CC_LANGUAGE_ROW (a)), cc_language_row_get_language (CC_LANGUAGE_ROW (b))); if (d != 0) return d; - ca = g_object_get_data (G_OBJECT (a), "country"); - cb = g_object_get_data (G_OBJECT (b), "country"); - return g_strcmp0 (ca, cb); + return g_strcmp0 (cc_language_row_get_country (CC_LANGUAGE_ROW (a)), cc_language_row_get_country (CC_LANGUAGE_ROW (b))); } static void -filter_changed (CcLanguageChooser *chooser) +language_filter_entry_search_changed_cb (CcLanguageChooser *self) { g_autofree gchar *filter_contents = NULL; - g_clear_pointer (&chooser->filter_words, g_strfreev); + g_clear_pointer (&self->filter_words, g_strfreev); filter_contents = - cc_util_normalize_casefold_and_unaccent (gtk_entry_get_text (GTK_ENTRY (chooser->language_filter_entry))); + cc_util_normalize_casefold_and_unaccent (gtk_entry_get_text (GTK_ENTRY (self->language_filter_entry))); if (!filter_contents) { - gtk_list_box_invalidate_filter (GTK_LIST_BOX (chooser->language_listbox)); - gtk_list_box_set_placeholder (GTK_LIST_BOX (chooser->language_listbox), NULL); + gtk_list_box_invalidate_filter (self->language_listbox); return; } - chooser->filter_words = g_strsplit_set (g_strstrip (filter_contents), " ", 0); - gtk_list_box_set_placeholder (GTK_LIST_BOX (chooser->language_listbox), chooser->no_results); - gtk_list_box_invalidate_filter (GTK_LIST_BOX (chooser->language_listbox)); + self->filter_words = g_strsplit_set (g_strstrip (filter_contents), " ", 0); + gtk_list_box_invalidate_filter (self->language_listbox); } static void -show_more (CcLanguageChooser *chooser, gboolean visible) +show_more (CcLanguageChooser *self, gboolean visible) { gint width, height; - gtk_window_get_size (GTK_WINDOW (chooser), &width, &height); - gtk_widget_set_size_request (GTK_WIDGET (chooser), width, height); + gtk_window_get_size (GTK_WINDOW (self), &width, &height); + gtk_widget_set_size_request (GTK_WIDGET (self), width, height); - gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (chooser->search_bar), visible); - gtk_widget_grab_focus (visible ? chooser->language_filter_entry : chooser->language_listbox); + gtk_search_bar_set_search_mode (self->search_bar, visible); + gtk_widget_grab_focus (visible ? GTK_WIDGET (self->language_filter_entry) : GTK_WIDGET (self->language_listbox)); - chooser->showing_extra = visible; + self->showing_extra = visible; - gtk_list_box_invalidate_filter (GTK_LIST_BOX (chooser->language_listbox)); + gtk_list_box_invalidate_filter (self->language_listbox); } static void -set_locale_id (CcLanguageChooser *chooser, +set_locale_id (CcLanguageChooser *self, const gchar *locale_id) { g_autoptr(GList) children = NULL; GList *l; - gtk_widget_set_sensitive (chooser->select_button, FALSE); + gtk_widget_set_sensitive (GTK_WIDGET (self->select_button), FALSE); - children = gtk_container_get_children (GTK_CONTAINER (chooser->language_listbox)); + children = gtk_container_get_children (GTK_CONTAINER (self->language_listbox)); for (l = children; l; l = l->next) { - GtkWidget *row = l->data; - GtkWidget *check = g_object_get_data (G_OBJECT (row), "check"); - const gchar *language = g_object_get_data (G_OBJECT (row), "locale-id"); - if (check == NULL || language == NULL) - continue; + GtkListBoxRow *row = l->data; - if (g_strcmp0 (locale_id, language) == 0) { - gboolean is_extra; + if (!CC_IS_LANGUAGE_ROW (row)) + continue; - gtk_widget_show (check); - gtk_widget_set_sensitive (chooser->select_button, TRUE); + if (g_strcmp0 (locale_id, cc_language_row_get_locale_id (CC_LANGUAGE_ROW (row))) == 0) { + cc_language_row_set_checked (CC_LANGUAGE_ROW (row), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (self->select_button), TRUE); /* make sure the selected language is shown */ - is_extra = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (row), "is-extra")); - if (!chooser->showing_extra && is_extra) { - g_object_set_data (G_OBJECT (row), "is-extra", GINT_TO_POINTER (FALSE)); - gtk_list_box_invalidate_filter (GTK_LIST_BOX (chooser->language_listbox)); + if (!self->showing_extra && cc_language_row_get_is_extra (CC_LANGUAGE_ROW (row))) { + cc_language_row_set_is_extra (CC_LANGUAGE_ROW (row), FALSE); + gtk_list_box_invalidate_filter (self->language_listbox); } } else { - gtk_widget_hide (check); + cc_language_row_set_checked (CC_LANGUAGE_ROW (row), FALSE); } } - g_free (chooser->language); - chooser->language = g_strdup (locale_id); + g_free (self->language); + self->language = g_strdup (locale_id); } static void -row_activated (CcLanguageChooser *chooser, - GtkListBoxRow *row) +language_listbox_row_activated_cb (CcLanguageChooser *self, GtkListBoxRow *row) { - gchar *new_locale_id; + const gchar *new_locale_id; - if (row == NULL) + if (row == self->more_row) { + show_more (self, TRUE); return; + } - if (row == chooser->more_item) { - show_more (chooser, TRUE); + if (!CC_IS_LANGUAGE_ROW (row)) return; - } - new_locale_id = g_object_get_data (G_OBJECT (row), "locale-id"); - if (g_strcmp0 (new_locale_id, chooser->language) == 0) { - gtk_dialog_response (GTK_DIALOG (chooser), - gtk_dialog_get_response_for_widget (GTK_DIALOG (chooser), - chooser->select_button)); + + new_locale_id = cc_language_row_get_locale_id (CC_LANGUAGE_ROW (row)); + if (g_strcmp0 (new_locale_id, self->language) == 0) { + gtk_dialog_response (GTK_DIALOG (self), + gtk_dialog_get_response_for_widget (GTK_DIALOG (self), + GTK_WIDGET (self->select_button))); } else { - set_locale_id (chooser, new_locale_id); + set_locale_id (self, new_locale_id); } } static void -activate_default (CcLanguageChooser *chooser) +activate_default_cb (CcLanguageChooser *self) { GtkWidget *focus; - gchar *locale_id; - focus = gtk_window_get_focus (GTK_WINDOW (chooser)); - if (!focus) + focus = gtk_window_get_focus (GTK_WINDOW (self)); + if (!focus || !CC_IS_LANGUAGE_ROW (focus)) return; - locale_id = g_object_get_data (G_OBJECT (focus), "locale-id"); - if (g_strcmp0 (locale_id, chooser->language) == 0) + if (g_strcmp0 (cc_language_row_get_locale_id (CC_LANGUAGE_ROW (focus)), self->language) == 0) return; - g_signal_stop_emission_by_name (GTK_WINDOW (chooser), "activate-default"); + g_signal_stop_emission_by_name (GTK_WINDOW (self), "activate-default"); gtk_widget_activate (focus); } void -cc_language_chooser_init (CcLanguageChooser *chooser) +cc_language_chooser_init (CcLanguageChooser *self) { g_resources_register (cc_common_get_resource ()); - gtk_widget_init_template (GTK_WIDGET (chooser)); + gtk_widget_init_template (GTK_WIDGET (self)); - chooser->more_item = more_widget_new (); - gtk_widget_show (GTK_WIDGET (chooser->more_item)); - /* We ref-sink here so we can reuse this widget multiple times */ - chooser->no_results = g_object_ref_sink (no_results_widget_new ()); - gtk_widget_show (chooser->no_results); - - gtk_list_box_set_sort_func (GTK_LIST_BOX (chooser->language_listbox), - sort_languages, chooser, NULL); - gtk_list_box_set_filter_func (GTK_LIST_BOX (chooser->language_listbox), - language_visible, chooser, NULL); - gtk_list_box_set_selection_mode (GTK_LIST_BOX (chooser->language_listbox), + gtk_list_box_set_sort_func (self->language_listbox, + sort_languages, self, NULL); + gtk_list_box_set_filter_func (self->language_listbox, + language_visible, self, NULL); + gtk_list_box_set_selection_mode (self->language_listbox, GTK_SELECTION_NONE); - gtk_list_box_set_header_func (GTK_LIST_BOX (chooser->language_listbox), + gtk_list_box_set_header_func (self->language_listbox, cc_list_box_update_header_func, NULL, NULL); - add_all_languages (chooser); - - g_signal_connect_object (chooser->language_filter_entry, "search-changed", - G_CALLBACK (filter_changed), chooser, G_CONNECT_SWAPPED); - - g_signal_connect_object (chooser->language_listbox, "row-activated", - G_CALLBACK (row_activated), chooser, G_CONNECT_SWAPPED); + add_all_languages (self); - gtk_list_box_invalidate_filter (GTK_LIST_BOX (chooser->language_listbox)); - - g_signal_connect (chooser, "activate-default", - G_CALLBACK (activate_default), NULL); + gtk_list_box_invalidate_filter (self->language_listbox); } static void cc_language_chooser_dispose (GObject *object) { - CcLanguageChooser *chooser = CC_LANGUAGE_CHOOSER (object); + CcLanguageChooser *self = CC_LANGUAGE_CHOOSER (object); - g_clear_object (&chooser->no_results); - g_clear_pointer (&chooser->filter_words, g_strfreev); - g_clear_pointer (&chooser->language, g_free); + g_clear_pointer (&self->filter_words, g_strfreev); + g_clear_pointer (&self->language, g_free); G_OBJECT_CLASS (cc_language_chooser_parent_class)->dispose (object); } @@ -459,10 +304,15 @@ cc_language_chooser_class_init (CcLanguageChooserClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/common/cc-language-chooser.ui"); - gtk_widget_class_bind_template_child (widget_class, CcLanguageChooser, select_button); - gtk_widget_class_bind_template_child (widget_class, CcLanguageChooser, search_bar); gtk_widget_class_bind_template_child (widget_class, CcLanguageChooser, language_filter_entry); gtk_widget_class_bind_template_child (widget_class, CcLanguageChooser, language_listbox); + gtk_widget_class_bind_template_child (widget_class, CcLanguageChooser, more_row); + gtk_widget_class_bind_template_child (widget_class, CcLanguageChooser, search_bar); + gtk_widget_class_bind_template_child (widget_class, CcLanguageChooser, select_button); + + gtk_widget_class_bind_template_callback (widget_class, activate_default_cb); + gtk_widget_class_bind_template_callback (widget_class, language_filter_entry_search_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, language_listbox_row_activated_cb); } CcLanguageChooser * @@ -474,24 +324,24 @@ cc_language_chooser_new (void) } void -cc_language_chooser_clear_filter (CcLanguageChooser *chooser) +cc_language_chooser_clear_filter (CcLanguageChooser *self) { - g_return_if_fail (CC_IS_LANGUAGE_CHOOSER (chooser)); - gtk_entry_set_text (GTK_ENTRY (chooser->language_filter_entry), ""); - show_more (chooser, FALSE); + g_return_if_fail (CC_IS_LANGUAGE_CHOOSER (self)); + gtk_entry_set_text (GTK_ENTRY (self->language_filter_entry), ""); + show_more (self, FALSE); } const gchar * -cc_language_chooser_get_language (CcLanguageChooser *chooser) +cc_language_chooser_get_language (CcLanguageChooser *self) { - g_return_val_if_fail (CC_IS_LANGUAGE_CHOOSER (chooser), NULL); - return chooser->language; + g_return_val_if_fail (CC_IS_LANGUAGE_CHOOSER (self), NULL); + return self->language; } void -cc_language_chooser_set_language (CcLanguageChooser *chooser, +cc_language_chooser_set_language (CcLanguageChooser *self, const gchar *language) { - g_return_if_fail (CC_IS_LANGUAGE_CHOOSER (chooser)); - set_locale_id (chooser, language); + g_return_if_fail (CC_IS_LANGUAGE_CHOOSER (self)); + set_locale_id (self, language); } diff --git a/panels/common/cc-language-chooser.ui b/panels/common/cc-language-chooser.ui index 6b61d552085c2d40028844be0d2228b388bda413..5449fb3dd6cf9d603b9f4bdddc9a1b44ad5a63e4 100644 --- a/panels/common/cc-language-chooser.ui +++ b/panels/common/cc-language-chooser.ui @@ -7,6 +7,7 @@ True 340 475 + _Select @@ -42,6 +43,7 @@ True 30 + @@ -60,6 +62,35 @@ True fill fill + + + + True + No languages found + False + + + + + + True + 10 + More… + + + False + view-more-symbolic + 1 + 10 + 10 + + + + + + diff --git a/panels/common/cc-language-row.c b/panels/common/cc-language-row.c new file mode 100644 index 0000000000000000000000000000000000000000..3b962056157af95aed856d3ec76b67193d43a45c --- /dev/null +++ b/panels/common/cc-language-row.c @@ -0,0 +1,176 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2020 Canonical Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "cc-language-row.h" +#include "cc-common-resources.h" + +#define GNOME_DESKTOP_USE_UNSTABLE_API +#include + +struct _CcLanguageRow { + GtkListBoxRow parent_instance; + + GtkImage *check_image; + GtkLabel *country_label; + GtkLabel *language_label; + + gchar *locale_id; + gchar *language; + gchar *language_local; + gchar *country; + gchar *country_local; + + gboolean is_extra; +}; + +G_DEFINE_TYPE (CcLanguageRow, cc_language_row, GTK_TYPE_LIST_BOX_ROW) + +static gchar * +get_language_label (const gchar *language_code, + const gchar *modifier, + const gchar *locale_id) +{ + g_autofree gchar *language = NULL; + + language = gnome_get_language_from_code (language_code, locale_id); + + if (modifier == NULL) + return g_steal_pointer (&language); + else + { + g_autofree gchar *t_mod = gnome_get_translated_modifier (modifier, locale_id); + return g_strdup_printf ("%s — %s", language, t_mod); + } +} + +static void +cc_language_row_dispose (GObject *object) +{ + CcLanguageRow *self = CC_LANGUAGE_ROW (object); + + g_clear_pointer (&self->locale_id, g_free); + g_clear_pointer (&self->country, g_free); + g_clear_pointer (&self->country_local, g_free); + g_clear_pointer (&self->language, g_free); + g_clear_pointer (&self->language_local, g_free); + + G_OBJECT_CLASS (cc_language_row_parent_class)->dispose (object); +} + +void +cc_language_row_class_init (CcLanguageRowClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->dispose = cc_language_row_dispose; + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/common/cc-language-row.ui"); + + gtk_widget_class_bind_template_child (widget_class, CcLanguageRow, check_image); + gtk_widget_class_bind_template_child (widget_class, CcLanguageRow, country_label); + gtk_widget_class_bind_template_child (widget_class, CcLanguageRow, language_label); +} + +void +cc_language_row_init (CcLanguageRow *self) +{ + g_resources_register (cc_common_get_resource ()); + + gtk_widget_init_template (GTK_WIDGET (self)); +} + +CcLanguageRow * +cc_language_row_new (const gchar *locale_id) +{ + CcLanguageRow *self; + g_autofree gchar *language_code = NULL; + g_autofree gchar *country_code = NULL; + g_autofree gchar *modifier = NULL; + + self = CC_LANGUAGE_ROW (g_object_new (CC_TYPE_LANGUAGE_ROW, NULL)); + self->locale_id = g_strdup (locale_id); + + gnome_parse_locale (locale_id, &language_code, &country_code, NULL, &modifier); + + self->language = get_language_label (language_code, modifier, locale_id); + self->language_local = get_language_label (language_code, modifier, NULL); + gtk_label_set_label (self->language_label, self->language); + + self->country = gnome_get_country_from_code (country_code, locale_id); + self->country_local = gnome_get_country_from_code (country_code, NULL); + gtk_label_set_label (self->country_label, self->country); + + return self; +} + +const gchar * +cc_language_row_get_locale_id (CcLanguageRow *self) +{ + g_return_val_if_fail (CC_IS_LANGUAGE_ROW (self), NULL); + return self->locale_id; +} + +const gchar * +cc_language_row_get_language (CcLanguageRow *self) +{ + g_return_val_if_fail (CC_IS_LANGUAGE_ROW (self), NULL); + return self->language; +} + +const gchar * +cc_language_row_get_language_local (CcLanguageRow *self) +{ + g_return_val_if_fail (CC_IS_LANGUAGE_ROW (self), NULL); + return self->language_local; +} + +const gchar * +cc_language_row_get_country (CcLanguageRow *self) +{ + g_return_val_if_fail (CC_IS_LANGUAGE_ROW (self), NULL); + return self->country; +} + +const gchar * +cc_language_row_get_country_local (CcLanguageRow *self) +{ + g_return_val_if_fail (CC_IS_LANGUAGE_ROW (self), NULL); + return self->country_local; +} + +void +cc_language_row_set_checked (CcLanguageRow *self, gboolean checked) +{ + g_return_if_fail (CC_IS_LANGUAGE_ROW (self)); + gtk_widget_set_visible (GTK_WIDGET (self->check_image), checked); +} + +void +cc_language_row_set_is_extra (CcLanguageRow *self, gboolean is_extra) +{ + g_return_if_fail (CC_IS_LANGUAGE_ROW (self)); + self->is_extra = is_extra; +} + +gboolean +cc_language_row_get_is_extra (CcLanguageRow *self) +{ + g_return_val_if_fail (CC_IS_LANGUAGE_ROW (self), FALSE); + return self->is_extra; +} diff --git a/panels/common/cc-language-row.h b/panels/common/cc-language-row.h new file mode 100644 index 0000000000000000000000000000000000000000..2e3e8cdc3253f7de8b7b764fe1b0d5ccc7be4336 --- /dev/null +++ b/panels/common/cc-language-row.h @@ -0,0 +1,46 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2020 Canonical Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +#define CC_TYPE_LANGUAGE_ROW (cc_language_row_get_type ()) +G_DECLARE_FINAL_TYPE (CcLanguageRow, cc_language_row, CC, LANGUAGE_ROW, GtkListBoxRow) + +CcLanguageRow *cc_language_row_new (const gchar *locale_id); + +const gchar *cc_language_row_get_locale_id (CcLanguageRow *row); + +const gchar *cc_language_row_get_language (CcLanguageRow *row); + +const gchar *cc_language_row_get_language_local (CcLanguageRow *row); + +const gchar *cc_language_row_get_country (CcLanguageRow *row); + +const gchar *cc_language_row_get_country_local (CcLanguageRow *row); + +void cc_language_row_set_checked (CcLanguageRow *row, gboolean checked); + +void cc_language_row_set_is_extra (CcLanguageRow *row, gboolean is_extra); + +gboolean cc_language_row_get_is_extra (CcLanguageRow *row); + +G_END_DECLS diff --git a/panels/common/cc-language-row.ui b/panels/common/cc-language-row.ui new file mode 100644 index 0000000000000000000000000000000000000000..3f2d67b68d9ce26806d796d45f83a65d08f86884 --- /dev/null +++ b/panels/common/cc-language-row.ui @@ -0,0 +1,41 @@ + + + + + diff --git a/panels/common/common.gresource.xml b/panels/common/common.gresource.xml index 9620dc1102786bdf9ecf7a6d8decc118665c6835..b8c2946317ef5fd600d3255ae21cf3de7dd58abd 100644 --- a/panels/common/common.gresource.xml +++ b/panels/common/common.gresource.xml @@ -2,6 +2,7 @@ cc-language-chooser.ui + cc-language-row.ui cc-list-row.ui cc-time-editor.ui cc-permission-infobar.ui diff --git a/panels/common/meson.build b/panels/common/meson.build index 85fabf21e14ebd02a60863f7f6f413fb84b60ad7..bf22b15397d17b25e176eeee4a893978a65be77a 100644 --- a/panels/common/meson.build +++ b/panels/common/meson.build @@ -46,6 +46,7 @@ libwidgets_dep = declare_dependency( sources = common_sources + files( 'cc-common-language.c', 'cc-language-chooser.c', + 'cc-language-row.c', 'cc-list-row.c', 'cc-time-editor.c', 'cc-permission-infobar.c', @@ -54,6 +55,7 @@ sources = common_sources + files( resource_data = files( 'cc-language-chooser.ui', + 'cc-language-row.ui', 'cc-list-row.ui', 'cc-time-editor.ui', 'cc-permission-infobar.ui',