Updated Hungarian translation
[evolution.git] / e-util / e-table-extras.c
blob43fca94435ed6a0b2e6497a747280b3f32e082ab
1 /*
2 * e-table-extras.c - Set of hash table sort of thingies.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 * Authors:
18 * Chris Lahey <clahey@ximian.com>
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include <stdlib.h>
29 #include <string.h>
31 #include <gtk/gtk.h>
33 #include "e-cell-checkbox.h"
34 #include "e-cell-date.h"
35 #include "e-cell-number.h"
36 #include "e-cell-pixbuf.h"
37 #include "e-cell-size.h"
38 #include "e-cell-text.h"
39 #include "e-cell-tree.h"
40 #include "e-table-extras.h"
41 #include "e-table-sorting-utils.h"
43 #define E_TABLE_EXTRAS_GET_PRIVATE(obj) \
44 (G_TYPE_INSTANCE_GET_PRIVATE \
45 ((obj), E_TYPE_TABLE_EXTRAS, ETableExtrasPrivate))
47 struct _ETableExtrasPrivate {
48 GHashTable *cells;
49 GHashTable *compares;
50 GHashTable *icon_names;
51 GHashTable *searches;
54 G_DEFINE_TYPE (
55 ETableExtras,
56 e_table_extras,
57 G_TYPE_OBJECT)
59 static void
60 ete_finalize (GObject *object)
62 ETableExtrasPrivate *priv;
64 priv = E_TABLE_EXTRAS_GET_PRIVATE (object);
66 if (priv->cells) {
67 g_hash_table_destroy (priv->cells);
68 priv->cells = NULL;
71 if (priv->compares) {
72 g_hash_table_destroy (priv->compares);
73 priv->compares = NULL;
76 if (priv->searches) {
77 g_hash_table_destroy (priv->searches);
78 priv->searches = NULL;
81 if (priv->icon_names) {
82 g_hash_table_destroy (priv->icon_names);
83 priv->icon_names = NULL;
86 G_OBJECT_CLASS (e_table_extras_parent_class)->finalize (object);
89 static void
90 e_table_extras_class_init (ETableExtrasClass *class)
92 GObjectClass *object_class;
94 g_type_class_add_private (class, sizeof (ETableExtrasPrivate));
96 object_class = G_OBJECT_CLASS (class);
97 object_class->finalize = ete_finalize;
100 static gint
101 e_strint_compare (gconstpointer data1,
102 gconstpointer data2)
104 gint int1 = atoi (data1);
105 gint int2 = atoi (data2);
107 return e_int_compare (GINT_TO_POINTER (int1), GINT_TO_POINTER (int2));
110 static gint
111 e_int64ptr_compare (gconstpointer data1,
112 gconstpointer data2)
114 const gint64 *pa = data1, *pb = data2;
116 if (pa && pb)
117 return (*pa == *pb) ? 0 : (*pa < *pb) ? -1 : 1;
119 /* sort unset values before set */
120 return (!pa && !pb) ? 0 : (pa ? 1 : -1);
123 /* UTF-8 strncasecmp - not optimized */
125 static gint
126 g_utf8_strncasecmp (const gchar *s1,
127 const gchar *s2,
128 guint n)
130 gunichar c1, c2;
132 g_return_val_if_fail (s1 != NULL && g_utf8_validate (s1, -1, NULL), 0);
133 g_return_val_if_fail (s2 != NULL && g_utf8_validate (s2, -1, NULL), 0);
135 while (n && *s1 && *s2)
138 n -= 1;
140 c1 = g_unichar_tolower (g_utf8_get_char (s1));
141 c2 = g_unichar_tolower (g_utf8_get_char (s2));
143 /* Collation is locale-dependent, so this
144 * totally fails to do the right thing. */
145 if (c1 != c2)
146 return c1 < c2 ? -1 : 1;
148 s1 = g_utf8_next_char (s1);
149 s2 = g_utf8_next_char (s2);
152 if (n == 0 || (*s1 == '\0' && *s2 == '\0'))
153 return 0;
155 return *s1 ? 1 : -1;
158 static gboolean
159 e_string_search (gconstpointer haystack,
160 const gchar *needle)
162 gint length;
163 if (haystack == NULL)
164 return FALSE;
166 length = g_utf8_strlen (needle, -1);
167 if (g_utf8_strncasecmp (haystack, needle, length) == 0)
168 return TRUE;
169 else
170 return FALSE;
173 static gint
174 e_table_str_case_compare (gconstpointer x,
175 gconstpointer y,
176 gpointer cmp_cache)
178 const gchar *cx = NULL, *cy = NULL;
180 if (!cmp_cache)
181 return e_str_case_compare (x, y);
183 if (x == NULL || y == NULL) {
184 if (x == y)
185 return 0;
186 else
187 return x ? -1 : 1;
190 #define prepare_value(_z, _cz) \
191 _cz = e_table_sorting_utils_lookup_cmp_cache (cmp_cache, _z); \
192 if (!_cz) { \
193 gchar *tmp = g_utf8_casefold (_z, -1); \
194 _cz = g_utf8_collate_key (tmp, -1); \
195 g_free (tmp); \
197 e_table_sorting_utils_add_to_cmp_cache ( \
198 cmp_cache, _z, (gchar *) _cz); \
201 prepare_value (x, cx);
202 prepare_value (y, cy);
204 #undef prepare_value
206 return strcmp (cx, cy);
209 static gint
210 e_table_collate_compare (gconstpointer x,
211 gconstpointer y,
212 gpointer cmp_cache)
214 const gchar *cx = NULL, *cy = NULL;
216 if (!cmp_cache)
217 return e_collate_compare (x, y);
219 if (x == NULL || y == NULL) {
220 if (x == y)
221 return 0;
222 else
223 return x ? -1 : 1;
226 #define prepare_value(_z, _cz) \
227 _cz = e_table_sorting_utils_lookup_cmp_cache (cmp_cache, _z); \
228 if (!_cz) { \
229 _cz = g_utf8_collate_key (_z, -1); \
231 e_table_sorting_utils_add_to_cmp_cache ( \
232 cmp_cache, _z, (gchar *) _cz); \
235 prepare_value (x, cx);
236 prepare_value (y, cy);
238 #undef prepare_value
240 return strcmp (cx, cy);
243 static void
244 safe_unref (gpointer object)
246 if (object != NULL)
247 g_object_unref (object);
250 static void
251 e_table_extras_init (ETableExtras *extras)
253 ECell *cell, *sub_cell;
255 extras->priv = E_TABLE_EXTRAS_GET_PRIVATE (extras);
257 extras->priv->cells = g_hash_table_new_full (
258 g_str_hash, g_str_equal,
259 (GDestroyNotify) g_free,
260 (GDestroyNotify) safe_unref);
262 extras->priv->compares = g_hash_table_new_full (
263 g_str_hash, g_str_equal,
264 (GDestroyNotify) g_free,
265 (GDestroyNotify) NULL);
267 extras->priv->icon_names = g_hash_table_new_full (
268 g_str_hash, g_str_equal,
269 (GDestroyNotify) g_free,
270 (GDestroyNotify) g_free);
272 extras->priv->searches = g_hash_table_new_full (
273 g_str_hash, g_str_equal,
274 (GDestroyNotify) g_free,
275 (GDestroyNotify) NULL);
277 e_table_extras_add_compare (
278 extras, "string",
279 (GCompareDataFunc) e_str_compare);
280 e_table_extras_add_compare (
281 extras, "stringcase",
282 (GCompareDataFunc) e_table_str_case_compare);
283 e_table_extras_add_compare (
284 extras, "collate",
285 (GCompareDataFunc) e_table_collate_compare);
286 e_table_extras_add_compare (
287 extras, "integer",
288 (GCompareDataFunc) e_int_compare);
289 e_table_extras_add_compare (
290 extras, "string-integer",
291 (GCompareDataFunc) e_strint_compare);
292 e_table_extras_add_compare (
293 extras, "pointer-integer64",
294 (GCompareDataFunc) e_int64ptr_compare);
296 e_table_extras_add_search (extras, "string", e_string_search);
298 cell = e_cell_checkbox_new ();
299 e_table_extras_add_cell (extras, "checkbox", cell);
300 g_object_unref (cell);
302 cell = e_cell_date_new (NULL, GTK_JUSTIFY_LEFT);
303 e_table_extras_add_cell (extras, "date", cell);
304 g_object_unref (cell);
306 cell = e_cell_number_new (NULL, GTK_JUSTIFY_RIGHT);
307 e_table_extras_add_cell (extras, "number", cell);
308 g_object_unref (cell);
310 cell = e_cell_pixbuf_new ();
311 e_table_extras_add_cell (extras, "pixbuf", cell);
312 g_object_unref (cell);
314 cell = e_cell_size_new (NULL, GTK_JUSTIFY_RIGHT);
315 e_table_extras_add_cell (extras, "size", cell);
316 g_object_unref (cell);
318 cell = e_cell_text_new (NULL, GTK_JUSTIFY_LEFT);
319 e_table_extras_add_cell (extras, "string", cell);
320 g_object_unref (cell);
322 sub_cell = e_cell_text_new (NULL, GTK_JUSTIFY_LEFT);
323 cell = e_cell_tree_new (TRUE, sub_cell);
324 e_table_extras_add_cell (extras, "tree-string", cell);
325 g_object_unref (sub_cell);
326 g_object_unref (cell);
329 ETableExtras *
330 e_table_extras_new (void)
332 return g_object_new (E_TYPE_TABLE_EXTRAS, NULL);
335 void
336 e_table_extras_add_cell (ETableExtras *extras,
337 const gchar *id,
338 ECell *cell)
340 g_return_if_fail (E_IS_TABLE_EXTRAS (extras));
341 g_return_if_fail (id != NULL);
343 if (cell != NULL)
344 g_object_ref_sink (cell);
346 g_hash_table_insert (extras->priv->cells, g_strdup (id), cell);
349 ECell *
350 e_table_extras_get_cell (ETableExtras *extras,
351 const gchar *id)
353 g_return_val_if_fail (E_IS_TABLE_EXTRAS (extras), NULL);
354 g_return_val_if_fail (id != NULL, NULL);
356 return g_hash_table_lookup (extras->priv->cells, id);
359 void
360 e_table_extras_add_compare (ETableExtras *extras,
361 const gchar *id,
362 GCompareDataFunc compare)
364 g_return_if_fail (E_IS_TABLE_EXTRAS (extras));
365 g_return_if_fail (id != NULL);
367 g_hash_table_insert (
368 extras->priv->compares,
369 g_strdup (id), (gpointer) compare);
372 GCompareDataFunc
373 e_table_extras_get_compare (ETableExtras *extras,
374 const gchar *id)
376 g_return_val_if_fail (E_IS_TABLE_EXTRAS (extras), NULL);
377 g_return_val_if_fail (id != NULL, NULL);
379 return g_hash_table_lookup (extras->priv->compares, id);
382 void
383 e_table_extras_add_search (ETableExtras *extras,
384 const gchar *id,
385 ETableSearchFunc search)
387 g_return_if_fail (E_IS_TABLE_EXTRAS (extras));
388 g_return_if_fail (id != NULL);
390 g_hash_table_insert (
391 extras->priv->searches,
392 g_strdup (id), (gpointer) search);
395 ETableSearchFunc
396 e_table_extras_get_search (ETableExtras *extras,
397 const gchar *id)
399 g_return_val_if_fail (E_IS_TABLE_EXTRAS (extras), NULL);
400 g_return_val_if_fail (id != NULL, NULL);
402 return g_hash_table_lookup (extras->priv->searches, id);
405 void
406 e_table_extras_add_icon_name (ETableExtras *extras,
407 const gchar *id,
408 const gchar *icon_name)
410 g_return_if_fail (E_IS_TABLE_EXTRAS (extras));
411 g_return_if_fail (id != NULL);
413 g_hash_table_insert (
414 extras->priv->icon_names,
415 g_strdup (id), g_strdup (icon_name));
418 const gchar *
419 e_table_extras_get_icon_name (ETableExtras *extras,
420 const gchar *id)
422 g_return_val_if_fail (E_IS_TABLE_EXTRAS (extras), NULL);
423 g_return_val_if_fail (id != NULL, NULL);
425 return g_hash_table_lookup (extras->priv->icon_names, id);