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