1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimplanguagestore.c
5  * Copyright (C) 2008, 2009  Sven Neumann <sven@gimp.org>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include <string.h>
24 
25 #include <gtk/gtk.h>
26 
27 #include "widgets-types.h"
28 
29 #include "gimplanguagestore.h"
30 #include "gimplanguagestore-parser.h"
31 
32 
33 static void   gimp_language_store_constructed (GObject           *object);
34 
35 static void   gimp_language_store_real_add    (GimpLanguageStore *store,
36                                                const gchar       *label,
37                                                const gchar       *code);
38 
39 static gint   gimp_language_store_sort        (GtkTreeModel      *model,
40                                                GtkTreeIter       *a,
41                                                GtkTreeIter       *b,
42                                                gpointer           userdata);
43 
44 
G_DEFINE_TYPE(GimpLanguageStore,gimp_language_store,GTK_TYPE_LIST_STORE)45 G_DEFINE_TYPE (GimpLanguageStore, gimp_language_store, GTK_TYPE_LIST_STORE)
46 
47 #define parent_class gimp_language_store_parent_class
48 
49 
50 static void
51 gimp_language_store_class_init (GimpLanguageStoreClass *klass)
52 {
53   GObjectClass *object_class = G_OBJECT_CLASS (klass);
54 
55   object_class->constructed = gimp_language_store_constructed;
56 
57   klass->add                = gimp_language_store_real_add;
58 }
59 
60 static void
gimp_language_store_init(GimpLanguageStore * store)61 gimp_language_store_init (GimpLanguageStore *store)
62 {
63   GType column_types[2] = { G_TYPE_STRING, G_TYPE_STRING };
64 
65   gtk_list_store_set_column_types (GTK_LIST_STORE (store),
66                                    G_N_ELEMENTS (column_types), column_types);
67 
68   gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store),
69                                    GIMP_LANGUAGE_STORE_LABEL,
70                                    gimp_language_store_sort, NULL, NULL);
71   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
72                                         GIMP_LANGUAGE_STORE_LABEL,
73                                         GTK_SORT_ASCENDING);
74 }
75 
76 static void
gimp_language_store_constructed(GObject * object)77 gimp_language_store_constructed (GObject *object)
78 {
79   GHashTable     *lang_list;
80   GHashTableIter  lang_iter;
81   gpointer        code;
82   gpointer        name;
83 
84   G_OBJECT_CLASS (parent_class)->constructed (object);
85 
86   lang_list = gimp_language_store_parser_get_languages (FALSE);
87   g_return_if_fail (lang_list != NULL);
88 
89   g_hash_table_iter_init (&lang_iter, lang_list);
90 
91   while (g_hash_table_iter_next (&lang_iter, &code, &name))
92     GIMP_LANGUAGE_STORE_GET_CLASS (object)->add (GIMP_LANGUAGE_STORE (object),
93                                                  name, code);
94 }
95 
96 static void
gimp_language_store_real_add(GimpLanguageStore * store,const gchar * label,const gchar * code)97 gimp_language_store_real_add (GimpLanguageStore *store,
98                               const gchar       *label,
99                               const gchar       *code)
100 {
101   GtkTreeIter iter;
102 
103   gtk_list_store_append (GTK_LIST_STORE (store), &iter);
104   gtk_list_store_set (GTK_LIST_STORE (store), &iter,
105                       GIMP_LANGUAGE_STORE_LABEL, label,
106                       GIMP_LANGUAGE_STORE_CODE,  code,
107                       -1);
108 }
109 
110 static gint
gimp_language_store_sort(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer userdata)111 gimp_language_store_sort (GtkTreeModel *model,
112                           GtkTreeIter  *a,
113                           GtkTreeIter  *b,
114                           gpointer      userdata)
115 {
116   GValue avalue = G_VALUE_INIT;
117   GValue bvalue = G_VALUE_INIT;
118   gint   cmp    = 0;
119 
120   /*  keep system language at the top of the list  */
121   gtk_tree_model_get_value (model, a, GIMP_LANGUAGE_STORE_CODE, &avalue);
122   gtk_tree_model_get_value (model, b, GIMP_LANGUAGE_STORE_CODE, &bvalue);
123 
124   if (g_strcmp0 ("", g_value_get_string (&avalue)) == 0)
125     cmp = -1;
126 
127   if (g_strcmp0 ("", g_value_get_string (&bvalue)) == 0)
128     cmp = 1;
129 
130   g_value_unset (&avalue);
131   g_value_unset (&bvalue);
132 
133   if (cmp)
134     return cmp;
135 
136   /*  sort labels alphabetically  */
137   gtk_tree_model_get_value (model, a, GIMP_LANGUAGE_STORE_LABEL, &avalue);
138   gtk_tree_model_get_value (model, b, GIMP_LANGUAGE_STORE_LABEL, &bvalue);
139 
140   cmp = g_utf8_collate (g_value_get_string (&avalue),
141                         g_value_get_string (&bvalue));
142 
143   g_value_unset (&avalue);
144   g_value_unset (&bvalue);
145 
146   return cmp;
147 }
148 
149 GtkListStore *
gimp_language_store_new(void)150 gimp_language_store_new (void)
151 {
152   return g_object_new (GIMP_TYPE_LANGUAGE_STORE, NULL);
153 }
154 
155 gboolean
gimp_language_store_lookup(GimpLanguageStore * store,const gchar * code,GtkTreeIter * iter)156 gimp_language_store_lookup (GimpLanguageStore *store,
157                             const gchar       *code,
158                             GtkTreeIter       *iter)
159 {
160   GtkTreeModel *model;
161   const gchar  *hyphen;
162   gint          len;
163   gboolean      iter_valid;
164 
165   g_return_val_if_fail (GIMP_IS_LANGUAGE_STORE (store), FALSE);
166   g_return_val_if_fail (code != NULL, FALSE);
167   g_return_val_if_fail (iter != NULL, FALSE);
168 
169   /*  We accept the code in RFC-3066 format here and only look at what's
170    *  before the first hyphen.
171    */
172   hyphen = strchr (code, '-');
173 
174   if (hyphen)
175     len = hyphen - code;
176   else
177     len = strlen (code);
178 
179   model = GTK_TREE_MODEL (store);
180 
181   for (iter_valid = gtk_tree_model_get_iter_first (model, iter);
182        iter_valid;
183        iter_valid = gtk_tree_model_iter_next (model, iter))
184     {
185       gchar *value;
186 
187       gtk_tree_model_get (model, iter,
188                           GIMP_LANGUAGE_STORE_CODE, &value,
189                           -1);
190 
191       if (value && strncmp (code, value, len) == 0)
192         {
193           g_free (value);
194           break;
195         }
196 
197       g_free (value);
198     }
199 
200   return iter_valid;
201 }
202