]> git.sur5r.net Git - glabels/blob - libglabels/db.c
Search both ~/.glabels and ${XDG_CONFIG_HOME}/libglabels/templates.
[glabels] / 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 <glib-object.h>
28 #include <string.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31
32 #include "libglabels-private.h"
33
34 #include "xml-paper.h"
35 #include "xml-category.h"
36 #include "xml-vendor.h"
37 #include "xml-template.h"
38
39 /*===========================================*/
40 /* Private macros and constants.             */
41 /*===========================================*/
42
43 /* Data system and user data directories.  (must free w/ g_free()) */
44 #define SYSTEM_CONFIG_DIR     g_build_filename (LIBGLABELS_CONFIG_DIR, "templates", NULL)
45 #define USER_CONFIG_DIR       g_build_filename (g_get_user_config_dir (), "libglabels", "templates" , NULL)
46 #define ALT_USER_CONFIG_DIR   g_build_filename (g_get_home_dir (), ".glabels", NULL)
47
48
49 /*===========================================*/
50 /* Private types                             */
51 /*===========================================*/
52
53 #define TYPE_LGL_DB_MODEL              (lgl_db_model_get_type ())
54 #define LGL_DB_MODEL(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_LGL_DB_MODEL, lglDbModel))
55 #define LGL_DB_MODEL_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_LGL_DB_MODEL, lglDbModelClass))
56 #define IS_LGL_DB_MODEL(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_LGL_DB_MODEL))
57 #define IS_LGL_DB_MODEL_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_LGL_DB_MODEL))
58 #define LGL_DB_MODEL_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), TYPE_LGL_DB_MODEL, lglDbModelClass))
59
60
61 typedef struct _lglDbModel          lglDbModel;
62 typedef struct _lglDbModelClass     lglDbModelClass;
63
64
65 struct _lglDbModel {
66         GObject     parent;
67
68         GList      *papers;
69         GList      *categories;
70         GList      *vendors;
71         GList      *templates;
72
73         GHashTable *template_cache;
74 };
75
76
77 struct _lglDbModelClass {
78         GObjectClass  parent_class;
79
80         /*
81          * Signals
82          */
83         void (*changed)     (lglDbModel *this,
84                              gpointer    user_data);
85
86 };
87
88
89 enum {
90         CHANGED,
91         LAST_SIGNAL
92 };
93
94
95 /*===========================================*/
96 /* Private globals                           */
97 /*===========================================*/
98
99 static guint signals[LAST_SIGNAL] = {0};
100
101 static lglDbModel *model = NULL;
102
103
104 /*===========================================*/
105 /* Local function prototypes                 */
106 /*===========================================*/
107
108 static void   lgl_db_model_finalize        (GObject     *object);
109
110 static void   add_to_template_cache        (lglTemplate *template);
111
112 static GList *read_papers                  (void);
113 static GList *read_paper_files_from_dir    (GList       *papers,
114                                             const gchar *dirname);
115
116 static GList *read_categories              (void);
117 static GList *read_category_files_from_dir (GList       *categories,
118                                             const gchar *dirname);
119
120 static GList *read_vendors                 (void);
121 static GList *read_vendor_files_from_dir   (GList       *vendors,
122                                             const gchar *dirname);
123
124 static void   read_templates               (void);
125 static void   read_template_files_from_dir (const gchar *dirname);
126
127 static lglTemplate *template_full_page     (const gchar *page_size);
128
129
130 /*****************************************************************************/
131 /* Object infrastructure.                                                    */
132 /*****************************************************************************/
133 G_DEFINE_TYPE (lglDbModel, lgl_db_model, G_TYPE_OBJECT);
134
135
136 /*****************************************************************************/
137 /* Class Init Function.                                                      */
138 /*****************************************************************************/
139 static void
140 lgl_db_model_class_init (lglDbModelClass *class)
141 {
142         GObjectClass  *gobject_class = (GObjectClass *) class;
143
144         lgl_db_model_parent_class = g_type_class_peek_parent (class);
145
146         gobject_class->finalize = lgl_db_model_finalize;
147
148         signals[CHANGED] =
149                 g_signal_new ("changed",
150                               G_OBJECT_CLASS_TYPE (gobject_class),
151                               G_SIGNAL_RUN_LAST,
152                               G_STRUCT_OFFSET (lglDbModelClass, changed),
153                               NULL, NULL,
154                               g_cclosure_marshal_VOID__VOID,
155                               G_TYPE_NONE,
156                               0);
157 }
158
159
160 /*****************************************************************************/
161 /* Object Instance Init Function.                                            */
162 /*****************************************************************************/
163 static void
164 lgl_db_model_init (lglDbModel *this)
165 {
166         this->template_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)lgl_template_free);
167 }
168
169
170 /*****************************************************************************/
171 /* Finalize Method.                                                          */
172 /*****************************************************************************/
173 static void
174 lgl_db_model_finalize (GObject *object)
175 {
176         lglDbModel    *this;
177         GList         *p;
178
179         g_return_if_fail (object && IS_LGL_DB_MODEL (object));
180         this = LGL_DB_MODEL (object);
181
182         g_hash_table_unref (this->template_cache);
183
184         for (p = this->papers; p != NULL; p = p->next)
185         {
186                 g_free (p->data);
187                 p->data = NULL;
188         }
189         g_list_free (this->papers);
190
191         for (p = this->categories; p != NULL; p = p->next)
192         {
193                 g_free (p->data);
194                 p->data = NULL;
195         }
196         g_list_free (this->categories);
197
198         for (p = this->vendors; p != NULL; p = p->next)
199         {
200                 g_free (p->data);
201                 p->data = NULL;
202         }
203         g_list_free (this->vendors);
204
205         for (p = this->templates; p != NULL; p = p->next)
206         {
207                 lgl_template_free ((lglTemplate *)p->data);
208                 p->data = NULL;
209         }
210         g_list_free (this->templates);
211
212         G_OBJECT_CLASS (lgl_db_model_parent_class)->finalize (object);
213 }
214
215
216 /*****************************************************************************/
217 /** New Object Generator.                                                    */
218 /*****************************************************************************/
219 lglDbModel *
220 lgl_db_model_new (void)
221 {
222         lglDbModel *this;
223
224         this = g_object_new (TYPE_LGL_DB_MODEL, NULL);
225
226         return this;
227 }
228
229
230 /*===========================================*/
231 /* Module initialization                     */
232 /*===========================================*/
233
234 /**
235  * lgl_db_init:
236  *
237  * Initialize all libglabels subsystems.  It is not necessary for an application to call
238  * lgl_db_init(), because libglabels will initialize on demand.  An application programmer may
239  * choose to call lgl_db_init() at startup to minimize the impact of the first libglabels call
240  * on GUI response time.
241  *
242  * This function initializes its paper definitions, category definitions, vendor definitions,
243  * and its template database. It will search both system and user template directories to locate
244  * this data.
245  */
246 void
247 lgl_db_init (void)
248 {
249         lglPaper    *paper_other;
250         lglCategory *category_user_defined;
251         lglTemplate *template;
252         GList       *page_sizes;
253         GList       *p;
254
255         model = lgl_db_model_new ();
256
257         /*
258          * Paper definitions
259          */
260         model->papers = read_papers ();
261
262         /* Create and append an "Other" entry. */
263         /* Translators: "Other" here means other page size.  Meaning a page size
264          * other than the standard ones that libglabels knows about such as
265          * "letter", "A4", etc. */
266         paper_other = lgl_paper_new ("Other", _("Other"), 0.0, 0.0, NULL);
267         model->papers = g_list_append (model->papers, paper_other);
268
269         /*
270          * Categories
271          */
272         model->categories = read_categories ();
273
274         /* Create and append a "User defined" entry. */
275         category_user_defined = lgl_category_new ("user-defined", _("User defined"));
276         model->categories = g_list_append (model->categories, category_user_defined);
277
278         /*
279          * Vendors
280          */
281         model->vendors = read_vendors ();
282
283         /*
284          * Templates
285          */
286         read_templates ();
287
288         /* Create and append generic full page templates. */
289         page_sizes = lgl_db_get_paper_id_list ();
290         for ( p=page_sizes; p != NULL; p=p->next )
291         {
292                 if ( !lgl_db_is_paper_id_other (p->data) )
293                 {
294                         template = template_full_page (p->data);
295                         _lgl_db_register_template_internal (template);
296                         lgl_template_free (template);
297                 }
298         }
299         lgl_db_free_paper_id_list (page_sizes);
300
301 }
302
303
304 /**
305  * lgl_db_notify_add:
306  * @func: Callback function to be called when database changes.
307  * @user_data: Passback user data to supply to callback function.
308  *
309  * Register a notification callback function to be called when the database changes.
310  *
311  * Returns: an ID for this notification registration.
312  */
313 gulong
314 lgl_db_notify_add (lglDbNotifyFunc func,
315                    gpointer        user_data)
316 {
317         if (!model)
318         {
319                 lgl_db_init ();
320         }
321
322         return g_signal_connect_swapped (G_OBJECT (model), "changed", G_CALLBACK (func), user_data);
323 }
324
325
326 /**
327  * lgl_db_notify_remove:
328  * @id: ID of notification registration to cancel (see lgl_db_notify_add()).
329  *
330  * Cancel a previous registration a notification callback function.
331  */
332 void
333 lgl_db_notify_remove  (gulong id)
334 {
335         g_signal_handler_disconnect (G_OBJECT (model), id);
336 }
337
338
339 /*===========================================*/
340 /* Paper db functions.                       */
341 /*===========================================*/
342
343 /**
344  * lgl_db_get_paper_id_list:
345  *
346  * Get a list of all paper ids known to libglabels.
347  *
348  * Returns: a list of paper ids.
349  *
350  */
351 GList *
352 lgl_db_get_paper_id_list (void)
353 {
354         GList           *ids = NULL;
355         GList           *p;
356         lglPaper        *paper;
357
358         if (!model)
359         {
360                 lgl_db_init ();
361         }
362
363         for ( p=model->papers; p != NULL; p=p->next )
364         {
365                 paper = (lglPaper *)p->data;
366                 ids = g_list_append (ids, g_strdup (paper->id));
367         }
368
369         return ids;
370 }
371
372
373 /**
374  * lgl_db_free_paper_id_list:
375  * @ids: List of id strings to be freed.
376  *
377  * Free up all storage associated with an id list obtained with
378  * lgl_db_get_paper_id_list().
379  *
380  */
381 void
382 lgl_db_free_paper_id_list (GList *ids)
383 {
384         GList *p;
385
386         for (p = ids; p != NULL; p = p->next)
387         {
388                 g_free (p->data);
389                 p->data = NULL;
390         }
391
392         g_list_free (ids);
393 }
394
395
396 /**
397  * lgl_db_get_paper_name_list:
398  *
399  * Get a list of all localized paper names known to libglabels.
400  *
401  * Returns: a list of localized paper names.
402  *
403  */
404 GList *
405 lgl_db_get_paper_name_list (void)
406 {
407         GList           *names = NULL;
408         GList           *p;
409         lglPaper        *paper;
410
411         if (!model)
412         {
413                 lgl_db_init ();
414         }
415
416         for ( p=model->papers; p != NULL; p=p->next )
417         {
418                 paper = (lglPaper *)p->data;
419                 names = g_list_append (names, g_strdup (paper->name));
420         }
421
422         return names;
423 }
424
425
426 /**
427  * lgl_db_free_paper_name_list:
428  * @names: List of localized paper name strings to be freed.
429  *
430  * Free up all storage associated with a name list obtained with
431  * lgl_db_get_paper_name_list().
432  *
433  */
434 void
435 lgl_db_free_paper_name_list (GList *names)
436 {
437         GList *p;
438
439         for (p = names; p != NULL; p = p->next)
440         {
441                 g_free (p->data);
442                 p->data = NULL;
443         }
444
445         g_list_free (names);
446 }
447
448
449 /**
450  * lgl_db_lookup_paper_from_name:
451  * @name: localized paper name string
452  *
453  * Lookup paper definition from localized paper name string.
454  *
455  * Returns: pointer to a newly allocated #lglPaper structure.
456  *
457  */
458 lglPaper *
459 lgl_db_lookup_paper_from_name (const gchar *name)
460 {
461         GList       *p;
462         lglPaper    *paper;
463
464         if (!model)
465         {
466                 lgl_db_init ();
467         }
468
469         if (name == NULL)
470         {
471                 /* If no name, return first paper as a default */
472                 return lgl_paper_dup ((lglPaper *) model->papers->data);
473         }
474
475         for (p = model->papers; p != NULL; p = p->next)
476         {
477                 paper = (lglPaper *) p->data;
478                 if (UTF8_EQUAL (paper->name, name))
479                 {
480                         return lgl_paper_dup (paper);
481                 }
482         }
483
484         return NULL;
485 }
486
487
488 /**
489  * lgl_db_lookup_paper_from_id:
490  * @id: paper id string
491  *
492  * Lookup paper definition from id string.
493  *
494  * Returns: pointer to a newly allocated #lglPaper structure.
495  *
496  */
497 lglPaper *
498 lgl_db_lookup_paper_from_id (const gchar *id)
499 {
500         GList       *p;
501         lglPaper    *paper;
502
503         if (!model)
504         {
505                 lgl_db_init ();
506         }
507
508         if (id == NULL)
509         {
510                 /* If no id, return first paper as a default */
511                 return lgl_paper_dup ((lglPaper *) model->papers->data);
512         }
513
514         for (p = model->papers; p != NULL; p = p->next)
515         {
516                 paper = (lglPaper *) p->data;
517                 if (ASCII_EQUAL (paper->id, id))
518                 {
519                         return lgl_paper_dup (paper);
520                 }
521         }
522
523         return NULL;
524 }
525
526
527 /**
528  * lgl_db_lookup_paper_id_from_name:
529  * @name: localized paper name stringp
530  *
531  * Lookup paper name string from localized paper name string.
532  *
533  * Returns: pointer to a newly allocated id string.
534  *
535  */
536 gchar *
537 lgl_db_lookup_paper_id_from_name (const gchar *name)
538 {
539         lglPaper *paper = NULL;
540         gchar    *id = NULL;
541
542         if (name != NULL)
543         {
544                 paper = lgl_db_lookup_paper_from_name (name);
545                 if ( paper != NULL )
546                 {
547                         id = g_strdup (paper->id);
548                         lgl_paper_free (paper);
549                         paper = NULL;
550                 }
551         }
552
553         return id;
554 }
555
556
557 /**
558  * lgl_db_lookup_paper_name_from_id:
559  * @id: paper id string
560  *
561  * Lookup localized paper name string from paper id string.
562  *
563  * Returns: pointer to a newly allocated localized paper name string.
564  *
565  */
566 gchar *
567 lgl_db_lookup_paper_name_from_id (const gchar         *id)
568 {
569         lglPaper *paper = NULL;
570         gchar    *name = NULL;
571
572         if (id != NULL)
573         {
574                 paper = lgl_db_lookup_paper_from_id (id);
575                 if ( paper != NULL )
576                 {
577                         name = g_strdup (paper->name);
578                         lgl_paper_free (paper);
579                         paper = NULL;
580                 }
581         }
582
583         return name;
584 }
585
586
587 /**
588  * lgl_db_is_paper_id_known:
589  * @id: paper id to test
590  *
591  * Determine if given paper id is known to libglabels.
592  *
593  * Returns: TRUE if id is known, otherwise FALSE.
594  *
595  */
596 gboolean
597 lgl_db_is_paper_id_known (const gchar *id)
598 {
599         GList       *p;
600         lglPaper    *paper;
601
602         if (!model)
603         {
604                 lgl_db_init ();
605         }
606
607         if (id == NULL)
608         {
609                 return FALSE;
610         }
611
612         for (p = model->papers; p != NULL; p = p->next)
613         {
614                 paper = (lglPaper *) p->data;
615                 if (ASCII_EQUAL (paper->id, id))
616                 {
617                         return TRUE;
618                 }
619         }
620
621         return FALSE;
622 }
623
624
625 /**
626  * lgl_db_is_paper_id_other:
627  * @id: paper id to test
628  *
629  * Determine if given paper id is the special id "Other."
630  *
631  * Returns: TRUE if id is "Other", otherwise FALSE.
632  *
633  */
634 gboolean
635 lgl_db_is_paper_id_other (const gchar *id)
636 {
637         if (id == NULL)
638         {
639                 return FALSE;
640         }
641
642         return (ASCII_EQUAL (id, "Other"));
643 }
644
645
646 static GList *
647 read_papers (void)
648 {
649         gchar *data_dir;
650         GList *papers = NULL;
651
652         data_dir = SYSTEM_CONFIG_DIR;
653         papers = read_paper_files_from_dir (papers, data_dir);
654         g_free (data_dir);
655
656         data_dir = USER_CONFIG_DIR;
657         papers = read_paper_files_from_dir (papers, data_dir);
658         g_free (data_dir);
659
660         if (papers == NULL) {
661                 g_critical (_("Unable to locate paper size definitions.  Libglabels may not be installed correctly!"));
662         }
663
664         return papers;
665 }
666
667
668 static GList *
669 read_paper_files_from_dir (GList       *papers,
670                            const gchar *dirname)
671 {
672         GDir        *dp;
673         const gchar *filename, *extension;
674         gchar       *full_filename = NULL;
675         GError      *gerror = NULL;
676         GList       *new_papers = NULL;
677
678         if (dirname == NULL) {
679                 return papers;
680         }
681
682         if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
683                 return papers;
684         }
685
686         dp = g_dir_open (dirname, 0, &gerror);
687         if (gerror != NULL) {
688                 g_message ("cannot open data directory: %s", gerror->message );
689                 return papers;
690         }
691
692         while ((filename = g_dir_read_name (dp)) != NULL) {
693
694                 extension = strrchr (filename, '.');
695
696                 if (extension != NULL) {
697
698                         if ( ASCII_EQUAL (filename, "paper-sizes.xml") )
699                         {
700
701                                 full_filename =
702                                     g_build_filename (dirname, filename, NULL);
703                                 new_papers =
704                                     lgl_xml_paper_read_papers_from_file (full_filename);
705                                 g_free (full_filename);
706
707                                 papers = g_list_concat (papers, new_papers);
708                                 new_papers = NULL;
709
710                         }
711
712                 }
713
714         }
715
716         g_dir_close (dp);
717
718         return papers;
719 }
720
721
722 /**
723  * lgl_db_print_known_papers:
724  *
725  * For debugging purposes: print a list of all paper definitions known to
726  * libglabels.
727  *
728  */
729 void
730 lgl_db_print_known_papers (void)
731 {
732         GList       *p;
733         lglPaper    *paper;
734
735         if (!model) {
736                 lgl_db_init ();
737         }
738
739         g_print ("%s():\n", __FUNCTION__);
740         for (p = model->papers; p != NULL; p = p->next) {
741                 paper = (lglPaper *) p->data;
742
743                 g_print ("PAPER id=\"%s\", name=\"%s\", width=%gpts, height=%gpts\n",
744                          paper->id, paper->name, paper->width, paper->height);
745
746         }
747         g_print ("\n");
748
749 }
750
751
752 /*===========================================*/
753 /* Category db functions.                    */
754 /*===========================================*/
755
756 /**
757  * lgl_db_get_category_id_list:
758  *
759  * Get a list of all category ids known to libglabels.
760  *
761  * Returns: a list of category ids.
762  *
763  */
764 GList *
765 lgl_db_get_category_id_list (void)
766 {
767         GList           *ids = NULL;
768         GList           *p;
769         lglCategory     *category;
770
771         if (!model)
772         {
773                 lgl_db_init ();
774         }
775
776         for ( p=model->categories; p != NULL; p=p->next )
777         {
778                 category = (lglCategory *)p->data;
779                 ids = g_list_append (ids, g_strdup (category->id));
780         }
781
782         return ids;
783 }
784
785
786 /**
787  * lgl_db_free_category_id_list:
788  * @ids: List of id strings to be freed.
789  *
790  * Free up all storage associated with an id list obtained with
791  * lgl_db_get_category_id_list().
792  *
793  */
794 void
795 lgl_db_free_category_id_list (GList *ids)
796 {
797         GList *p;
798
799         for (p = ids; p != NULL; p = p->next)
800         {
801                 g_free (p->data);
802                 p->data = NULL;
803         }
804
805         g_list_free (ids);
806 }
807
808
809 /**
810  * lgl_db_get_category_name_list:
811  *
812  * Get a list of all localized category names known to libglabels.
813  *
814  * Returns: a list of localized category names.
815  *
816  */
817 GList *
818 lgl_db_get_category_name_list (void)
819 {
820         GList           *names = NULL;
821         GList           *p;
822         lglCategory     *category;
823
824         if (!model)
825         {
826                 lgl_db_init ();
827         }
828
829         for ( p=model->categories; p != NULL; p=p->next )
830         {
831                 category = (lglCategory *)p->data;
832                 names = g_list_append (names, g_strdup (category->name));
833         }
834
835         return names;
836 }
837
838
839 /**
840  * lgl_db_free_category_name_list:
841  * @names: List of localized category name strings to be freed.
842  *
843  * Free up all storage associated with a name list obtained with
844  * lgl_db_get_category_name_list().
845  *
846  */
847 void
848 lgl_db_free_category_name_list (GList *names)
849 {
850         GList *p;
851
852         for (p = names; p != NULL; p = p->next)
853         {
854                 g_free (p->data);
855                 p->data = NULL;
856         }
857
858         g_list_free (names);
859 }
860
861
862 /**
863  * lgl_db_lookup_category_from_name:
864  * @name: localized category name string
865  *
866  * Lookup category definition from localized category name string.
867  *
868  * Returns: pointer to a newly allocated #lglCategory structure.
869  *
870  */
871 lglCategory *
872 lgl_db_lookup_category_from_name (const gchar *name)
873 {
874         GList       *p;
875         lglCategory *category;
876
877         if (!model)
878         {
879                 lgl_db_init ();
880         }
881
882         if (name == NULL)
883         {
884                 /* If no name, return first category as a default */
885                 return lgl_category_dup ((lglCategory *) model->categories->data);
886         }
887
888         for (p = model->categories; p != NULL; p = p->next)
889         {
890                 category = (lglCategory *) p->data;
891                 if (UTF8_EQUAL (category->name, name))
892                 {
893                         return lgl_category_dup (category);
894                 }
895         }
896
897         return NULL;
898 }
899
900
901 /**
902  * lgl_db_lookup_category_from_id:
903  * @id: category id string
904  *
905  * Lookup category definition from id string.
906  *
907  * Returns: pointer to a newly allocated #lglCategory structure.
908  *
909  */
910 lglCategory *
911 lgl_db_lookup_category_from_id (const gchar *id)
912 {
913         GList       *p;
914         lglCategory *category;
915
916         if (!model)
917         {
918                 lgl_db_init ();
919         }
920
921         if (id == NULL)
922         {
923                 /* If no id, return first category as a default */
924                 return lgl_category_dup ((lglCategory *) model->categories->data);
925         }
926
927         for (p = model->categories; p != NULL; p = p->next)
928         {
929                 category = (lglCategory *) p->data;
930                 if (ASCII_EQUAL (category->id, id))
931                 {
932                         return lgl_category_dup (category);
933                 }
934         }
935
936         return NULL;
937 }
938
939
940 /**
941  * lgl_db_lookup_category_id_from_name:
942  * @name: localized category name stringp
943  *
944  * Lookup category name string from localized category name string.
945  *
946  * Returns: pointer to a newly allocated id string.
947  *
948  */
949 gchar *
950 lgl_db_lookup_category_id_from_name (const gchar *name)
951 {
952         lglCategory *category = NULL;
953         gchar       *id = NULL;
954
955         if (name != NULL)
956         {
957                 category = lgl_db_lookup_category_from_name (name);
958                 if ( category != NULL )
959                 {
960                         id = g_strdup (category->id);
961                         lgl_category_free (category);
962                         category = NULL;
963                 }
964         }
965
966         return id;
967 }
968
969
970 /**
971  * lgl_db_lookup_category_name_from_id:
972  * @id: category id string
973  *
974  * Lookup localized category name string from category id string.
975  *
976  * Returns: pointer to a newly allocated localized category name string.
977  *
978  */
979 gchar *
980 lgl_db_lookup_category_name_from_id (const gchar         *id)
981 {
982         lglCategory *category = NULL;
983         gchar       *name = NULL;
984
985         if (id != NULL)
986         {
987                 category = lgl_db_lookup_category_from_id (id);
988                 if ( category != NULL )
989                 {
990                         name = g_strdup (category->name);
991                         lgl_category_free (category);
992                         category = NULL;
993                 }
994         }
995
996         return name;
997 }
998
999
1000 /**
1001  * lgl_db_is_category_id_known:
1002  * @id: category id to test
1003  *
1004  * Determine if given category id is known to libglabels.
1005  *
1006  * Returns: TRUE if id is known, otherwise FALSE.
1007  *
1008  */
1009 gboolean
1010 lgl_db_is_category_id_known (const gchar *id)
1011 {
1012         GList       *p;
1013         lglCategory *category;
1014
1015         if (!model)
1016         {
1017                 lgl_db_init ();
1018         }
1019
1020         if (id == NULL)
1021         {
1022                 return FALSE;
1023         }
1024
1025         for (p = model->categories; p != NULL; p = p->next)
1026         {
1027                 category = (lglCategory *) p->data;
1028                 if (ASCII_EQUAL (category->id, id))
1029                 {
1030                         return TRUE;
1031                 }
1032         }
1033
1034         return FALSE;
1035 }
1036
1037
1038 static GList *
1039 read_categories (void)
1040 {
1041         gchar *data_dir;
1042         GList *categories = NULL;
1043
1044         data_dir = SYSTEM_CONFIG_DIR;
1045         categories = read_category_files_from_dir (categories, data_dir);
1046         g_free (data_dir);
1047
1048         data_dir = USER_CONFIG_DIR;
1049         categories = read_category_files_from_dir (categories, data_dir);
1050         g_free (data_dir);
1051
1052         if (categories == NULL) {
1053                 g_critical (_("Unable to locate category definitions.  Libglabels may not be installed correctly!"));
1054         }
1055
1056         return categories;
1057 }
1058
1059
1060 static GList *
1061 read_category_files_from_dir (GList       *categories,
1062                               const gchar *dirname)
1063 {
1064         GDir        *dp;
1065         const gchar *filename, *extension;
1066         gchar       *full_filename = NULL;
1067         GError      *gerror = NULL;
1068         GList       *new_categories = NULL;
1069
1070         if (dirname == NULL) {
1071                 return categories;
1072         }
1073
1074         if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
1075                 return categories;
1076         }
1077
1078         dp = g_dir_open (dirname, 0, &gerror);
1079         if (gerror != NULL) {
1080                 g_message ("cannot open data directory: %s", gerror->message );
1081                 return categories;
1082         }
1083
1084         while ((filename = g_dir_read_name (dp)) != NULL) {
1085
1086                 extension = strrchr (filename, '.');
1087
1088                 if (extension != NULL) {
1089
1090                         if ( ASCII_EQUAL (filename, "categories.xml") )
1091                         {
1092
1093                                 full_filename =
1094                                     g_build_filename (dirname, filename, NULL);
1095                                 new_categories =
1096                                     lgl_xml_category_read_categories_from_file (full_filename);
1097                                 g_free (full_filename);
1098
1099                                 categories = g_list_concat (categories, new_categories);
1100                                 new_categories = NULL;
1101
1102                         }
1103
1104                 }
1105
1106         }
1107
1108         g_dir_close (dp);
1109
1110         return categories;
1111 }
1112
1113
1114 /**
1115  * lgl_db_print_known_categories:
1116  *
1117  * For debugging purposes: print a list of all category definitions known to
1118  * libglabels.
1119  *
1120  */
1121 void
1122 lgl_db_print_known_categories (void)
1123 {
1124         GList       *p;
1125         lglCategory *category;
1126
1127         if (!model) {
1128                 lgl_db_init ();
1129         }
1130
1131         g_print ("%s():\n", __FUNCTION__);
1132         for (p = model->categories; p != NULL; p = p->next) {
1133                 category = (lglCategory *) p->data;
1134
1135                 g_print ("CATEGORY id=\"%s\", name=\"%s\"\n", category->id, category->name);
1136
1137         }
1138         g_print ("\n");
1139
1140 }
1141
1142
1143 /*===========================================*/
1144 /* Vendor db functions.                       */
1145 /*===========================================*/
1146
1147 /**
1148  * lgl_db_get_vendor_name_list:
1149  *
1150  * Get a list of all localized vendor names known to libglabels.
1151  *
1152  * Returns: a list of localized vendor names.
1153  *
1154  */
1155 GList *
1156 lgl_db_get_vendor_name_list (void)
1157 {
1158         GList           *names = NULL;
1159         GList           *p;
1160         lglVendor       *vendor;
1161
1162         if (!model)
1163         {
1164                 lgl_db_init ();
1165         }
1166
1167         for ( p=model->vendors; p != NULL; p=p->next )
1168         {
1169                 vendor = (lglVendor *)p->data;
1170                 names = g_list_append (names, g_strdup (vendor->name));
1171         }
1172
1173         return names;
1174 }
1175
1176
1177 /**
1178  * lgl_db_free_vendor_name_list:
1179  * @names: List of localized vendor name strings to be freed.
1180  *
1181  * Free up all storage associated with a name list obtained with
1182  * lgl_db_get_vendor_name_list().
1183  *
1184  */
1185 void
1186 lgl_db_free_vendor_name_list (GList *names)
1187 {
1188         GList *p;
1189
1190         for (p = names; p != NULL; p = p->next)
1191         {
1192                 g_free (p->data);
1193                 p->data = NULL;
1194         }
1195
1196         g_list_free (names);
1197 }
1198
1199
1200 /**
1201  * lgl_db_lookup_vendor_from_name:
1202  * @name: localized vendor name string
1203  *
1204  * Lookup vendor definition from localized vendor name string.
1205  *
1206  * Returns: pointer to a newly allocated #lglVendor structure.
1207  *
1208  */
1209 lglVendor *
1210 lgl_db_lookup_vendor_from_name (const gchar *name)
1211 {
1212         GList       *p;
1213         lglVendor   *vendor;
1214
1215         if (!model)
1216         {
1217                 lgl_db_init ();
1218         }
1219
1220         if (name == NULL)
1221         {
1222                 /* If no name, return first vendor as a default */
1223                 return lgl_vendor_dup ((lglVendor *) model->vendors->data);
1224         }
1225
1226         for (p = model->vendors; p != NULL; p = p->next)
1227         {
1228                 vendor = (lglVendor *) p->data;
1229                 if (UTF8_EQUAL (vendor->name, name))
1230                 {
1231                         return lgl_vendor_dup (vendor);
1232                 }
1233         }
1234
1235         return NULL;
1236 }
1237
1238
1239 /**
1240  * lgl_db_is_vendor_name_known:
1241  * @name: vendor name to test
1242  *
1243  * Determine if given vendor id is known to libglabels.
1244  *
1245  * Returns: TRUE if id is known, otherwise FALSE.
1246  *
1247  */
1248 gboolean
1249 lgl_db_is_vendor_name_known (const gchar *name)
1250 {
1251         GList       *p;
1252         lglVendor   *vendor;
1253
1254         if (!model)
1255         {
1256                 lgl_db_init ();
1257         }
1258
1259         if (name == NULL)
1260         {
1261                 return FALSE;
1262         }
1263
1264         for (p = model->vendors; p != NULL; p = p->next)
1265         {
1266                 vendor = (lglVendor *) p->data;
1267                 if (UTF8_EQUAL (vendor->name, name))
1268                 {
1269                         return TRUE;
1270                 }
1271         }
1272
1273         return FALSE;
1274 }
1275
1276
1277 static GList *
1278 read_vendors (void)
1279 {
1280         gchar *data_dir;
1281         GList *vendors = NULL;
1282
1283         data_dir = SYSTEM_CONFIG_DIR;
1284         vendors = read_vendor_files_from_dir (vendors, data_dir);
1285         g_free (data_dir);
1286
1287         data_dir = USER_CONFIG_DIR;
1288         vendors = read_vendor_files_from_dir (vendors, data_dir);
1289         g_free (data_dir);
1290
1291         return vendors;
1292 }
1293
1294
1295 static GList *
1296 read_vendor_files_from_dir (GList      *vendors,
1297                            const gchar *dirname)
1298 {
1299         GDir        *dp;
1300         const gchar *filename, *extension;
1301         gchar       *full_filename = NULL;
1302         GError      *gerror = NULL;
1303         GList       *new_vendors = NULL;
1304
1305         if (dirname == NULL) {
1306                 return vendors;
1307         }
1308
1309         if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
1310                 return vendors;
1311         }
1312
1313         dp = g_dir_open (dirname, 0, &gerror);
1314         if (gerror != NULL) {
1315                 g_message ("cannot open data directory: %s", gerror->message );
1316                 return vendors;
1317         }
1318
1319         while ((filename = g_dir_read_name (dp)) != NULL) {
1320
1321                 extension = strrchr (filename, '.');
1322
1323                 if (extension != NULL) {
1324
1325                         if ( ASCII_EQUAL (filename, "vendors.xml") )
1326                         {
1327
1328                                 full_filename =
1329                                     g_build_filename (dirname, filename, NULL);
1330                                 new_vendors =
1331                                     lgl_xml_vendor_read_vendors_from_file (full_filename);
1332                                 g_free (full_filename);
1333
1334                                 vendors = g_list_concat (vendors, new_vendors);
1335                                 new_vendors = NULL;
1336
1337                         }
1338
1339                 }
1340
1341         }
1342
1343         g_dir_close (dp);
1344
1345         return vendors;
1346 }
1347
1348
1349 /**
1350  * lgl_db_print_known_vendors:
1351  *
1352  * For debugging purposes: print a list of all vendor definitions known to
1353  * libglabels.
1354  *
1355  */
1356 void
1357 lgl_db_print_known_vendors (void)
1358 {
1359         GList       *p;
1360         lglVendor   *vendor;
1361
1362         if (!model) {
1363                 lgl_db_init ();
1364         }
1365
1366         g_print ("%s():\n", __FUNCTION__);
1367         for (p = model->vendors; p != NULL; p = p->next) {
1368                 vendor = (lglVendor *) p->data;
1369
1370                 g_print ("VENDOR name=\"%s\", url=\"%s\"\n",
1371                          vendor->name, vendor->url);
1372
1373         }
1374         g_print ("\n");
1375
1376 }
1377
1378
1379 /*===========================================*/
1380 /* Brand db functions.                       */
1381 /*===========================================*/
1382
1383 /**
1384  * lgl_db_get_brand_list:
1385  * @paper_id: If non NULL, limit results to given page size.
1386  * @category_id: If non NULL, limit results to given template category.
1387  *
1388  * Get a list of all valid brands of templates in the template database.
1389  * Results can be filtered by page size and/or template category.  A list of valid page
1390  * sizes can be obtained using lgl_db_get_paper_id_list().  A list of valid template
1391  * categories can be obtained using lgl_db_get_category_id_list().
1392  *
1393  * Returns: a list of brands
1394  */
1395 GList *
1396 lgl_db_get_brand_list (const gchar *paper_id,
1397                        const gchar *category_id)
1398 {
1399         GList            *p_tmplt;
1400         lglTemplate      *template;
1401         GList            *brands = NULL;
1402
1403         if (!model)
1404         {
1405                 lgl_db_init ();
1406         }
1407
1408         for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1409         {
1410                 template = (lglTemplate *) p_tmplt->data;
1411                 if (lgl_template_does_page_size_match (template, paper_id) &&
1412                     lgl_template_does_category_match (template, category_id))
1413                 {
1414
1415                         if ( !g_list_find_custom (brands, template->brand,
1416                                                   (GCompareFunc)lgl_str_utf8_casecmp) )
1417                         {
1418                                 brands = g_list_insert_sorted (brands,
1419                                                                g_strdup (template->brand),
1420                                                                (GCompareFunc)lgl_str_utf8_casecmp);
1421                         }
1422                 }
1423         }
1424
1425         return brands;
1426 }
1427
1428
1429 /**
1430  * lgl_db_free_brand_list:
1431  * @brands: List of template brand strings to be freed.
1432  *
1433  * Free up all storage associated with a list of template names obtained with
1434  * lgl_db_get_brand_list().
1435  *
1436  */
1437 void
1438 lgl_db_free_brand_list (GList *brands)
1439 {
1440         GList *p_brand;
1441
1442         for (p_brand = brands; p_brand != NULL; p_brand = p_brand->next)
1443         {
1444                 g_free (p_brand->data);
1445                 p_brand->data = NULL;
1446         }
1447
1448         g_list_free (brands);
1449 }
1450
1451
1452 /*===========================================*/
1453 /* Template db functions.                    */
1454 /*===========================================*/
1455
1456 void
1457 _lgl_db_register_template_internal (const lglTemplate   *template)
1458 {
1459         lglTemplate *template_copy;
1460
1461         if (!lgl_db_does_template_exist (template->brand, template->part))
1462         {
1463                 template_copy = lgl_template_dup (template);
1464                 model->templates = g_list_append (model->templates, template_copy);
1465                 add_to_template_cache (template_copy);
1466         }
1467         else
1468         {
1469                 g_message ("Duplicate template: %s %s.", template->brand, template->part);
1470         }
1471 }
1472
1473
1474 /**
1475  * lgl_db_register_template:
1476  * @template:  Pointer to a template structure to add to database.
1477  *
1478  * Register a template.  This function adds a template to the template database.
1479  * The template will be stored in an individual XML file in the user template directory.
1480  *
1481  * Returns: Status of registration attempt (#lglDbRegStatus)
1482  */
1483 lglDbRegStatus
1484 lgl_db_register_template (const lglTemplate *template)
1485 {
1486         lglTemplate *template_copy;
1487         gchar       *dir, *filename, *abs_filename;
1488         gint         bytes_written;
1489
1490         if (!model)
1491         {
1492                 lgl_db_init ();
1493         }
1494
1495         if (lgl_db_does_template_exist (template->brand, template->part))
1496         {
1497                 return LGL_DB_REG_BRAND_PART_EXISTS;
1498         }
1499
1500         if (lgl_db_is_paper_id_known (template->paper_id))
1501         {
1502                 dir = USER_CONFIG_DIR;
1503                 g_mkdir_with_parents (dir, 0775); /* Try to make sure directory exists. */
1504                 filename = g_strdup_printf ("%s_%s.template", template->brand, template->part);
1505                 abs_filename = g_build_filename (dir, filename, NULL);
1506                 bytes_written = lgl_xml_template_write_template_to_file (template, abs_filename);
1507                 g_free (dir);
1508                 g_free (filename);
1509                 g_free (abs_filename);
1510
1511                 if (bytes_written > 0)
1512                 {
1513                         template_copy = lgl_template_dup (template);
1514                         lgl_template_add_category (template_copy, "user-defined");
1515                         model->templates = g_list_append (model->templates, template_copy);
1516                         add_to_template_cache (template_copy);
1517                         g_signal_emit (G_OBJECT (model), signals[CHANGED], 0);
1518                         return LGL_DB_REG_OK;
1519                 }
1520                 else
1521                 {
1522                         return LGL_DB_REG_FILE_WRITE_ERROR;
1523                 }
1524         }
1525         else
1526         {
1527                 g_message ("Cannot register new template with unknown page size.");
1528                 return LGL_DB_REG_BAD_PAPER_ID;
1529         }
1530
1531 }
1532
1533
1534 /**
1535  * lgl_db_delete_template_by_name:
1536  * @name:  Name of template to be deleted.
1537  *
1538  * Delete a user defined template.  This function deletes a template from
1539  * the template database. The individual XML file in the user template
1540  * directory will also be removed.
1541  *
1542  * Returns: Status of registration attempt (#lglDbDeleteStatus)
1543  */
1544 lglDbDeleteStatus
1545 lgl_db_delete_template_by_name (const gchar *name)
1546 {
1547         lglTemplate *template, *template1;
1548         gchar       *dir, *filename, *abs_filename;
1549         GList       *p;
1550
1551         if (!model)
1552         {
1553                 lgl_db_init ();
1554         }
1555
1556         if (!lgl_db_does_template_name_exist (name))
1557         {
1558                 return LGL_DB_DELETE_DOES_NOT_EXIST;
1559         }
1560
1561         template = lgl_db_lookup_template_from_name (name);
1562         if ( lgl_template_does_category_match (template, "user-defined") )
1563         {
1564                 dir = USER_CONFIG_DIR;
1565                 filename = g_strdup_printf ("%s_%s.template", template->brand, template->part);
1566                 abs_filename = g_build_filename (dir, filename, NULL);
1567
1568                 if (!g_file_test (abs_filename, G_FILE_TEST_EXISTS))
1569                 {
1570                         g_message ("File \"%s\" does not exist.  Cannot delete it.");
1571                         return LGL_DB_DELETE_DOES_NOT_EXIST;
1572                 }
1573
1574                 g_unlink (abs_filename);
1575
1576                 g_free (dir);
1577                 g_free (filename);
1578                 g_free (abs_filename);
1579
1580                 for ( p=model->templates; p != NULL; p=p->next )
1581                 {
1582                         template1 = (lglTemplate *)p->data;
1583
1584                         if ( lgl_template_do_templates_match (template, template1) )
1585                         {
1586                                 model->templates = g_list_delete_link (model->templates, p);
1587                                 g_hash_table_remove (model->template_cache, name);
1588                                 break;
1589                         }
1590                 }
1591
1592                 lgl_template_free (template);
1593
1594                 g_signal_emit (G_OBJECT (model), signals[CHANGED], 0);
1595                 return LGL_DB_DELETE_OK;
1596         }
1597         else
1598         {
1599                 return LGL_DB_DELETE_NOT_USER_DEFINED;
1600         }
1601
1602 }
1603
1604
1605 /**
1606  * lgl_db_delete_template_by_brand_part:
1607  * @brand:  Brand name or vendor of template to be deleted.
1608  * @part:   Part name or number of template to be deleted.
1609  *
1610  * Delete a user defined template.  This function deletes a template from
1611  * the template database. The individual XML file in the user template
1612  * directory will also be removed.
1613  *
1614  * Returns: Status of registration attempt (#lglDbDeleteStatus)
1615  */
1616 lglDbDeleteStatus
1617 lgl_db_delete_template_by_brand_part (const gchar  *brand,
1618                                       const gchar  *part)
1619 {
1620         gchar             *name;
1621         lglDbDeleteStatus  status;
1622
1623         name = g_strdup_printf ("%s %s", brand, part);
1624
1625         status = lgl_db_delete_template_by_name (name);
1626
1627         g_free (name);
1628
1629         return status;
1630 }
1631
1632
1633 /**
1634  * lgl_db_does_template_exist:
1635  * @brand: Brand name.
1636  * @part:  Part name/number.
1637  *
1638  * This function tests whether a template with the given brand and part name/number exists.
1639  *
1640  * Returns:  TRUE if such a template exists in the database.
1641  */
1642 gboolean
1643 lgl_db_does_template_exist (const gchar *brand,
1644                             const gchar *part)
1645 {
1646         GList            *p_tmplt;
1647         lglTemplate      *template;
1648
1649         if (!model)
1650         {
1651                 lgl_db_init ();
1652         }
1653
1654         if ((brand == NULL) || (part == NULL))
1655         {
1656                 return FALSE;
1657         }
1658
1659         for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1660         {
1661                 template = (lglTemplate *) p_tmplt->data;
1662
1663                 if ( UTF8_EQUAL (brand, template->brand) &&
1664                      UTF8_EQUAL (part, template->part) )
1665                 {
1666                         return TRUE;
1667                 }
1668         }
1669
1670         return FALSE;
1671 }
1672
1673
1674 /**
1675  * lgl_db_does_template_name_exist:
1676  * @name: name string
1677  *
1678  * This function test whether a template with the given name exists.
1679  *
1680  * Returns: TRUE if such a template exists in the database.
1681  *
1682  */
1683 gboolean
1684 lgl_db_does_template_name_exist (const gchar *name)
1685 {
1686         GList            *p_tmplt;
1687         lglTemplate      *template;
1688         gchar            *candidate_name;
1689
1690         if (!model)
1691         {
1692                 lgl_db_init ();
1693         }
1694
1695         if (name == NULL)
1696         {
1697                 return FALSE;
1698         }
1699
1700         for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1701         {
1702                 template = (lglTemplate *) p_tmplt->data;
1703                 candidate_name = g_strdup_printf ("%s %s", template->brand, template->part);
1704
1705                 if ( UTF8_EQUAL (candidate_name, name) )
1706                 {
1707                         g_free (candidate_name);
1708                         return TRUE;
1709                 }
1710                 g_free (candidate_name);
1711         }
1712
1713         return FALSE;
1714 }
1715
1716
1717 /**
1718  * lgl_db_get_template_name_list_all:
1719  * @brand:     If non NULL, limit results to given brand
1720  * @paper_id: If non NULL, limit results to given page size.
1721  * @category_id: If non NULL, limit results to given template category.
1722  *
1723  * Get a list of all valid names of templates in the template database.
1724  * Results can be filtered by page size and/or template category.  A list of valid page
1725  * sizes can be obtained using lgl_db_get_paper_id_list().  A list of valid template
1726  * categories can be obtained using lgl_db_get_category_id_list().
1727  *
1728  * Returns: a list of template names.
1729  */
1730 GList *
1731 lgl_db_get_template_name_list_all (const gchar *brand,
1732                                    const gchar *paper_id,
1733                                    const gchar *category_id)
1734 {
1735         GList            *p_tmplt;
1736         lglTemplate      *template;
1737         gchar            *name;
1738         GList            *names = NULL;
1739
1740         if (!model)
1741         {
1742                 lgl_db_init ();
1743         }
1744
1745         for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1746         {
1747                 template = (lglTemplate *) p_tmplt->data;
1748                 if (lgl_template_does_brand_match (template, brand) &&
1749                     lgl_template_does_page_size_match (template, paper_id) &&
1750                     lgl_template_does_category_match (template, category_id))
1751                 {
1752                         name = g_strdup_printf ("%s %s", template->brand, template->part);
1753                         names = g_list_insert_sorted (names, name, (GCompareFunc)lgl_str_part_name_cmp);
1754                 }
1755         }
1756
1757         return names;
1758 }
1759
1760
1761 /**
1762  * lgl_db_get_similar_template_name_list:
1763  * @name:     Name of template under test.
1764  *
1765  * Get a list of all valid names of templates in the template database that
1766  * have the same size and layout characteristics as the given template.
1767  *
1768  * Returns: a list of template names.
1769  */
1770 GList *
1771 lgl_db_get_similar_template_name_list (const gchar  *name)
1772 {
1773         GList            *p_tmplt;
1774         lglTemplate      *template1;
1775         lglTemplate      *template2;
1776         gchar            *name2;
1777         GList            *names = NULL;
1778
1779         if (!model)
1780         {
1781                 lgl_db_init ();
1782         }
1783
1784         if ( !name )
1785         {
1786                 return NULL;
1787         }
1788
1789         template1 = lgl_db_lookup_template_from_name (name);
1790         if ( !template1 )
1791         {
1792                 return NULL;
1793         }
1794
1795         for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1796         {
1797                 template2 = (lglTemplate *) p_tmplt->data;
1798
1799                 if ( lgl_template_are_templates_identical (template1, template2) )
1800                 {
1801
1802                         name2 = g_strdup_printf ("%s %s", template2->brand, template2->part);
1803                         if ( !UTF8_EQUAL (name2, name) )
1804                         {
1805                                 names = g_list_insert_sorted (names, name2,
1806                                                               (GCompareFunc)lgl_str_part_name_cmp);
1807                         }
1808
1809                 }
1810         }
1811
1812         return names;
1813 }
1814
1815
1816 /**
1817  * lgl_db_free_template_name_list:
1818  * @names: List of template name strings to be freed.
1819  *
1820  * Free up all storage associated with a list of template names obtained with
1821  * lgl_db_get_template_name_list_all() or lgl_db_get_template_name_list_unique().
1822  *
1823  */
1824 void
1825 lgl_db_free_template_name_list (GList *names)
1826 {
1827         GList *p_name;
1828
1829         for (p_name = names; p_name != NULL; p_name = p_name->next)
1830         {
1831                 g_free (p_name->data);
1832                 p_name->data = NULL;
1833         }
1834
1835         g_list_free (names);
1836 }
1837
1838
1839 /**
1840  * lgl_db_lookup_template_from_name:
1841  * @name: name string
1842  *
1843  * Lookup template in template database from name string.
1844  *
1845  * Returns: pointer to a newly allocated #lglTemplate structure.
1846  *
1847  */
1848 lglTemplate *
1849 lgl_db_lookup_template_from_name (const gchar *name)
1850 {
1851         lglTemplate      *template;
1852         lglTemplate      *new_template;
1853
1854         if (!model)
1855         {
1856                 lgl_db_init ();
1857         }
1858
1859         if (name == NULL)
1860         {
1861                 /* If no name, return first template as a default */
1862                 return lgl_template_dup ((lglTemplate *) model->templates->data);
1863         }
1864
1865         template = g_hash_table_lookup (model->template_cache, name);
1866
1867         if (template)
1868         {
1869                 new_template = lgl_template_dup (template);
1870                 return new_template;
1871         }
1872
1873         /* No matching template has been found so return the first template */
1874         return lgl_template_dup ((lglTemplate *) model->templates->data);
1875 }
1876
1877
1878 /**
1879  * lgl_db_lookup_template_from_brand_part:
1880  * @brand: brand name string
1881  * @part:  part name string
1882  *
1883  * Lookup template in template database from brand and part strings.
1884  *
1885  * Returns: pointer to a newly allocated #lglTemplate structure.
1886  *
1887  */
1888 lglTemplate *
1889 lgl_db_lookup_template_from_brand_part(const gchar *brand,
1890                                        const gchar *part)
1891 {
1892         gchar            *name;
1893         lglTemplate      *template;
1894         lglTemplate      *new_template;
1895
1896         if (!model)
1897         {
1898                 lgl_db_init ();
1899         }
1900
1901         if ((brand == NULL) || (part == NULL))
1902         {
1903                 /* If no name, return first template as a default */
1904                 return lgl_template_dup ((lglTemplate *) model->templates->data);
1905         }
1906
1907         name = g_strdup_printf ("%s %s", brand, part);
1908         template = g_hash_table_lookup (model->template_cache, name);
1909
1910         if (template)
1911         {
1912                 new_template = lgl_template_dup (template);
1913                 return new_template;
1914         }
1915
1916         /* No matching template has been found so return the first template */
1917         g_free (name);
1918         return lgl_template_dup ((lglTemplate *) model->templates->data);
1919 }
1920
1921
1922 static void
1923 add_to_template_cache (lglTemplate *template)
1924 {
1925         gchar            *name;
1926
1927         name = g_strdup_printf ("%s %s", template->brand, template->part);
1928
1929         g_hash_table_insert (model->template_cache, name, template);
1930 }
1931
1932
1933 void
1934 read_templates (void)
1935 {
1936         gchar       *data_dir;
1937         GList       *p;
1938         lglTemplate *template;
1939
1940         /*
1941          * User defined templates.  Add to user-defined category.
1942          */
1943         data_dir = USER_CONFIG_DIR;
1944         read_template_files_from_dir (data_dir);
1945         g_free (data_dir);
1946         for ( p=model->templates; p != NULL; p=p->next )
1947         {
1948                 template = (lglTemplate *)p->data;
1949                 lgl_template_add_category (template, "user-defined");
1950         }
1951
1952         /*
1953          * Alternate user defined templates.  (Used for manually created templates).
1954          */
1955         data_dir = ALT_USER_CONFIG_DIR;
1956         read_template_files_from_dir (data_dir);
1957         g_free (data_dir);
1958
1959         /*
1960          * System templates.
1961          */
1962         data_dir = SYSTEM_CONFIG_DIR;
1963         read_template_files_from_dir (data_dir);
1964         g_free (data_dir);
1965
1966         if (model->templates == NULL)
1967         {
1968                 g_critical (_("Unable to locate any template files.  Libglabels may not be installed correctly!"));
1969         }
1970 }
1971
1972
1973 void
1974 read_template_files_from_dir (const gchar *dirname)
1975 {
1976         GDir        *dp;
1977         const gchar *filename, *extension, *extension2;
1978         gchar       *full_filename = NULL;
1979         GError      *gerror = NULL;
1980
1981         if (dirname == NULL)
1982                 return;
1983
1984         if (!g_file_test (dirname, G_FILE_TEST_EXISTS))
1985         {
1986                 return;
1987         }
1988
1989         dp = g_dir_open (dirname, 0, &gerror);
1990         if (gerror != NULL)
1991         {
1992                 g_message ("cannot open data directory: %s", gerror->message );
1993                 return;
1994         }
1995
1996         while ((filename = g_dir_read_name (dp)) != NULL)
1997         {
1998
1999                 extension = strrchr (filename, '.');
2000                 extension2 = strrchr (filename, '-');
2001
2002                 if ( (extension && ASCII_EQUAL (extension, ".template")) ||
2003                      (extension2 && ASCII_EQUAL (extension2, "-templates.xml")) )
2004                 {
2005
2006                         full_filename = g_build_filename (dirname, filename, NULL);
2007                         lgl_xml_template_read_templates_from_file (full_filename);
2008                         g_free (full_filename);
2009                 }
2010
2011         }
2012
2013         g_dir_close (dp);
2014 }
2015
2016
2017 static lglTemplate *
2018 template_full_page (const gchar *paper_id)
2019 {
2020         lglPaper              *paper = NULL;
2021         lglTemplate           *template = NULL;
2022         lglTemplateFrame      *frame = NULL;
2023         gchar                 *part;
2024         gchar                 *desc;
2025
2026         g_return_val_if_fail (paper_id, NULL);
2027
2028         paper = lgl_db_lookup_paper_from_id (paper_id);
2029         if ( paper == NULL )
2030         {
2031                 return NULL;
2032         }
2033
2034         part = g_strdup_printf ("%s-Full-Page", paper->id);
2035         desc = g_strdup_printf (_("%s full page label"), paper->name);
2036
2037         template = lgl_template_new ("Generic", part, desc,
2038                                      paper_id, paper->width, paper->height);
2039
2040
2041         frame = lgl_template_frame_rect_new ("0",
2042                                              paper->width,
2043                                              paper->height,
2044                                              0.0,
2045                                              0.0,
2046                                              0.0);
2047         lgl_template_add_frame (template, frame);
2048
2049         lgl_template_frame_add_layout (frame, lgl_template_layout_new (1, 1, 0., 0., 0., 0.));
2050
2051         lgl_template_frame_add_markup (frame, lgl_template_markup_margin_new (9.0));
2052
2053         g_free (desc);
2054         desc = NULL;
2055         lgl_paper_free (paper);
2056         paper = NULL;
2057
2058         return template;
2059 }
2060
2061
2062 /**
2063  * lgl_db_print_known_templates:
2064  *
2065  * Print all known templates (for debugging purposes).
2066  *
2067  */
2068 void
2069 lgl_db_print_known_templates (void)
2070 {
2071         GList       *p;
2072         lglTemplate *template;
2073
2074         if (!model)
2075         {
2076                 lgl_db_init ();
2077         }
2078
2079         g_print ("%s():\n", __FUNCTION__);
2080         for (p=model->templates; p!=NULL; p=p->next)
2081         {
2082                 template = (lglTemplate *)p->data;
2083
2084                 g_print("TEMPLATE brand=\"%s\", part=\"%s\", description=\"%s\"\n",
2085                         template->brand, template->part, template->description);
2086
2087         }
2088         g_print ("\n");
2089
2090 }
2091
2092
2093
2094
2095 /*
2096  * Local Variables:       -- emacs
2097  * mode: C                -- emacs
2098  * c-basic-offset: 8      -- emacs
2099  * tab-width: 8           -- emacs
2100  * indent-tabs-mode: nil  -- emacs
2101  * End:                   -- emacs
2102  */