]> git.sur5r.net Git - glabels/blob - glabels2/libglabels/category.c
2007-10-01 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / libglabels / category.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  *  (LIBGLABELS) Template library for GLABELS
5  *
6  *  category.c:  template category module
7  *
8  *  Copyright (C) 2001-2006  Jim Evins <evins@snaught.com>.
9  *
10  *  This file is part of the LIBGLABELS library.
11  *
12  *  This library is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Library General Public
14  *  License as published by the Free Software Foundation; either
15  *  version 2 of the License, or (at your option) any later version.
16  *
17  *  This library is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  *  Library General Public License for more details.
21  *
22  *  You should have received a copy of the GNU Library General Public
23  *  License along with this library; if not, write to the Free
24  *  Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  *  MA 02111-1307, USA
26  */
27 #include <config.h>
28
29 #include "category.h"
30
31 #include <glib/gi18n.h>
32 #include <glib/gmem.h>
33 #include <glib/gstrfuncs.h>
34 #include <glib/gmessages.h>
35 #include <glib/gdir.h>
36 #include <string.h>
37
38 #include "libglabels-private.h"
39
40 #include "xml-category.h"
41
42 /*===========================================*/
43 /* Private types                             */
44 /*===========================================*/
45
46
47 /*===========================================*/
48 /* Private globals                           */
49 /*===========================================*/
50
51 static GList *categories = NULL;
52
53
54 /*===========================================*/
55 /* Local function prototypes                 */
56 /*===========================================*/
57
58 static GList *read_categories (void);
59
60 static GList *read_category_files_from_dir (GList       *categories,
61                                             const gchar *dirname);
62
63
64 /**
65  * lgl_category_init:
66  *
67  * Initialize libglabels category module by reading all category definition
68  * files located in system and user template directories.
69  *
70  * The end user would typically call lgl_init() instead.
71  */
72 void
73 lgl_category_init (void)
74 {
75         if (categories) {
76                 return; /* Already initialized. */
77         }
78
79         categories = read_categories ();
80 }
81
82
83 /**
84  * lgl_category_new:
85  * @id:     Id of category definition. (E.g. label, card, etc.)  Should be
86  *          unique.
87  * @name:   Localized name of category.
88  *
89  * Allocates and constructs a new #lglCategory structure.
90  *
91  * Returns: a pointer to a newly allocated #lglCategory structure.
92  *
93  */
94 lglCategory *
95 lgl_category_new (gchar             *id,
96                   gchar             *name)
97 {
98         lglCategory *category;
99
100         category         = g_new0 (lglCategory,1);
101         category->id     = g_strdup (id);
102         category->name   = g_strdup (name);
103
104         return category;
105 }
106
107
108 /**
109  * lgl_category_dup:
110  * @orig:  #lglCategory structure to be duplicated.
111  *
112  * Duplicates an existing #lglCategory structure.
113  *
114  * Returns: a pointer to a newly allocated #lglCategory structure.
115  *
116  */
117 lglCategory *lgl_category_dup (const lglCategory *orig)
118 {
119         lglCategory       *category;
120
121         g_return_val_if_fail (orig, NULL);
122
123         category = g_new0 (lglCategory,1);
124
125         category->id     = g_strdup (orig->id);
126         category->name   = g_strdup (orig->name);
127
128         return category;
129 }
130
131
132 /**
133  * lgl_category_free:
134  * @category:  pointer to #lglCategory structure to be freed.
135  *
136  * Free all memory associated with an existing #lglCategory structure.
137  *
138  */
139 void lgl_category_free (lglCategory *category)
140 {
141
142         if ( category != NULL ) {
143
144                 g_free (category->id);
145                 category->id = NULL;
146
147                 g_free (category->name);
148                 category->name = NULL;
149
150                 g_free (category);
151         }
152
153 }
154
155
156 /**
157  * lgl_category_get_name_list:
158  *
159  * Get a list of all localized category names known to liblglabels.
160  *
161  * Returns: a list of localized category names.
162  *
163  */
164 GList *
165 lgl_category_get_name_list (void)
166 {
167         GList           *names = NULL;
168         GList           *p;
169         lglCategory     *category;
170
171         if (!categories) {
172                 lgl_category_init ();
173         }
174
175         for ( p=categories; p != NULL; p=p->next ) {
176                 category = (lglCategory *)p->data;
177                 names = g_list_append (names, g_strdup (category->name));
178         }
179
180         return names;
181 }
182
183
184 /**
185  * lgl_category_free_name_list:
186  * @names: List of localized category name strings to be freed.
187  *
188  * Free up all storage associated with a name list obtained with
189  * lgl_category_get_name_list().
190  *
191  */
192 void
193 lgl_category_free_name_list (GList *names)
194 {
195         GList *p;
196
197         for (p = names; p != NULL; p = p->next) {
198                 g_free (p->data);
199                 p->data = NULL;
200         }
201
202         g_list_free (names);
203 }
204
205
206 /**
207  * lgl_category_from_id:
208  * @id: category id string
209  *
210  * Lookup category definition from id string.
211  *
212  * Returns: pointer to a newly allocated #lglCategory structure.
213  *
214  */
215 lglCategory *
216 lgl_category_from_id (const gchar *id)
217 {
218         GList        *p;
219         lglCategory  *category;
220
221         if (!categories) {
222                 lgl_category_init ();
223         }
224
225         if (id == NULL) {
226                 /* If no id, return first category as a default */
227                 return lgl_category_dup ((lglCategory *) categories->data);
228         }
229
230         for (p = categories; p != NULL; p = p->next) {
231                 category = (lglCategory *) p->data;
232                 if (g_strcasecmp (category->id, id) == 0) {
233                         return lgl_category_dup (category);
234                 }
235         }
236
237         return NULL;
238 }
239
240
241 /**
242  * lgl_category_from_name:
243  * @name: localized category name string
244  *
245  * Lookup category definition from localized category name string.
246  *
247  * Returns: pointer to a newly allocated #lglCategory structure.
248  *
249  */
250 lglCategory *
251 lgl_category_from_name (const gchar *name)
252 {
253         GList        *p;
254         lglCategory  *category;
255
256         if (!categories) {
257                 lgl_category_init ();
258         }
259
260         if (name == NULL) {
261                 /* If no name, return first category as a default */
262                 return lgl_category_dup ((lglCategory *) categories->data);
263         }
264
265         for (p = categories; p != NULL; p = p->next) {
266                 category = (lglCategory *) p->data;
267                 if (g_strcasecmp (category->name, name) == 0) {
268                         return lgl_category_dup (category);
269                 }
270         }
271
272         return NULL;
273 }
274
275
276 /**
277  * lgl_category_lookup_id_from_name:
278  * @name: localized category name stringp
279  *
280  * Lookup category name string from localized category name string.
281  *
282  * Returns: pointer to a newly allocated id string.
283  *
284  */
285 gchar *
286 lgl_category_lookup_id_from_name (const gchar       *name)
287 {
288         lglCategory *category = NULL;
289         gchar       *id = NULL;
290
291         if (name != NULL)
292         {
293                 category = lgl_category_from_name (name);
294                 if ( category != NULL )
295                 {
296                         id = g_strdup (category->id);
297                         lgl_category_free (category);
298                         category = NULL;
299                 }
300         }
301
302         return id;
303 }
304
305 /**
306  * lgl_category_lookup_name_from_id:
307  * @id: category id string
308  *
309  * Lookup localized category name string from category id string.
310  *
311  * Returns: pointer to a newly allocated localized category name string.
312  *
313  */
314 gchar *
315 lgl_category_lookup_name_from_id (const gchar       *id)
316 {
317         lglCategory *category = NULL;
318         gchar       *name = NULL;
319
320         if (id != NULL)
321         {
322                 category = lgl_category_from_id (id);
323                 if ( category != NULL )
324                 {
325                         name = g_strdup (category->name);
326                         lgl_category_free (category);
327                         category = NULL;
328                 }
329         }
330
331         return name;
332 }
333
334 /*--------------------------------------------------------------------------*/
335 /* PRIVATE.  Read categories from various files.                            */
336 /*--------------------------------------------------------------------------*/
337 static GList *
338 read_categories (void)
339 {
340         gchar *data_dir;
341         GList *categories = NULL;
342
343         data_dir = LGL_SYSTEM_DATA_DIR;
344         categories = read_category_files_from_dir (categories, data_dir);
345         g_free (data_dir);
346
347         data_dir = LGL_USER_DATA_DIR;
348         categories = read_category_files_from_dir (categories, data_dir);
349         g_free (data_dir);
350
351         if (categories == NULL) {
352                 g_critical (_("Unable to locate category definitions.  Libglabels may not be installed correctly!"));
353         }
354
355         return categories;
356 }
357
358 /*--------------------------------------------------------------------------*/
359 /* PRIVATE.  Read all category files from given directory.  Append to list.    */
360 /*--------------------------------------------------------------------------*/
361 static GList *
362 read_category_files_from_dir (GList       *categories,
363                               const gchar *dirname)
364 {
365         GDir        *dp;
366         const gchar *filename, *extension;
367         gchar       *full_filename = NULL;
368         GError      *gerror = NULL;
369         GList       *new_categories = NULL;
370
371         if (dirname == NULL) {
372                 return categories;
373         }
374
375         if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
376                 return categories;
377         }
378
379         dp = g_dir_open (dirname, 0, &gerror);
380         if (gerror != NULL) {
381                 g_message ("cannot open data directory: %s", gerror->message );
382                 return categories;
383         }
384
385         while ((filename = g_dir_read_name (dp)) != NULL) {
386
387                 extension = strrchr (filename, '.');
388
389                 if (extension != NULL) {
390
391                         if ( (g_strcasecmp (extension, ".categories") == 0)
392                              || (g_strcasecmp (filename, "categories.xml") == 0) ) {
393
394                                 full_filename =
395                                     g_build_filename (dirname, filename, NULL);
396                                 new_categories =
397                                     lgl_xml_category_read_categories_from_file (full_filename);
398                                 g_free (full_filename);
399
400                                 categories = g_list_concat (categories, new_categories);
401                                 new_categories = NULL;
402
403                         }
404
405                 }
406
407         }
408
409         g_dir_close (dp);
410
411         return categories;
412 }
413
414
415
416