]> Pileus Git - ~andy/gtk/blob - gtk/gtktreedatalist.c
Deprecation cleanup
[~andy/gtk] / gtk / gtktreedatalist.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 "gtktreedatalist.h"
24 #include <string.h>
25 static GMemChunk *tree_chunk = NULL;
26 #define TREE_CHUNK_PREALLOCS 64
27
28 /* node allocation
29  */
30 GtkTreeDataList *
31 _gtk_tree_data_list_alloc (void)
32 {
33   GtkTreeDataList *list;
34
35   if (tree_chunk == NULL)
36     tree_chunk = g_mem_chunk_new ("treedatalist mem chunk",
37                                   sizeof (GtkTreeDataList),
38                                   sizeof (GtkTreeDataList) * TREE_CHUNK_PREALLOCS,
39                                   G_ALLOC_AND_FREE);
40
41   list = g_chunk_new (GtkTreeDataList, tree_chunk);
42   memset (list, 0, sizeof (GtkTreeDataList));
43
44   return list;
45 }
46
47 void
48 _gtk_tree_data_list_free (GtkTreeDataList *list,
49                           GType           *column_headers)
50 {
51   GtkTreeDataList *tmp, *next;
52   gint i = 0;
53
54   tmp = list;
55
56   while (tmp)
57     {
58       next = tmp->next;
59       if (g_type_is_a (column_headers [i], G_TYPE_STRING))
60         g_free ((gchar *) tmp->data.v_pointer);
61       else if (g_type_is_a (column_headers [i], G_TYPE_OBJECT) && tmp->data.v_pointer != NULL)
62         g_object_unref (tmp->data.v_pointer);
63       else if (g_type_is_a (column_headers [i], G_TYPE_BOXED) && tmp->data.v_pointer != NULL)
64         g_boxed_free (column_headers [i], (gpointer) tmp->data.v_pointer);
65
66       g_mem_chunk_free (tree_chunk, tmp);
67       i++;
68       tmp = next;
69     }
70 }
71
72 gboolean
73 _gtk_tree_data_list_check_type (GType type)
74 {
75   gint i = 0;
76   static GType type_list[] =
77   {
78     G_TYPE_BOOLEAN,
79     G_TYPE_CHAR,
80     G_TYPE_UCHAR,
81     G_TYPE_INT,
82     G_TYPE_UINT,
83     G_TYPE_LONG,
84     G_TYPE_ULONG,
85     G_TYPE_INT64,
86     G_TYPE_UINT64,
87     G_TYPE_ENUM,
88     G_TYPE_FLAGS,
89     G_TYPE_FLOAT,
90     G_TYPE_DOUBLE,
91     G_TYPE_STRING,
92     G_TYPE_POINTER,
93     G_TYPE_BOXED,
94     G_TYPE_OBJECT,
95     G_TYPE_INVALID
96   };
97
98   if (! G_TYPE_IS_VALUE_TYPE (type))
99     return FALSE;
100
101
102   while (type_list[i] != G_TYPE_INVALID)
103     {
104       if (g_type_is_a (type, type_list[i]))
105         return TRUE;
106       i++;
107     }
108   return FALSE;
109 }
110
111
112 void
113 _gtk_tree_data_list_node_to_value (GtkTreeDataList *list,
114                                    GType            type,
115                                    GValue          *value)
116 {
117   g_value_init (value, type);
118
119   switch (G_TYPE_FUNDAMENTAL (type))
120     {
121     case G_TYPE_BOOLEAN:
122       g_value_set_boolean (value, (gboolean) list->data.v_int);
123       break;
124     case G_TYPE_CHAR:
125       g_value_set_char (value, (gchar) list->data.v_char);
126       break;
127     case G_TYPE_UCHAR:
128       g_value_set_uchar (value, (guchar) list->data.v_uchar);
129       break;
130     case G_TYPE_INT:
131       g_value_set_int (value, (gint) list->data.v_int);
132       break;
133     case G_TYPE_UINT:
134       g_value_set_uint (value, (guint) list->data.v_uint);
135       break;
136     case G_TYPE_LONG:
137       g_value_set_long (value, list->data.v_long);
138       break;
139     case G_TYPE_ULONG:
140       g_value_set_ulong (value, list->data.v_ulong);
141       break;
142     case G_TYPE_INT64:
143       g_value_set_int64 (value, list->data.v_int64);
144       break;
145     case G_TYPE_UINT64:
146       g_value_set_uint64 (value, list->data.v_uint64);
147       break;
148     case G_TYPE_ENUM:
149       g_value_set_enum (value, list->data.v_int);
150       break;
151     case G_TYPE_FLAGS:
152       g_value_set_flags (value, list->data.v_uint);
153       break;
154     case G_TYPE_FLOAT:
155       g_value_set_float (value, (gfloat) list->data.v_float);
156       break;
157     case G_TYPE_DOUBLE:
158       g_value_set_double (value, (gdouble) list->data.v_double);
159       break;
160     case G_TYPE_STRING:
161       g_value_set_string (value, (gchar *) list->data.v_pointer);
162       break;
163     case G_TYPE_POINTER:
164       g_value_set_pointer (value, (gpointer) list->data.v_pointer);
165       break;
166     case G_TYPE_BOXED:
167       g_value_set_boxed (value, (gpointer) list->data.v_pointer);
168       break;
169     case G_TYPE_OBJECT:
170       g_value_set_object (value, (GObject *) list->data.v_pointer);
171       break;
172     default:
173       g_warning ("%s: Unsupported type (%s) retrieved.", G_STRLOC, g_type_name (value->g_type));
174       break;
175     }
176 }
177
178 void
179 _gtk_tree_data_list_value_to_node (GtkTreeDataList *list,
180                                    GValue          *value)
181 {
182   switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)))
183     {
184     case G_TYPE_BOOLEAN:
185       list->data.v_int = g_value_get_boolean (value);
186       break;
187     case G_TYPE_CHAR:
188       list->data.v_char = g_value_get_char (value);
189       break;
190     case G_TYPE_UCHAR:
191       list->data.v_uchar = g_value_get_uchar (value);
192       break;
193     case G_TYPE_INT:
194       list->data.v_int = g_value_get_int (value);
195       break;
196     case G_TYPE_UINT:
197       list->data.v_uint = g_value_get_uint (value);
198       break;
199     case G_TYPE_LONG:
200       list->data.v_long = g_value_get_long (value);
201       break;
202     case G_TYPE_ULONG:
203       list->data.v_ulong = g_value_get_ulong (value);
204       break;
205     case G_TYPE_INT64:
206       list->data.v_int64 = g_value_get_int64 (value);
207       break;
208     case G_TYPE_UINT64:
209       list->data.v_uint64 = g_value_get_uint64 (value);
210       break;
211     case G_TYPE_ENUM:
212       list->data.v_int = g_value_get_enum (value);
213       break;
214     case G_TYPE_FLAGS:
215       list->data.v_uint = g_value_get_flags (value);
216       break;
217     case G_TYPE_POINTER:
218       list->data.v_pointer = g_value_get_pointer (value);
219       break;
220     case G_TYPE_FLOAT:
221       list->data.v_float = g_value_get_float (value);
222       break;
223     case G_TYPE_DOUBLE:
224       list->data.v_double = g_value_get_double (value);
225       break;
226     case G_TYPE_STRING:
227       if (list->data.v_pointer)
228         g_free (list->data.v_pointer);
229       list->data.v_pointer = g_value_dup_string (value);
230       break;
231     case G_TYPE_OBJECT:
232       if (list->data.v_pointer)
233         g_object_unref (list->data.v_pointer);
234       list->data.v_pointer = g_value_dup_object (value);
235       break;
236     case G_TYPE_BOXED:
237       if (list->data.v_pointer)
238         g_boxed_free (G_VALUE_TYPE (value), list->data.v_pointer);
239       list->data.v_pointer = g_value_dup_boxed (value);
240       break;
241     default:
242       g_warning ("%s: Unsupported type (%s) stored.", G_STRLOC, g_type_name (G_VALUE_TYPE (value)));
243       break;
244     }
245 }
246
247 GtkTreeDataList *
248 _gtk_tree_data_list_node_copy (GtkTreeDataList *list,
249                                GType            type)
250 {
251   GtkTreeDataList *new_list;
252
253   g_return_val_if_fail (list != NULL, NULL);
254   
255   new_list = _gtk_tree_data_list_alloc ();
256   new_list->next = NULL;
257
258   switch (G_TYPE_FUNDAMENTAL (type))
259     {
260     case G_TYPE_BOOLEAN:
261     case G_TYPE_CHAR:
262     case G_TYPE_UCHAR:
263     case G_TYPE_INT:
264     case G_TYPE_UINT:
265     case G_TYPE_LONG:
266     case G_TYPE_ULONG:
267     case G_TYPE_INT64:
268     case G_TYPE_UINT64:
269     case G_TYPE_ENUM:
270     case G_TYPE_FLAGS:
271     case G_TYPE_POINTER:
272     case G_TYPE_FLOAT:
273     case G_TYPE_DOUBLE:
274       new_list->data = list->data;
275       break;
276     case G_TYPE_STRING:
277       new_list->data.v_pointer = g_strdup (list->data.v_pointer);
278       break;
279     case G_TYPE_OBJECT:
280       new_list->data.v_pointer = list->data.v_pointer;
281       if (new_list->data.v_pointer)
282         g_object_ref (new_list->data.v_pointer);
283       break;
284     case G_TYPE_BOXED:
285       if (list->data.v_pointer)
286         new_list->data.v_pointer = g_boxed_copy (type, list->data.v_pointer);
287       else
288         new_list->data.v_pointer = NULL;
289       break;
290     default:
291       g_warning ("Unsupported node type (%s) copied.", g_type_name (type));
292       break;
293     }
294
295   return new_list;
296 }
297
298 gint
299 gtk_tree_data_list_compare_func (GtkTreeModel *model,
300                                  GtkTreeIter  *a,
301                                  GtkTreeIter  *b,
302                                  gpointer      user_data)
303 {
304   gint column = GPOINTER_TO_INT (user_data);
305   GType type = gtk_tree_model_get_column_type (model, column);
306   GValue a_value = {0, };
307   GValue b_value = {0, };
308   gint retval;
309   const gchar *stra, *strb;
310
311   gtk_tree_model_get_value (model, a, column, &a_value);
312   gtk_tree_model_get_value (model, b, column, &b_value);
313
314   switch (G_TYPE_FUNDAMENTAL (type))
315     {
316     case G_TYPE_BOOLEAN:
317       if (g_value_get_int (&a_value) < g_value_get_int (&b_value))
318         retval = -1;
319       else if (g_value_get_int (&a_value) == g_value_get_int (&b_value))
320         retval = 0;
321       else
322         retval = 1;
323       break;
324     case G_TYPE_CHAR:
325       if (g_value_get_char (&a_value) < g_value_get_char (&b_value))
326         retval = -1;
327       else if (g_value_get_char (&a_value) == g_value_get_char (&b_value))
328         retval = 0;
329       else
330         retval = 1;
331       break;
332     case G_TYPE_UCHAR:
333       if (g_value_get_uchar (&a_value) < g_value_get_uchar (&b_value))
334         retval = -1;
335       else if (g_value_get_uchar (&a_value) == g_value_get_uchar (&b_value))
336         retval = 0;
337       else
338         retval = 1;
339       break;
340     case G_TYPE_INT:
341       if (g_value_get_int (&a_value) < g_value_get_int (&b_value))
342         retval = -1;
343       else if (g_value_get_int (&a_value) == g_value_get_int (&b_value))
344         retval = 0;
345       else
346         retval = 1;
347       break;
348     case G_TYPE_UINT:
349       if (g_value_get_uint (&a_value) < g_value_get_uint (&b_value))
350         retval = -1;
351       else if (g_value_get_uint (&a_value) == g_value_get_uint (&b_value))
352         retval = 0;
353       else
354         retval = 1;
355       break;
356     case G_TYPE_LONG:
357       if (g_value_get_long (&a_value) < g_value_get_long (&b_value))
358         retval = -1;
359       else if (g_value_get_long (&a_value) == g_value_get_long (&b_value))
360         retval = 0;
361       else
362         retval = 1;
363       break;
364     case G_TYPE_ULONG:
365       if (g_value_get_ulong (&a_value) < g_value_get_ulong (&b_value))
366         retval = -1;
367       else if (g_value_get_ulong (&a_value) == g_value_get_ulong (&b_value))
368         retval = 0;
369       else
370         retval = 1;
371       break;
372     case G_TYPE_INT64:
373       if (g_value_get_int64 (&a_value) < g_value_get_int64 (&b_value))
374         retval = -1;
375       else if (g_value_get_int64 (&a_value) == g_value_get_int64 (&b_value))
376         retval = 0;
377       else
378         retval = 1;
379       break;
380     case G_TYPE_UINT64:
381       if (g_value_get_uint64 (&a_value) < g_value_get_uint64 (&b_value))
382         retval = -1;
383       else if (g_value_get_uint64 (&a_value) == g_value_get_uint64 (&b_value))
384         retval = 0;
385       else
386         retval = 1;
387       break;
388     case G_TYPE_ENUM:
389       /* this is somewhat bogus. */
390       if (g_value_get_enum (&a_value) < g_value_get_enum (&b_value))
391         retval = -1;
392       else if (g_value_get_enum (&a_value) == g_value_get_enum (&b_value))
393         retval = 0;
394       else
395         retval = 1;
396       break;
397     case G_TYPE_FLAGS:
398       /* this is even more bogus. */
399       if (g_value_get_flags (&a_value) < g_value_get_flags (&b_value))
400         retval = -1;
401       else if (g_value_get_flags (&a_value) == g_value_get_flags (&b_value))
402         retval = 0;
403       else
404         retval = 1;
405       break;
406     case G_TYPE_FLOAT:
407       if (g_value_get_float (&a_value) < g_value_get_float (&b_value))
408         retval = -1;
409       else if (g_value_get_float (&a_value) == g_value_get_float (&b_value))
410         retval = 0;
411       else
412         retval = 1;
413       break;
414     case G_TYPE_DOUBLE:
415       if (g_value_get_double (&a_value) < g_value_get_double (&b_value))
416         retval = -1;
417       else if (g_value_get_double (&a_value) == g_value_get_double (&b_value))
418         retval = 0;
419       else
420         retval = 1;
421       break;
422     case G_TYPE_STRING:
423       stra = g_value_get_string (&a_value);
424       strb = g_value_get_string (&b_value);
425       if (stra == NULL) stra = "";
426       if (strb == NULL) strb = "";
427       retval = g_utf8_collate (stra, strb);
428       break;
429     case G_TYPE_POINTER:
430     case G_TYPE_BOXED:
431     case G_TYPE_OBJECT:
432     default:
433       g_warning ("Attempting to sort on invalid type %s\n", g_type_name (type));
434       retval = FALSE;
435       break;
436     }
437
438   g_value_unset (&a_value);
439   g_value_unset (&b_value);
440
441   return retval;
442 }
443
444
445 GList *
446 _gtk_tree_data_list_header_new (gint   n_columns,
447                                 GType *types)
448 {
449   GList *retval = NULL;
450
451   gint i;
452
453   for (i = 0; i < n_columns; i ++)
454     {
455       GtkTreeDataSortHeader *header;
456
457       header = g_new (GtkTreeDataSortHeader, 1);
458
459       retval = g_list_prepend (retval, header);
460       header->sort_column_id = i;
461       header->func = gtk_tree_data_list_compare_func;
462       header->destroy = NULL;
463       header->data = GINT_TO_POINTER (i);
464     }
465   return g_list_reverse (retval);
466 }
467
468 void
469 _gtk_tree_data_list_header_free (GList *list)
470 {
471   GList *tmp;
472
473   for (tmp = list; tmp; tmp = tmp->next)
474     {
475       GtkTreeDataSortHeader *header = (GtkTreeDataSortHeader *) tmp->data;
476
477       if (header->destroy)
478         {
479           GtkDestroyNotify d = header->destroy;
480
481           header->destroy = NULL;
482           d (header->data);
483         }
484
485       g_free (header);
486     }
487   g_list_free (list);
488 }
489
490 GtkTreeDataSortHeader *
491 _gtk_tree_data_list_get_header (GList *header_list,
492                                 gint   sort_column_id)
493 {
494   GtkTreeDataSortHeader *header = NULL;
495
496   for (; header_list; header_list = header_list->next)
497     {
498       header = (GtkTreeDataSortHeader*) header_list->data;
499       if (header->sort_column_id == sort_column_id)
500         return header;
501     }
502   return NULL;
503 }