]> git.sur5r.net Git - glabels/blob - glabels2/libglabels/db.c
2007-11-18 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / libglabels / db.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  *  db.c:  template db module
7  *
8  *  Copyright (C) 2003-2007  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 "db.h"
30
31 #include <glib/gi18n.h>
32 #include <glib/gmem.h>
33 #include <glib/gstrfuncs.h>
34 #include <glib/gdir.h>
35 #include <glib/gmessages.h>
36 #include <string.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39
40 #include "libglabels-private.h"
41
42 #include "xml-paper.h"
43 #include "xml-category.h"
44 #include "xml-template.h"
45
46
47 /*===========================================*/
48 /* Private types                             */
49 /*===========================================*/
50
51 /*===========================================*/
52 /* Private globals                           */
53 /*===========================================*/
54
55 static GList *papers     = NULL;
56 static GList *categories = NULL;
57 static GList *templates  = NULL;
58
59 /*===========================================*/
60 /* Local function prototypes                 */
61 /*===========================================*/
62
63 static GList *read_papers                  (void);
64 static GList *read_paper_files_from_dir    (GList       *papers,
65                                             const gchar *dirname);
66
67 static GList *read_categories              (void);
68 static GList *read_category_files_from_dir (GList       *categories,
69                                             const gchar *dirname);
70
71 static GList *read_templates               (void);
72 static GList *read_template_files_from_dir (GList       *templates,
73                                             const gchar *dirname);
74
75 static lglTemplate *template_full_page (const gchar *page_size);
76
77
78
79 /*===========================================*/
80 /* Module initialization                     */
81 /*===========================================*/
82
83 /**
84  * lgl_db_init:
85  *
86  * Initialize all libglabels subsystems.  It is not necessary for an application to call
87  * lgl_db_init(), because libglabels will initialize on demand.  An application programmer may
88  * choose to call lgl_db_init() at startup to minimize the impact of the first libglabels call
89  * on GUI response time.
90  *
91  * This function initializes its paper definitions, category definitions, and its template
92  * database.. It will search both system and user template directories to locate
93  * this data.
94  */
95 void
96 lgl_db_init (void)
97 {
98         lglPaper    *paper_other;
99         lglCategory *category_user_defined;
100         GList       *page_sizes;
101         GList       *p;
102
103         /*
104          * Paper definitions
105          */
106         if (!papers)
107         {
108
109                 papers = read_papers ();
110
111                 /* Create and append an "Other" entry. */
112                 paper_other = lgl_paper_new ("Other", _("Other"), 0.0, 0.0);
113                 papers = g_list_append (papers, paper_other);
114
115         }
116
117         /*
118          * Categories
119          */
120         if (!categories)
121         {
122                 categories = read_categories ();
123
124                 /* Create and append a "User defined" entry. */
125                 category_user_defined = lgl_category_new ("user-defined", _("User defined"));
126                 categories = g_list_append (categories, category_user_defined);
127         }
128
129         /*
130          * Templates
131          */
132         if (!templates)
133         {
134
135                 templates = read_templates ();
136
137                 /* Create and append generic full page templates. */
138                 page_sizes = lgl_db_get_paper_id_list ();
139                 for ( p=page_sizes; p != NULL; p=p->next )
140                 {
141                         if ( !lgl_db_is_paper_id_other (p->data) )
142                         {
143                                 templates = g_list_append (templates,
144                                                            template_full_page (p->data));
145                         }
146                 }
147                 lgl_db_free_paper_id_list (page_sizes);
148
149         }
150 }
151
152
153
154 /*===========================================*/
155 /* Paper db functions.                       */
156 /*===========================================*/
157
158 /**
159  * lgl_db_get_paper_id_list:
160  *
161  * Get a list of all paper ids known to libglabels.
162  *
163  * Returns: a list of paper ids.
164  *
165  */
166 GList *
167 lgl_db_get_paper_id_list (void)
168 {
169         GList           *ids = NULL;
170         GList           *p;
171         lglPaper        *paper;
172
173         if (!papers)
174         {
175                 lgl_db_init ();
176         }
177
178         for ( p=papers; p != NULL; p=p->next )
179         {
180                 paper = (lglPaper *)p->data;
181                 ids = g_list_append (ids, g_strdup (paper->id));
182         }
183
184         return ids;
185 }
186
187
188 /**
189  * lgl_db_free_paper_id_list:
190  * @ids: List of id strings to be freed.
191  *
192  * Free up all storage associated with an id list obtained with
193  * lgl_db_get_paper_id_list().
194  *
195  */
196 void
197 lgl_db_free_paper_id_list (GList *ids)
198 {
199         GList *p;
200
201         for (p = ids; p != NULL; p = p->next)
202         {
203                 g_free (p->data);
204                 p->data = NULL;
205         }
206
207         g_list_free (ids);
208 }
209
210
211 /**
212  * lgl_db_get_paper_name_list:
213  *
214  * Get a list of all localized paper names known to libglabels.
215  *
216  * Returns: a list of localized paper names.
217  *
218  */
219 GList *
220 lgl_db_get_paper_name_list (void)
221 {
222         GList           *names = NULL;
223         GList           *p;
224         lglPaper        *paper;
225
226         if (!papers)
227         {
228                 lgl_db_init ();
229         }
230
231         for ( p=papers; p != NULL; p=p->next )
232         {
233                 paper = (lglPaper *)p->data;
234                 names = g_list_append (names, g_strdup (paper->name));
235         }
236
237         return names;
238 }
239
240
241 /**
242  * lgl_db_free_paper_name_list:
243  * @names: List of localized paper name strings to be freed.
244  *
245  * Free up all storage associated with a name list obtained with
246  * lgl_db_get_paper_name_list().
247  *
248  */
249 void
250 lgl_db_free_paper_name_list (GList *names)
251 {
252         GList *p;
253
254         for (p = names; p != NULL; p = p->next)
255         {
256                 g_free (p->data);
257                 p->data = NULL;
258         }
259
260         g_list_free (names);
261 }
262
263
264 /**
265  * lgl_db_lookup_paper_from_name:
266  * @name: localized paper name string
267  *
268  * Lookup paper definition from localized paper name string.
269  *
270  * Returns: pointer to a newly allocated #lglPaper structure.
271  *
272  */
273 lglPaper *
274 lgl_db_lookup_paper_from_name (const gchar *name)
275 {
276         GList       *p;
277         lglPaper    *paper;
278
279         if (!papers)
280         {
281                 lgl_db_init ();
282         }
283
284         if (name == NULL)
285         {
286                 /* If no name, return first paper as a default */
287                 return lgl_paper_dup ((lglPaper *) papers->data);
288         }
289
290         for (p = papers; p != NULL; p = p->next)
291         {
292                 paper = (lglPaper *) p->data;
293                 if (UTF8_EQUAL (paper->name, name))
294                 {
295                         return lgl_paper_dup (paper);
296                 }
297         }
298
299         return NULL;
300 }
301
302
303 /**
304  * lgl_db_lookup_paper_from_id:
305  * @id: paper id string
306  *
307  * Lookup paper definition from id string.
308  *
309  * Returns: pointer to a newly allocated #lglPaper structure.
310  *
311  */
312 lglPaper *
313 lgl_db_lookup_paper_from_id (const gchar *id)
314 {
315         GList       *p;
316         lglPaper    *paper;
317
318         if (!papers)
319         {
320                 lgl_db_init ();
321         }
322
323         if (id == NULL)
324         {
325                 /* If no id, return first paper as a default */
326                 return lgl_paper_dup ((lglPaper *) papers->data);
327         }
328
329         for (p = papers; p != NULL; p = p->next)
330         {
331                 paper = (lglPaper *) p->data;
332                 if (ASCII_EQUAL (paper->id, id))
333                 {
334                         return lgl_paper_dup (paper);
335                 }
336         }
337
338         return NULL;
339 }
340
341
342 /**
343  * lgl_db_lookup_paper_id_from_name:
344  * @name: localized paper name stringp
345  *
346  * Lookup paper name string from localized paper name string.
347  *
348  * Returns: pointer to a newly allocated id string.
349  *
350  */
351 gchar *
352 lgl_db_lookup_paper_id_from_name (const gchar *name)
353 {
354         lglPaper *paper = NULL;
355         gchar    *id = NULL;
356
357         if (name != NULL)
358         {
359                 paper = lgl_db_lookup_paper_from_name (name);
360                 if ( paper != NULL )
361                 {
362                         id = g_strdup (paper->id);
363                         lgl_paper_free (paper);
364                         paper = NULL;
365                 }
366         }
367
368         return id;
369 }
370
371
372 /**
373  * lgl_db_lookup_paper_name_from_id:
374  * @id: paper id string
375  *
376  * Lookup localized paper name string from paper id string.
377  *
378  * Returns: pointer to a newly allocated localized paper name string.
379  *
380  */
381 gchar *
382 lgl_db_lookup_paper_name_from_id (const gchar         *id)
383 {
384         lglPaper *paper = NULL;
385         gchar    *name = NULL;
386
387         if (id != NULL)
388         {
389                 paper = lgl_db_lookup_paper_from_id (id);
390                 if ( paper != NULL )
391                 {
392                         name = g_strdup (paper->name);
393                         lgl_paper_free (paper);
394                         paper = NULL;
395                 }
396         }
397
398         return name;
399 }
400
401
402 /**
403  * lgl_db_is_paper_id_known:
404  * @id: paper id to test
405  *
406  * Determine if given paper id is known to libglabels.
407  *
408  * Returns: TRUE if id is known, otherwise FALSE.
409  *
410  */
411 gboolean
412 lgl_db_is_paper_id_known (const gchar *id)
413 {
414         GList       *p;
415         lglPaper    *paper;
416
417         if (!papers)
418         {
419                 lgl_db_init ();
420         }
421
422         if (id == NULL)
423         {
424                 return FALSE;
425         }
426
427         for (p = papers; p != NULL; p = p->next)
428         {
429                 paper = (lglPaper *) p->data;
430                 if (ASCII_EQUAL (paper->id, id))
431                 {
432                         return TRUE;
433                 }
434         }
435
436         return FALSE;
437 }
438
439 /**
440  * lgl_db_is_paper_id_other:
441  * @id: paper id to test
442  *
443  * Determine if given paper id is the special id "Other."
444  *
445  * Returns: TRUE if id is "Other", otherwise FALSE.
446  *
447  */
448 gboolean
449 lgl_db_is_paper_id_other (const gchar *id)
450 {
451         if (id == NULL)
452         {
453                 return FALSE;
454         }
455
456         return (ASCII_EQUAL (id, "Other"));
457 }
458
459
460 static GList *
461 read_papers (void)
462 {
463         gchar *data_dir;
464         GList *papers = NULL;
465
466         data_dir = LGL_SYSTEM_DATA_DIR;
467         papers = read_paper_files_from_dir (papers, data_dir);
468         g_free (data_dir);
469
470         data_dir = LGL_USER_DATA_DIR;
471         papers = read_paper_files_from_dir (papers, data_dir);
472         g_free (data_dir);
473
474         if (papers == NULL) {
475                 g_critical (_("Unable to locate paper size definitions.  Libglabels may not be installed correctly!"));
476         }
477
478         return papers;
479 }
480
481
482 static GList *
483 read_paper_files_from_dir (GList       *papers,
484                            const gchar *dirname)
485 {
486         GDir        *dp;
487         const gchar *filename, *extension;
488         gchar       *full_filename = NULL;
489         GError      *gerror = NULL;
490         GList       *new_papers = NULL;
491
492         if (dirname == NULL) {
493                 return papers;
494         }
495
496         if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
497                 return papers;
498         }
499
500         dp = g_dir_open (dirname, 0, &gerror);
501         if (gerror != NULL) {
502                 g_message ("cannot open data directory: %s", gerror->message );
503                 return papers;
504         }
505
506         while ((filename = g_dir_read_name (dp)) != NULL) {
507
508                 extension = strrchr (filename, '.');
509
510                 if (extension != NULL) {
511
512                         if ( ASCII_EQUAL (extension, ".paper") ||
513                              ASCII_EQUAL (filename, "paper-sizes.xml") )
514                         {
515
516                                 full_filename =
517                                     g_build_filename (dirname, filename, NULL);
518                                 new_papers =
519                                     lgl_xml_paper_read_papers_from_file (full_filename);
520                                 g_free (full_filename);
521
522                                 papers = g_list_concat (papers, new_papers);
523                                 new_papers = NULL;
524
525                         }
526
527                 }
528
529         }
530
531         g_dir_close (dp);
532
533         return papers;
534 }
535
536
537 /**
538  * lgl_db_print_known_papers:
539  *
540  * For debugging purposes: print a list of all paper definitions known to
541  * libglabels.
542  *
543  */
544 void
545 lgl_db_print_known_papers (void)
546 {
547         GList       *p;
548         lglPaper    *paper;
549
550         if (!papers) {
551                 lgl_db_init ();
552         }
553
554         g_print ("%s():\n", __FUNCTION__);
555         for (p = papers; p != NULL; p = p->next) {
556                 paper = (lglPaper *) p->data;
557
558                 g_print ("PAPER id=\"%s\", name=\"%s\", width=%gpts, height=%gpts\n",
559                          paper->id, paper->name, paper->width, paper->height);
560
561         }
562         g_print ("\n");
563
564 }
565
566
567 /*===========================================*/
568 /* Category db functions.                    */
569 /*===========================================*/
570
571 /**
572  * lgl_db_get_category_id_list:
573  *
574  * Get a list of all category ids known to libglabels.
575  *
576  * Returns: a list of category ids.
577  *
578  */
579 GList *
580 lgl_db_get_category_id_list (void)
581 {
582         GList           *ids = NULL;
583         GList           *p;
584         lglCategory     *category;
585
586         if (!categories)
587         {
588                 lgl_db_init ();
589         }
590
591         for ( p=categories; p != NULL; p=p->next )
592         {
593                 category = (lglCategory *)p->data;
594                 ids = g_list_append (ids, g_strdup (category->id));
595         }
596
597         return ids;
598 }
599
600
601 /**
602  * lgl_db_free_category_id_list:
603  * @ids: List of id strings to be freed.
604  *
605  * Free up all storage associated with an id list obtained with
606  * lgl_db_get_category_id_list().
607  *
608  */
609 void
610 lgl_db_free_category_id_list (GList *ids)
611 {
612         GList *p;
613
614         for (p = ids; p != NULL; p = p->next)
615         {
616                 g_free (p->data);
617                 p->data = NULL;
618         }
619
620         g_list_free (ids);
621 }
622
623
624 /**
625  * lgl_db_get_category_name_list:
626  *
627  * Get a list of all localized category names known to libglabels.
628  *
629  * Returns: a list of localized category names.
630  *
631  */
632 GList *
633 lgl_db_get_category_name_list (void)
634 {
635         GList           *names = NULL;
636         GList           *p;
637         lglCategory     *category;
638
639         if (!categories)
640         {
641                 lgl_db_init ();
642         }
643
644         for ( p=categories; p != NULL; p=p->next )
645         {
646                 category = (lglCategory *)p->data;
647                 names = g_list_append (names, g_strdup (category->name));
648         }
649
650         return names;
651 }
652
653
654 /**
655  * lgl_db_free_category_name_list:
656  * @names: List of localized category name strings to be freed.
657  *
658  * Free up all storage associated with a name list obtained with
659  * lgl_db_get_category_name_list().
660  *
661  */
662 void
663 lgl_db_free_category_name_list (GList *names)
664 {
665         GList *p;
666
667         for (p = names; p != NULL; p = p->next)
668         {
669                 g_free (p->data);
670                 p->data = NULL;
671         }
672
673         g_list_free (names);
674 }
675
676
677 /**
678  * lgl_db_lookup_category_from_name:
679  * @name: localized category name string
680  *
681  * Lookup category definition from localized category name string.
682  *
683  * Returns: pointer to a newly allocated #lglCategory structure.
684  *
685  */
686 lglCategory *
687 lgl_db_lookup_category_from_name (const gchar *name)
688 {
689         GList       *p;
690         lglCategory *category;
691
692         if (!categories)
693         {
694                 lgl_db_init ();
695         }
696
697         if (name == NULL)
698         {
699                 /* If no name, return first category as a default */
700                 return lgl_category_dup ((lglCategory *) categories->data);
701         }
702
703         for (p = categories; p != NULL; p = p->next)
704         {
705                 category = (lglCategory *) p->data;
706                 if (UTF8_EQUAL (category->name, name))
707                 {
708                         return lgl_category_dup (category);
709                 }
710         }
711
712         return NULL;
713 }
714
715
716 /**
717  * lgl_db_lookup_category_from_id:
718  * @id: category id string
719  *
720  * Lookup category definition from id string.
721  *
722  * Returns: pointer to a newly allocated #lglCategory structure.
723  *
724  */
725 lglCategory *
726 lgl_db_lookup_category_from_id (const gchar *id)
727 {
728         GList       *p;
729         lglCategory *category;
730
731         if (!categories)
732         {
733                 lgl_db_init ();
734         }
735
736         if (id == NULL)
737         {
738                 /* If no id, return first category as a default */
739                 return lgl_category_dup ((lglCategory *) categories->data);
740         }
741
742         for (p = categories; p != NULL; p = p->next)
743         {
744                 category = (lglCategory *) p->data;
745                 if (ASCII_EQUAL (category->id, id))
746                 {
747                         return lgl_category_dup (category);
748                 }
749         }
750
751         return NULL;
752 }
753
754
755 /**
756  * lgl_db_lookup_category_id_from_name:
757  * @name: localized category name stringp
758  *
759  * Lookup category name string from localized category name string.
760  *
761  * Returns: pointer to a newly allocated id string.
762  *
763  */
764 gchar *
765 lgl_db_lookup_category_id_from_name (const gchar *name)
766 {
767         lglCategory *category = NULL;
768         gchar       *id = NULL;
769
770         if (name != NULL)
771         {
772                 category = lgl_db_lookup_category_from_name (name);
773                 if ( category != NULL )
774                 {
775                         id = g_strdup (category->id);
776                         lgl_category_free (category);
777                         category = NULL;
778                 }
779         }
780
781         return id;
782 }
783
784
785 /**
786  * lgl_db_lookup_category_name_from_id:
787  * @id: category id string
788  *
789  * Lookup localized category name string from category id string.
790  *
791  * Returns: pointer to a newly allocated localized category name string.
792  *
793  */
794 gchar *
795 lgl_db_lookup_category_name_from_id (const gchar         *id)
796 {
797         lglCategory *category = NULL;
798         gchar       *name = NULL;
799
800         if (id != NULL)
801         {
802                 category = lgl_db_lookup_category_from_id (id);
803                 if ( category != NULL )
804                 {
805                         name = g_strdup (category->name);
806                         lgl_category_free (category);
807                         category = NULL;
808                 }
809         }
810
811         return name;
812 }
813
814
815 /**
816  * lgl_db_is_category_id_known:
817  * @id: category id to test
818  *
819  * Determine if given category id is known to libglabels.
820  *
821  * Returns: TRUE if id is known, otherwise FALSE.
822  *
823  */
824 gboolean
825 lgl_db_is_category_id_known (const gchar *id)
826 {
827         GList       *p;
828         lglCategory *category;
829
830         if (!categories)
831         {
832                 lgl_db_init ();
833         }
834
835         if (id == NULL)
836         {
837                 return FALSE;
838         }
839
840         for (p = categories; p != NULL; p = p->next)
841         {
842                 category = (lglCategory *) p->data;
843                 if (ASCII_EQUAL (category->id, id))
844                 {
845                         return TRUE;
846                 }
847         }
848
849         return FALSE;
850 }
851
852
853 static GList *
854 read_categories (void)
855 {
856         gchar *data_dir;
857         GList *categories = NULL;
858
859         data_dir = LGL_SYSTEM_DATA_DIR;
860         categories = read_category_files_from_dir (categories, data_dir);
861         g_free (data_dir);
862
863         data_dir = LGL_USER_DATA_DIR;
864         categories = read_category_files_from_dir (categories, data_dir);
865         g_free (data_dir);
866
867         if (categories == NULL) {
868                 g_critical (_("Unable to locate category definitions.  Libglabels may not be installed correctly!"));
869         }
870
871         return categories;
872 }
873
874
875 static GList *
876 read_category_files_from_dir (GList       *categories,
877                               const gchar *dirname)
878 {
879         GDir        *dp;
880         const gchar *filename, *extension;
881         gchar       *full_filename = NULL;
882         GError      *gerror = NULL;
883         GList       *new_categories = NULL;
884
885         if (dirname == NULL) {
886                 return categories;
887         }
888
889         if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
890                 return categories;
891         }
892
893         dp = g_dir_open (dirname, 0, &gerror);
894         if (gerror != NULL) {
895                 g_message ("cannot open data directory: %s", gerror->message );
896                 return categories;
897         }
898
899         while ((filename = g_dir_read_name (dp)) != NULL) {
900
901                 extension = strrchr (filename, '.');
902
903                 if (extension != NULL) {
904
905                         if ( ASCII_EQUAL (extension, ".category") ||
906                              ASCII_EQUAL (filename, "categories.xml") )
907                         {
908
909                                 full_filename =
910                                     g_build_filename (dirname, filename, NULL);
911                                 new_categories =
912                                     lgl_xml_category_read_categories_from_file (full_filename);
913                                 g_free (full_filename);
914
915                                 categories = g_list_concat (categories, new_categories);
916                                 new_categories = NULL;
917
918                         }
919
920                 }
921
922         }
923
924         g_dir_close (dp);
925
926         return categories;
927 }
928
929
930 /**
931  * lgl_db_print_known_categories:
932  *
933  * For debugging purposes: print a list of all category definitions known to
934  * libglabels.
935  *
936  */
937 void
938 lgl_db_print_known_categories (void)
939 {
940         GList       *p;
941         lglCategory *category;
942
943         if (!categories) {
944                 lgl_db_init ();
945         }
946
947         g_print ("%s():\n", __FUNCTION__);
948         for (p = categories; p != NULL; p = p->next) {
949                 category = (lglCategory *) p->data;
950
951                 g_print ("CATEGORY id=\"%s\", name=\"%s\"\n", category->id, category->name);
952
953         }
954         g_print ("\n");
955
956 }
957
958
959
960 /*===========================================*/
961 /* Brand db functions.                       */
962 /*===========================================*/
963
964 /**
965  * lgl_db_get_brand_list:
966  * @paper_id: If non NULL, limit results to given page size.
967  * @category_id: If non NULL, limit results to given template category.
968  *
969  * Get a list of all valid brands of templates in the template database.
970  * Results can be filtered by page size and/or template category.  A list of valid page
971  * sizes can be obtained using lgl_db_get_paper_id_list().  A list of valid template
972  * categories can be obtained using lgl_db_get_category_id_list().
973  *
974  * Returns: a list of brands
975  */
976 GList *
977 lgl_db_get_brand_list (const gchar *paper_id,
978                        const gchar *category_id)
979 {
980         GList            *p_tmplt, *p_alias;
981         lglTemplate      *template;
982         lglTemplateAlias *alias;
983         GList            *brands = NULL;
984
985         if (!templates)
986         {
987                 lgl_db_init ();
988         }
989
990         for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
991         {
992                 template = (lglTemplate *) p_tmplt->data;
993                 if (lgl_template_does_page_size_match (template, paper_id) &&
994                     lgl_template_does_category_match (template, category_id))
995                 {
996                         for (p_alias = template->aliases; p_alias != NULL;
997                              p_alias = p_alias->next)
998                         {
999                                 alias = (lglTemplateAlias *)p_alias->data;
1000
1001                                 if ( !g_list_find_custom (brands, alias->brand,
1002                                                           (GCompareFunc)lgl_str_utf8_casecmp) )
1003                                 {
1004                                         brands = g_list_insert_sorted (brands,
1005                                                                        g_strdup (alias->brand),
1006                                                                        (GCompareFunc)lgl_str_utf8_casecmp);
1007                                 }
1008                         }
1009                 }
1010         }
1011
1012         return brands;
1013 }
1014
1015
1016 /**
1017  * lgl_db_free_brand_list:
1018  * @brands: List of template brand strings to be freed.
1019  *
1020  * Free up all storage associated with a list of template names obtained with
1021  * lgl_db_get_brand_list().
1022  *
1023  */
1024 void
1025 lgl_db_free_brand_list (GList *brands)
1026 {
1027         GList *p_brand;
1028
1029         for (p_brand = brands; p_brand != NULL; p_brand = p_brand->next)
1030         {
1031                 g_free (p_brand->data);
1032                 p_brand->data = NULL;
1033         }
1034
1035         g_list_free (brands);
1036 }
1037
1038
1039
1040 /*===========================================*/
1041 /* Template db functions.                    */
1042 /*===========================================*/
1043
1044 /**
1045  * lgl_db_register_template:
1046  * @template:  Pointer to a template structure to add to database.
1047  *
1048  * Register a template.  This function adds a template to the template database.
1049  * The template will be stored in an individual XML file in the user template directory.
1050  *
1051  * Returns: Status of registration attempt (#lglDbRegStatus)
1052  */
1053 lglDbRegStatus
1054 lgl_db_register_template (const lglTemplate *template)
1055 {
1056         lglTemplate *template_copy;
1057         gchar       *dir, *filename, *abs_filename;
1058         gint         bytes_written;
1059
1060         if (!templates)
1061         {
1062                 lgl_db_init ();
1063         }
1064
1065         if (lgl_db_does_template_exist (template->brand, template->part))
1066         {
1067                 return LGL_DB_REG_BRAND_PART_EXISTS;
1068         }
1069
1070         if (lgl_db_is_paper_id_known (template->paper_id))
1071         {
1072                 dir = LGL_USER_DATA_DIR;
1073                 mkdir (dir, 0775); /* Try to make sure directory exists. */
1074                 filename = g_strdup_printf ("%s_%s.template", template->brand, template->part);
1075                 abs_filename = g_build_filename (dir, filename, NULL);
1076                 bytes_written = lgl_xml_template_write_template_to_file (template, abs_filename);
1077                 g_free (dir);
1078                 g_free (filename);
1079                 g_free (abs_filename);
1080
1081                 if (bytes_written > 0)
1082                 {
1083                         template_copy = lgl_template_dup (template);
1084                         lgl_template_add_category (template_copy, "user-defined");
1085                         templates = g_list_append (templates, template_copy);
1086                         return LGL_DB_REG_OK;
1087                 }
1088                 else
1089                 {
1090                         lgl_template_free (template_copy);
1091                         return LGL_DB_REG_FILE_WRITE_ERROR;
1092                 }
1093         }
1094         else
1095         {
1096                 g_message ("Cannot register new template with unknown page size.");
1097                 return LGL_DB_REG_BAD_PAPER_ID;
1098         }
1099
1100 }
1101
1102
1103 /**
1104  * lgl_db_does_template_exist:
1105  * @brand: Brand name.
1106  * @part:  Part name/number.
1107  *
1108  * This function tests whether a template with the given brand and part name/number exists.
1109  *
1110  * Returns:  TRUE if such a template exists in the database.
1111  */
1112 gboolean
1113 lgl_db_does_template_exist (const gchar *brand,
1114                             const gchar *part)
1115 {
1116         GList            *p_tmplt, *p_alias;
1117         lglTemplate      *template;
1118         lglTemplateAlias *alias;
1119
1120         if (!templates)
1121         {
1122                 lgl_db_init ();
1123         }
1124
1125         if ((brand == NULL) || (part == NULL))
1126         {
1127                 return FALSE;
1128         }
1129
1130         for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1131         {
1132                 template = (lglTemplate *) p_tmplt->data;
1133                 for (p_alias = template->aliases; p_alias != NULL; p_alias = p_alias->next)
1134                 {
1135                         alias = (lglTemplateAlias *)p_alias->data;
1136
1137                         if ( UTF8_EQUAL (brand, alias->brand) &&
1138                              UTF8_EQUAL (part, alias->part) )
1139                         {
1140                                 return TRUE;
1141                         }
1142                 }
1143         }
1144
1145         return FALSE;
1146 }
1147
1148
1149 /**
1150  * lgl_db_get_template_name_list_unique:
1151  * @brand:     If non NULL, limit results to given brand
1152  * @paper_id: If non NULL, limit results to given page size.
1153  * @category_id: If non NULL, limit results to given template category.
1154  *
1155  * Get a list of valid names of unique templates in the template database.  Results
1156  * can be filtered by page size and/or template category.  A list of valid page sizes
1157  * can be obtained using lgl_db_get_paper_id_list().  A list of valid template categories
1158  * can be obtained using lgl_db_get_category_id_list().
1159  *
1160  * This function differs from lgl_db_get_template_name_list_all(), because it does not
1161  * return multiple names for the same template.
1162  *
1163  * Returns: a list of template names.
1164  */
1165 GList *
1166 lgl_db_get_template_name_list_unique (const gchar *brand,
1167                                       const gchar *paper_id,
1168                                       const gchar *category_id)
1169 {
1170         GList       *p_tmplt;
1171         lglTemplate *template;
1172         gchar       *name;
1173         GList       *names = NULL;
1174
1175         if (!templates)
1176         {
1177                 lgl_db_init ();
1178         }
1179
1180         for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1181         {
1182                 template = (lglTemplate *) p_tmplt->data;
1183
1184                 if (lgl_template_does_brand_match (template, brand) &&
1185                     lgl_template_does_page_size_match (template, paper_id) &&
1186                     lgl_template_does_category_match (template, category_id))
1187                 {
1188                         name = g_strdup_printf ("%s %s", template->brand, template->part);
1189                         names = g_list_insert_sorted (names, name,
1190                                                       (GCompareFunc)g_utf8_collate);
1191                 }
1192         }
1193
1194         return names;
1195 }
1196
1197
1198 /**
1199  * lgl_db_get_template_name_list_all:
1200  * @brand:     If non NULL, limit results to given brand
1201  * @paper_id: If non NULL, limit results to given page size.
1202  * @category_id: If non NULL, limit results to given template category.
1203  *
1204  * Get a list of all valid names and aliases of templates in the template database.
1205  * Results can be filtered by page size and/or template category.  A list of valid page
1206  * sizes can be obtained using lgl_db_get_paper_id_list().  A list of valid template
1207  * categories can be obtained using lgl_db_get_category_id_list().
1208  *
1209  * This function differs from lgl_db_get_template_name_list_unique(), because it will
1210  * return multiple names for the same template.
1211  *
1212  * Returns: a list of template names and aliases.
1213  */
1214 GList *
1215 lgl_db_get_template_name_list_all (const gchar *brand,
1216                                    const gchar *paper_id,
1217                                    const gchar *category_id)
1218 {
1219         GList            *p_tmplt, *p_alias;
1220         lglTemplate      *template;
1221         lglTemplateAlias *alias;
1222         gchar            *name;
1223         GList            *names = NULL;
1224
1225         if (!templates)
1226         {
1227                 lgl_db_init ();
1228         }
1229
1230         for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1231         {
1232                 template = (lglTemplate *) p_tmplt->data;
1233                 if (lgl_template_does_page_size_match (template, paper_id) &&
1234                     lgl_template_does_category_match (template, category_id))
1235                 {
1236                         for (p_alias = template->aliases; p_alias != NULL;
1237                              p_alias = p_alias->next)
1238                         {
1239                                 alias = (lglTemplateAlias *)p_alias->data;
1240
1241                                 if ( !brand || UTF8_EQUAL( alias->brand, brand) )
1242                                 {
1243                                         name = g_strdup_printf ("%s %s", alias->brand, alias->part);
1244                                         names = g_list_insert_sorted (names, name,
1245                                                                       (GCompareFunc)g_utf8_collate);
1246                                 }
1247                         }
1248                 }
1249         }
1250
1251         return names;
1252 }
1253
1254
1255 /**
1256  * lgl_db_free_template_name_list:
1257  * @names: List of template name strings to be freed.
1258  *
1259  * Free up all storage associated with a list of template names obtained with
1260  * lgl_db_get_template_name_list_all() or lgl_db_get_template_name_list_unique().
1261  *
1262  */
1263 void
1264 lgl_db_free_template_name_list (GList *names)
1265 {
1266         GList *p_name;
1267
1268         for (p_name = names; p_name != NULL; p_name = p_name->next)
1269         {
1270                 g_free (p_name->data);
1271                 p_name->data = NULL;
1272         }
1273
1274         g_list_free (names);
1275 }
1276
1277
1278 /**
1279  * lgl_db_lookup_template_from_name:
1280  * @name: name string
1281  *
1282  * Lookup template in template database from name string.
1283  *
1284  * Returns: pointer to a newly allocated #lglTemplate structure.
1285  *
1286  */
1287 lglTemplate *
1288 lgl_db_lookup_template_from_name (const gchar *name)
1289 {
1290         GList            *p_tmplt, *p_alias;
1291         lglTemplate      *template;
1292         lglTemplateAlias *alias;
1293         gchar            *candidate_name;
1294
1295         if (!templates)
1296         {
1297                 lgl_db_init ();
1298         }
1299
1300         if (name == NULL)
1301         {
1302                 /* If no name, return first template as a default */
1303                 return lgl_template_dup ((lglTemplate *) templates->data);
1304         }
1305
1306         for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1307         {
1308                 template = (lglTemplate *) p_tmplt->data;
1309                 for (p_alias = template->aliases; p_alias != NULL; p_alias = p_alias->next)
1310                 {
1311                         alias = (lglTemplateAlias *)p_alias->data;
1312                         candidate_name = g_strdup_printf ("%s %s", alias->brand, alias->part);
1313
1314                         if ( UTF8_EQUAL (candidate_name, name) ) {
1315                                 g_free (candidate_name);
1316                                 return lgl_template_dup (template);
1317                         }
1318                         g_free (candidate_name);
1319                 }
1320         }
1321
1322         /* No matching template has been found so return the first template */
1323         return lgl_template_dup ((lglTemplate *) templates->data);
1324 }
1325
1326
1327 static GList *
1328 read_templates (void)
1329 {
1330         gchar       *data_dir;
1331         GList       *templates = NULL;
1332         GList       *p;
1333         lglTemplate *template;
1334
1335         /*
1336          * User defined templates.  Add to user-defined category.
1337          */
1338         data_dir = LGL_USER_DATA_DIR;
1339         templates = read_template_files_from_dir (templates, data_dir);
1340         g_free (data_dir);
1341         for ( p=templates; p != NULL; p=p->next )
1342         {
1343                 template = (lglTemplate *)p->data;
1344                 lgl_template_add_category (template, "user-defined");
1345         }
1346
1347         /*
1348          * System templates.
1349          */
1350         data_dir = LGL_SYSTEM_DATA_DIR;
1351         templates = read_template_files_from_dir (templates, data_dir);
1352         g_free (data_dir);
1353
1354         if (templates == NULL)
1355         {
1356                 g_critical (_("Unable to locate any template files.  Libglabels may not be installed correctly!"));
1357         }
1358
1359         return templates;
1360 }
1361
1362
1363 static GList *
1364 read_template_files_from_dir (GList       *templates,
1365                               const gchar *dirname)
1366 {
1367         GDir        *dp;
1368         const gchar *filename, *extension, *extension2;
1369         gchar       *full_filename = NULL;
1370         GError      *gerror = NULL;
1371         GList       *new_templates = NULL;
1372
1373         if (dirname == NULL)
1374                 return templates;
1375
1376         if (!g_file_test (dirname, G_FILE_TEST_EXISTS))
1377         {
1378                 return templates;
1379         }
1380
1381         dp = g_dir_open (dirname, 0, &gerror);
1382         if (gerror != NULL)
1383         {
1384                 g_message ("cannot open data directory: %s", gerror->message );
1385                 return templates;
1386         }
1387
1388         while ((filename = g_dir_read_name (dp)) != NULL)
1389         {
1390
1391                 extension = strrchr (filename, '.');
1392                 extension2 = strrchr (filename, '-');
1393
1394                 if ( (extension && ASCII_EQUAL (extension, ".template")) ||
1395                      (extension2 && ASCII_EQUAL (extension2, "-templates.xml")) )
1396                 {
1397
1398                         full_filename = g_build_filename (dirname, filename, NULL);
1399                         new_templates =
1400                                 lgl_xml_template_read_templates_from_file (full_filename);
1401                         g_free (full_filename);
1402
1403                         templates = g_list_concat (templates, new_templates);
1404                         new_templates = NULL;
1405                 }
1406
1407         }
1408
1409         g_dir_close (dp);
1410
1411         return templates;
1412 }
1413
1414
1415 static lglTemplate *
1416 template_full_page (const gchar *paper_id)
1417 {
1418         lglPaper              *paper = NULL;
1419         lglTemplate           *template = NULL;
1420         lglTemplateFrame      *frame = NULL;
1421         gchar                 *part;
1422         gchar                 *desc;
1423
1424         g_return_val_if_fail (paper_id, NULL);
1425
1426         paper = lgl_db_lookup_paper_from_id (paper_id);
1427         if ( paper == NULL )
1428         {
1429                 return NULL;
1430         }
1431
1432         part = g_strdup_printf ("%s-Full-Page", paper->id);
1433         desc = g_strdup_printf (_("Generic %s full page template"), paper->name);
1434
1435         template = lgl_template_new ("Generic", part, desc,
1436                                      paper_id, paper->width, paper->height);
1437
1438
1439         frame = lgl_template_frame_rect_new ("0",
1440                                              paper->width,
1441                                              paper->height,
1442                                              0.0,
1443                                              0.0,
1444                                              0.0);
1445         lgl_template_add_frame (template, frame);
1446
1447         lgl_template_frame_add_layout (frame, lgl_template_layout_new (1, 1, 0., 0., 0., 0.));
1448
1449         lgl_template_frame_add_markup (frame, lgl_template_markup_margin_new (9.0));
1450
1451         g_free (desc);
1452         desc = NULL;
1453         lgl_paper_free (paper);
1454         paper = NULL;
1455
1456         return template;
1457 }
1458
1459
1460 /**
1461  * lgl_db_print_known_templates:
1462  *
1463  * Print all known templates (for debugging purposes).
1464  *
1465  */
1466 void
1467 lgl_db_print_known_templates (void)
1468 {
1469         GList       *p;
1470         lglTemplate *template;
1471
1472         g_print ("%s():\n", __FUNCTION__);
1473         for (p=templates; p!=NULL; p=p->next)
1474         {
1475                 template = (lglTemplate *)p->data;
1476
1477                 g_print("TEMPLATE brand=\"%s\", part=\"%s\", description=\"%s\"\n",
1478                         template->brand, template->part, template->description);
1479
1480         }
1481         g_print ("\n");
1482
1483 }
1484
1485 /**
1486  * lgl_db_print_aliases:
1487  *   @template: template
1488  *
1489  * Print all aliases of a template (for debugging purposes).
1490  *
1491  */
1492 void
1493 lgl_db_print_aliases (const lglTemplate *template)
1494 {
1495         GList            *p;
1496         lglTemplateAlias *alias;
1497
1498         g_print ("%s():\n", __FUNCTION__);
1499         for (p=template->aliases; p!=NULL; p=p->next)
1500         {
1501                 alias = (lglTemplateAlias *)p->data;
1502                 
1503                 g_print("Alias: brand=\"%s\", part=\"%s\"\n", alias->brand, alias->part);
1504
1505         }
1506         g_print ("\n");
1507
1508 }
1509
1510