resetting manifest requested domain to floor
[platform/upstream/sysprof.git] / footreedatalist.c
1 /* gtktreedatalist.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  * 
19  * This file contains code shared between GtkTreeStore and GtkListStore.  Please
20  * do not use it.
21  */
22
23 #include "footreedatalist.h"
24 #include <string.h>
25
26 static FooTreeDataList *cache;
27
28 /* node allocation
29  */
30 #define N_DATA_LISTS (64)
31
32 FooTreeDataList *
33 _foo_tree_data_list_alloc (void)
34 {
35   FooTreeDataList *list;
36
37   if (!cache)
38   {
39       int i;
40
41       list = g_malloc (N_DATA_LISTS * sizeof (FooTreeDataList));
42
43       for (i = 0; i < N_DATA_LISTS; ++i)
44       {
45           list[i].next = cache;
46           cache = &(list[i]);
47       }
48   }
49
50   list = cache;
51   cache = cache->next;
52
53   memset (list, 0, sizeof (FooTreeDataList));
54   
55   return list;
56 }
57
58 void
59 _foo_tree_data_list_free (FooTreeDataList *list,
60                           GType           *column_headers)
61 {
62   FooTreeDataList *tmp, *next;
63   gint i = 0;
64
65   tmp = list;
66
67   while (tmp)
68     {
69       next = tmp->next;
70       if (g_type_is_a (column_headers [i], G_TYPE_STRING))
71         g_free ((gchar *) tmp->data.v_pointer);
72       else if (g_type_is_a (column_headers [i], G_TYPE_OBJECT) && tmp->data.v_pointer != NULL)
73         g_object_unref (tmp->data.v_pointer);
74       else if (g_type_is_a (column_headers [i], G_TYPE_BOXED) && tmp->data.v_pointer != NULL)
75         g_boxed_free (column_headers [i], (gpointer) tmp->data.v_pointer);
76
77       tmp->next = cache;
78       cache = tmp;
79       
80       i++;
81       tmp = next;
82     }
83 }
84
85 gboolean
86 _foo_tree_data_list_check_type (GType type)
87 {
88   gint i = 0;
89   static const GType type_list[] =
90   {
91     G_TYPE_BOOLEAN,
92     G_TYPE_CHAR,
93     G_TYPE_UCHAR,
94     G_TYPE_INT,
95     G_TYPE_UINT,
96     G_TYPE_LONG,
97     G_TYPE_ULONG,
98     G_TYPE_INT64,
99     G_TYPE_UINT64,
100     G_TYPE_ENUM,
101     G_TYPE_FLAGS,
102     G_TYPE_FLOAT,
103     G_TYPE_DOUBLE,
104     G_TYPE_STRING,
105     G_TYPE_POINTER,
106     G_TYPE_BOXED,
107     G_TYPE_OBJECT,
108     G_TYPE_INVALID
109   };
110
111   if (! G_TYPE_IS_VALUE_TYPE (type))
112     return FALSE;
113
114
115   while (type_list[i] != G_TYPE_INVALID)
116     {
117       if (g_type_is_a (type, type_list[i]))
118         return TRUE;
119       i++;
120     }
121   return FALSE;
122 }
123
124 static inline GType
125 get_fundamental_type (GType type)
126 {
127   GType result;
128
129   result = G_TYPE_FUNDAMENTAL (type);
130
131   if (result == G_TYPE_INTERFACE)
132     {
133       if (g_type_is_a (type, G_TYPE_OBJECT))
134         result = G_TYPE_OBJECT;
135     }
136
137   return result;
138 }
139 void
140 _foo_tree_data_list_node_to_value (FooTreeDataList *list,
141                                    GType            type,
142                                    GValue          *value)
143 {
144   g_value_init (value, type);
145
146   switch (get_fundamental_type (type))
147     {
148     case G_TYPE_BOOLEAN:
149       g_value_set_boolean (value, (gboolean) list->data.v_int);
150       break;
151     case G_TYPE_CHAR:
152       g_value_set_char (value, (gchar) list->data.v_char);
153       break;
154     case G_TYPE_UCHAR:
155       g_value_set_uchar (value, (guchar) list->data.v_uchar);
156       break;
157     case G_TYPE_INT:
158       g_value_set_int (value, (gint) list->data.v_int);
159       break;
160     case G_TYPE_UINT:
161       g_value_set_uint (value, (guint) list->data.v_uint);
162       break;
163     case G_TYPE_LONG:
164       g_value_set_long (value, list->data.v_long);
165       break;
166     case G_TYPE_ULONG:
167       g_value_set_ulong (value, list->data.v_ulong);
168       break;
169     case G_TYPE_INT64:
170       g_value_set_int64 (value, list->data.v_int64);
171       break;
172     case G_TYPE_UINT64:
173       g_value_set_uint64 (value, list->data.v_uint64);
174       break;
175     case G_TYPE_ENUM:
176       g_value_set_enum (value, list->data.v_int);
177       break;
178     case G_TYPE_FLAGS:
179       g_value_set_flags (value, list->data.v_uint);
180       break;
181     case G_TYPE_FLOAT:
182       g_value_set_float (value, (gfloat) list->data.v_float);
183       break;
184     case G_TYPE_DOUBLE:
185       g_value_set_double (value, (gdouble) list->data.v_double);
186       break;
187     case G_TYPE_STRING:
188       g_value_set_string (value, (gchar *) list->data.v_pointer);
189       break;
190     case G_TYPE_POINTER:
191       g_value_set_pointer (value, (gpointer) list->data.v_pointer);
192       break;
193     case G_TYPE_BOXED:
194       g_value_set_boxed (value, (gpointer) list->data.v_pointer);
195       break;
196     case G_TYPE_OBJECT:
197       g_value_set_object (value, (GObject *) list->data.v_pointer);
198       break;
199     default:
200       g_warning ("%s: Unsupported type (%s) retrieved.", G_STRLOC, g_type_name (value->g_type));
201       break;
202     }
203 }
204
205 void
206 _foo_tree_data_list_value_to_node (FooTreeDataList *list,
207                                    GValue          *value)
208 {
209   switch (get_fundamental_type (G_VALUE_TYPE (value)))
210     {
211     case G_TYPE_BOOLEAN:
212       list->data.v_int = g_value_get_boolean (value);
213       break;
214     case G_TYPE_CHAR:
215       list->data.v_char = g_value_get_char (value);
216       break;
217     case G_TYPE_UCHAR:
218       list->data.v_uchar = g_value_get_uchar (value);
219       break;
220     case G_TYPE_INT:
221       list->data.v_int = g_value_get_int (value);
222       break;
223     case G_TYPE_UINT:
224       list->data.v_uint = g_value_get_uint (value);
225       break;
226     case G_TYPE_LONG:
227       list->data.v_long = g_value_get_long (value);
228       break;
229     case G_TYPE_ULONG:
230       list->data.v_ulong = g_value_get_ulong (value);
231       break;
232     case G_TYPE_INT64:
233       list->data.v_int64 = g_value_get_int64 (value);
234       break;
235     case G_TYPE_UINT64:
236       list->data.v_uint64 = g_value_get_uint64 (value);
237       break;
238     case G_TYPE_ENUM:
239       list->data.v_int = g_value_get_enum (value);
240       break;
241     case G_TYPE_FLAGS:
242       list->data.v_uint = g_value_get_flags (value);
243       break;
244     case G_TYPE_POINTER:
245       list->data.v_pointer = g_value_get_pointer (value);
246       break;
247     case G_TYPE_FLOAT:
248       list->data.v_float = g_value_get_float (value);
249       break;
250     case G_TYPE_DOUBLE:
251       list->data.v_double = g_value_get_double (value);
252       break;
253     case G_TYPE_STRING:
254       g_free (list->data.v_pointer);
255       list->data.v_pointer = g_value_dup_string (value);
256       break;
257     case G_TYPE_OBJECT:
258       if (list->data.v_pointer)
259         g_object_unref (list->data.v_pointer);
260       list->data.v_pointer = g_value_dup_object (value);
261       break;
262     case G_TYPE_BOXED:
263       if (list->data.v_pointer)
264         g_boxed_free (G_VALUE_TYPE (value), list->data.v_pointer);
265       list->data.v_pointer = g_value_dup_boxed (value);
266       break;
267     default:
268       g_warning ("%s: Unsupported type (%s) stored.", G_STRLOC, g_type_name (G_VALUE_TYPE (value)));
269       break;
270     }
271 }
272
273 FooTreeDataList *
274 _foo_tree_data_list_node_copy (FooTreeDataList *list,
275                                GType            type)
276 {
277   FooTreeDataList *new_list;
278
279   g_return_val_if_fail (list != NULL, NULL);
280   
281   new_list = _foo_tree_data_list_alloc ();
282   new_list->next = NULL;
283
284   switch (get_fundamental_type (type))
285     {
286     case G_TYPE_BOOLEAN:
287     case G_TYPE_CHAR:
288     case G_TYPE_UCHAR:
289     case G_TYPE_INT:
290     case G_TYPE_UINT:
291     case G_TYPE_LONG:
292     case G_TYPE_ULONG:
293     case G_TYPE_INT64:
294     case G_TYPE_UINT64:
295     case G_TYPE_ENUM:
296     case G_TYPE_FLAGS:
297     case G_TYPE_POINTER:
298     case G_TYPE_FLOAT:
299     case G_TYPE_DOUBLE:
300       new_list->data = list->data;
301       break;
302     case G_TYPE_STRING:
303       new_list->data.v_pointer = g_strdup (list->data.v_pointer);
304       break;
305     case G_TYPE_OBJECT:
306     case G_TYPE_INTERFACE:
307       new_list->data.v_pointer = list->data.v_pointer;
308       if (new_list->data.v_pointer)
309         g_object_ref (new_list->data.v_pointer);
310       break;
311     case G_TYPE_BOXED:
312       if (list->data.v_pointer)
313         new_list->data.v_pointer = g_boxed_copy (type, list->data.v_pointer);
314       else
315         new_list->data.v_pointer = NULL;
316       break;
317     default:
318       g_warning ("Unsupported node type (%s) copied.", g_type_name (type));
319       break;
320     }
321
322   return new_list;
323 }
324
325 gint
326 _foo_tree_data_list_compare_func (GtkTreeModel *model,
327                                   GtkTreeIter  *a,
328                                   GtkTreeIter  *b,
329                                   gpointer      user_data)
330 {
331   gint column = GPOINTER_TO_INT (user_data);
332   GType type = gtk_tree_model_get_column_type (model, column);
333   GValue a_value = {0, };
334   GValue b_value = {0, };
335   gint retval;
336   const gchar *stra, *strb;
337
338   gtk_tree_model_get_value (model, a, column, &a_value);
339   gtk_tree_model_get_value (model, b, column, &b_value);
340
341   switch (get_fundamental_type (type))
342     {
343     case G_TYPE_BOOLEAN:
344       if (g_value_get_boolean (&a_value) < g_value_get_boolean (&b_value))
345         retval = -1;
346       else if (g_value_get_boolean (&a_value) == g_value_get_boolean (&b_value))
347         retval = 0;
348       else
349         retval = 1;
350       break;
351     case G_TYPE_CHAR:
352       if (g_value_get_char (&a_value) < g_value_get_char (&b_value))
353         retval = -1;
354       else if (g_value_get_char (&a_value) == g_value_get_char (&b_value))
355         retval = 0;
356       else
357         retval = 1;
358       break;
359     case G_TYPE_UCHAR:
360       if (g_value_get_uchar (&a_value) < g_value_get_uchar (&b_value))
361         retval = -1;
362       else if (g_value_get_uchar (&a_value) == g_value_get_uchar (&b_value))
363         retval = 0;
364       else
365         retval = 1;
366       break;
367     case G_TYPE_INT:
368       if (g_value_get_int (&a_value) < g_value_get_int (&b_value))
369         retval = -1;
370       else if (g_value_get_int (&a_value) == g_value_get_int (&b_value))
371         retval = 0;
372       else
373         retval = 1;
374       break;
375     case G_TYPE_UINT:
376       if (g_value_get_uint (&a_value) < g_value_get_uint (&b_value))
377         retval = -1;
378       else if (g_value_get_uint (&a_value) == g_value_get_uint (&b_value))
379         retval = 0;
380       else
381         retval = 1;
382       break;
383     case G_TYPE_LONG:
384       if (g_value_get_long (&a_value) < g_value_get_long (&b_value))
385         retval = -1;
386       else if (g_value_get_long (&a_value) == g_value_get_long (&b_value))
387         retval = 0;
388       else
389         retval = 1;
390       break;
391     case G_TYPE_ULONG:
392       if (g_value_get_ulong (&a_value) < g_value_get_ulong (&b_value))
393         retval = -1;
394       else if (g_value_get_ulong (&a_value) == g_value_get_ulong (&b_value))
395         retval = 0;
396       else
397         retval = 1;
398       break;
399     case G_TYPE_INT64:
400       if (g_value_get_int64 (&a_value) < g_value_get_int64 (&b_value))
401         retval = -1;
402       else if (g_value_get_int64 (&a_value) == g_value_get_int64 (&b_value))
403         retval = 0;
404       else
405         retval = 1;
406       break;
407     case G_TYPE_UINT64:
408       if (g_value_get_uint64 (&a_value) < g_value_get_uint64 (&b_value))
409         retval = -1;
410       else if (g_value_get_uint64 (&a_value) == g_value_get_uint64 (&b_value))
411         retval = 0;
412       else
413         retval = 1;
414       break;
415     case G_TYPE_ENUM:
416       /* this is somewhat bogus. */
417       if (g_value_get_enum (&a_value) < g_value_get_enum (&b_value))
418         retval = -1;
419       else if (g_value_get_enum (&a_value) == g_value_get_enum (&b_value))
420         retval = 0;
421       else
422         retval = 1;
423       break;
424     case G_TYPE_FLAGS:
425       /* this is even more bogus. */
426       if (g_value_get_flags (&a_value) < g_value_get_flags (&b_value))
427         retval = -1;
428       else if (g_value_get_flags (&a_value) == g_value_get_flags (&b_value))
429         retval = 0;
430       else
431         retval = 1;
432       break;
433     case G_TYPE_FLOAT:
434       if (g_value_get_float (&a_value) < g_value_get_float (&b_value))
435         retval = -1;
436       else if (g_value_get_float (&a_value) == g_value_get_float (&b_value))
437         retval = 0;
438       else
439         retval = 1;
440       break;
441     case G_TYPE_DOUBLE:
442       if (g_value_get_double (&a_value) < g_value_get_double (&b_value))
443         retval = -1;
444       else if (g_value_get_double (&a_value) == g_value_get_double (&b_value))
445         retval = 0;
446       else
447         retval = 1;
448       break;
449     case G_TYPE_STRING:
450       stra = g_value_get_string (&a_value);
451       strb = g_value_get_string (&b_value);
452       if (stra == NULL) stra = "";
453       if (strb == NULL) strb = "";
454       retval = g_utf8_collate (stra, strb);
455       break;
456     case G_TYPE_POINTER:
457     case G_TYPE_BOXED:
458     case G_TYPE_OBJECT:
459     default:
460       g_warning ("Attempting to sort on invalid type %s\n", g_type_name (type));
461       retval = FALSE;
462       break;
463     }
464
465   g_value_unset (&a_value);
466   g_value_unset (&b_value);
467
468   return retval;
469 }
470
471
472 GList *
473 _foo_tree_data_list_header_new (gint   n_columns,
474                                 GType *types)
475 {
476   GList *retval = NULL;
477
478   gint i;
479
480   for (i = 0; i < n_columns; i ++)
481     {
482       GtkTreeDataSortHeader *header;
483
484       header = g_slice_new (GtkTreeDataSortHeader);
485
486       retval = g_list_prepend (retval, header);
487       header->sort_column_id = i;
488       header->func = _foo_tree_data_list_compare_func;
489       header->destroy = NULL;
490       header->data = GINT_TO_POINTER (i);
491     }
492   return g_list_reverse (retval);
493 }
494
495 void
496 _foo_tree_data_list_header_free (GList *list)
497 {
498   GList *tmp;
499
500   for (tmp = list; tmp; tmp = tmp->next)
501     {
502       GtkTreeDataSortHeader *header = (GtkTreeDataSortHeader *) tmp->data;
503
504       if (header->destroy)
505         {
506           GDestroyNotify d = header->destroy;
507
508           header->destroy = NULL;
509           d (header->data);
510         }
511
512       g_slice_free (GtkTreeDataSortHeader, header);
513     }
514   g_list_free (list);
515 }
516
517 GtkTreeDataSortHeader *
518 _foo_tree_data_list_get_header (GList   *header_list,
519                                 gint     sort_column_id)
520 {
521   GtkTreeDataSortHeader *header = NULL;
522
523   for (; header_list; header_list = header_list->next)
524     {
525       header = (GtkTreeDataSortHeader*) header_list->data;
526       if (header->sort_column_id == sort_column_id)
527         return header;
528     }
529   return NULL;
530 }
531
532
533 GList *
534 _foo_tree_data_list_set_header (GList                  *header_list,
535                                 gint                    sort_column_id,
536                                 GtkTreeIterCompareFunc  func,
537                                 gpointer                data,
538                                 GDestroyNotify          destroy)
539 {
540   GList *list = header_list;
541   GtkTreeDataSortHeader *header = NULL;
542
543   for (; list; list = list->next)
544     {
545       header = (GtkTreeDataSortHeader*) list->data;
546       if (header->sort_column_id == sort_column_id)
547         break;
548       header = NULL;
549
550       if (list->next == NULL)
551         break;
552     }
553   
554   if (header == NULL)
555     {
556       header = g_slice_new0 (GtkTreeDataSortHeader);
557       header->sort_column_id = sort_column_id;
558       if (list)
559         list = g_list_append (list, header);
560       else
561         header_list = g_list_append (header_list, header);
562     }
563
564   if (header->destroy)
565     {
566       GDestroyNotify d = header->destroy;
567       
568       header->destroy = NULL;
569       d (header->data);
570     }
571   
572   header->func = func;
573   header->data = data;
574   header->destroy = destroy;
575
576   return header_list;
577 }