--- /dev/null
+/*
+ * lgl-db.c
+ * Copyright (C) 2003-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "lgl-db.h"
+
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib-object.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "libglabels-private.h"
+
+#include "lgl-xml-paper.h"
+#include "lgl-xml-category.h"
+#include "lgl-xml-vendor.h"
+#include "lgl-xml-template.h"
+
+/*===========================================*/
+/* Private macros and constants. */
+/*===========================================*/
+
+/* Data system and user data directories. (must free w/ g_free()) */
+#define SYSTEM_CONFIG_DIR g_build_filename (LIBGLABELS_CONFIG_DIR, "templates", NULL)
+#define USER_CONFIG_DIR g_build_filename (g_get_user_config_dir (), "libglabels", "templates" , NULL)
+#define ALT_USER_CONFIG_DIR g_build_filename (g_get_home_dir (), ".glabels", NULL)
+
+
+/*===========================================*/
+/* Private types */
+/*===========================================*/
+
+#define TYPE_LGL_DB_MODEL (lgl_db_model_get_type ())
+#define LGL_DB_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_LGL_DB_MODEL, lglDbModel))
+#define LGL_DB_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_LGL_DB_MODEL, lglDbModelClass))
+#define IS_LGL_DB_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_LGL_DB_MODEL))
+#define IS_LGL_DB_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_LGL_DB_MODEL))
+#define LGL_DB_MODEL_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), TYPE_LGL_DB_MODEL, lglDbModelClass))
+
+
+typedef struct _lglDbModel lglDbModel;
+typedef struct _lglDbModelClass lglDbModelClass;
+
+
+struct _lglDbModel {
+ GObject parent;
+
+ GList *papers;
+ GList *categories;
+ GList *vendors;
+ GList *templates;
+
+ GHashTable *template_cache;
+};
+
+
+struct _lglDbModelClass {
+ GObjectClass parent_class;
+
+ /*
+ * Signals
+ */
+ void (*changed) (lglDbModel *this,
+ gpointer user_data);
+
+};
+
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+
+/*===========================================*/
+/* Private globals */
+/*===========================================*/
+
+static guint signals[LAST_SIGNAL] = {0};
+
+static lglDbModel *model = NULL;
+
+
+/*===========================================*/
+/* Local function prototypes */
+/*===========================================*/
+
+static void lgl_db_model_finalize (GObject *object);
+
+static void add_to_template_cache (lglTemplate *template);
+
+static GList *read_papers (void);
+static GList *read_paper_files_from_dir (GList *papers,
+ const gchar *dirname);
+
+static GList *read_categories (void);
+static GList *read_category_files_from_dir (GList *categories,
+ const gchar *dirname);
+
+static GList *read_vendors (void);
+static GList *read_vendor_files_from_dir (GList *vendors,
+ const gchar *dirname);
+
+static void read_templates (void);
+static void read_template_files_from_dir (const gchar *dirname);
+
+static lglTemplate *template_full_page (const gchar *page_size);
+
+
+/*****************************************************************************/
+/* Object infrastructure. */
+/*****************************************************************************/
+G_DEFINE_TYPE (lglDbModel, lgl_db_model, G_TYPE_OBJECT);
+
+
+/*****************************************************************************/
+/* Class Init Function. */
+/*****************************************************************************/
+static void
+lgl_db_model_class_init (lglDbModelClass *class)
+{
+ GObjectClass *gobject_class = (GObjectClass *) class;
+
+ lgl_db_model_parent_class = g_type_class_peek_parent (class);
+
+ gobject_class->finalize = lgl_db_model_finalize;
+
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (lglDbModelClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+
+/*****************************************************************************/
+/* Object Instance Init Function. */
+/*****************************************************************************/
+static void
+lgl_db_model_init (lglDbModel *this)
+{
+ this->template_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)lgl_template_free);
+}
+
+
+/*****************************************************************************/
+/* Finalize Method. */
+/*****************************************************************************/
+static void
+lgl_db_model_finalize (GObject *object)
+{
+ lglDbModel *this;
+ GList *p;
+
+ g_return_if_fail (object && IS_LGL_DB_MODEL (object));
+ this = LGL_DB_MODEL (object);
+
+ g_hash_table_unref (this->template_cache);
+
+ for (p = this->papers; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+ g_list_free (this->papers);
+
+ for (p = this->categories; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+ g_list_free (this->categories);
+
+ for (p = this->vendors; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+ g_list_free (this->vendors);
+
+ for (p = this->templates; p != NULL; p = p->next)
+ {
+ lgl_template_free ((lglTemplate *)p->data);
+ p->data = NULL;
+ }
+ g_list_free (this->templates);
+
+ G_OBJECT_CLASS (lgl_db_model_parent_class)->finalize (object);
+}
+
+
+/*****************************************************************************/
+/** New Object Generator. */
+/*****************************************************************************/
+lglDbModel *
+lgl_db_model_new (void)
+{
+ lglDbModel *this;
+
+ this = g_object_new (TYPE_LGL_DB_MODEL, NULL);
+
+ return this;
+}
+
+
+/*===========================================*/
+/* Module initialization */
+/*===========================================*/
+
+/**
+ * lgl_db_init:
+ *
+ * Initialize all libglabels subsystems. It is not necessary for an application to call
+ * lgl_db_init(), because libglabels will initialize on demand. An application programmer may
+ * choose to call lgl_db_init() at startup to minimize the impact of the first libglabels call
+ * on GUI response time.
+ *
+ * This function initializes its paper definitions, category definitions, vendor definitions,
+ * and its template database. It will search both system and user template directories to locate
+ * this data.
+ */
+void
+lgl_db_init (void)
+{
+ lglPaper *paper_other;
+ lglCategory *category_user_defined;
+ lglTemplate *template;
+ GList *page_sizes;
+ GList *p;
+
+ model = lgl_db_model_new ();
+
+ /*
+ * Paper definitions
+ */
+ model->papers = read_papers ();
+
+ /* Create and append an "Other" entry. */
+ /* Translators: "Other" here means other page size. Meaning a page size
+ * other than the standard ones that libglabels knows about such as
+ * "letter", "A4", etc. */
+ paper_other = lgl_paper_new ("Other", _("Other"), 0.0, 0.0, NULL);
+ model->papers = g_list_append (model->papers, paper_other);
+
+ /*
+ * Categories
+ */
+ model->categories = read_categories ();
+
+ /* Create and append a "User defined" entry. */
+ category_user_defined = lgl_category_new ("user-defined", _("User defined"));
+ model->categories = g_list_append (model->categories, category_user_defined);
+
+ /*
+ * Vendors
+ */
+ model->vendors = read_vendors ();
+
+ /*
+ * Templates
+ */
+ read_templates ();
+
+ /* Create and append generic full page templates. */
+ page_sizes = lgl_db_get_paper_id_list ();
+ for ( p=page_sizes; p != NULL; p=p->next )
+ {
+ if ( !lgl_db_is_paper_id_other (p->data) )
+ {
+ template = template_full_page (p->data);
+ _lgl_db_register_template_internal (template);
+ lgl_template_free (template);
+ }
+ }
+ lgl_db_free_paper_id_list (page_sizes);
+
+}
+
+
+/**
+ * lgl_db_notify_add:
+ * @func: Callback function to be called when database changes.
+ * @user_data: Passback user data to supply to callback function.
+ *
+ * Register a notification callback function to be called when the database changes.
+ *
+ * Returns: an ID for this notification registration.
+ */
+gulong
+lgl_db_notify_add (lglDbNotifyFunc func,
+ gpointer user_data)
+{
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ return g_signal_connect_swapped (G_OBJECT (model), "changed", G_CALLBACK (func), user_data);
+}
+
+
+/**
+ * lgl_db_notify_remove:
+ * @id: ID of notification registration to cancel (see lgl_db_notify_add()).
+ *
+ * Cancel a previous registration a notification callback function.
+ */
+void
+lgl_db_notify_remove (gulong id)
+{
+ g_signal_handler_disconnect (G_OBJECT (model), id);
+}
+
+
+/*===========================================*/
+/* Paper db functions. */
+/*===========================================*/
+
+/**
+ * lgl_db_get_paper_id_list:
+ *
+ * Get a list of all paper ids known to libglabels.
+ *
+ * Returns: a list of paper ids.
+ *
+ */
+GList *
+lgl_db_get_paper_id_list (void)
+{
+ GList *ids = NULL;
+ GList *p;
+ lglPaper *paper;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ for ( p=model->papers; p != NULL; p=p->next )
+ {
+ paper = (lglPaper *)p->data;
+ ids = g_list_append (ids, g_strdup (paper->id));
+ }
+
+ return ids;
+}
+
+
+/**
+ * lgl_db_free_paper_id_list:
+ * @ids: List of id strings to be freed.
+ *
+ * Free up all storage associated with an id list obtained with
+ * lgl_db_get_paper_id_list().
+ *
+ */
+void
+lgl_db_free_paper_id_list (GList *ids)
+{
+ GList *p;
+
+ for (p = ids; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+
+ g_list_free (ids);
+}
+
+
+/**
+ * lgl_db_get_paper_name_list:
+ *
+ * Get a list of all localized paper names known to libglabels.
+ *
+ * Returns: a list of localized paper names.
+ *
+ */
+GList *
+lgl_db_get_paper_name_list (void)
+{
+ GList *names = NULL;
+ GList *p;
+ lglPaper *paper;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ for ( p=model->papers; p != NULL; p=p->next )
+ {
+ paper = (lglPaper *)p->data;
+ names = g_list_append (names, g_strdup (paper->name));
+ }
+
+ return names;
+}
+
+
+/**
+ * lgl_db_free_paper_name_list:
+ * @names: List of localized paper name strings to be freed.
+ *
+ * Free up all storage associated with a name list obtained with
+ * lgl_db_get_paper_name_list().
+ *
+ */
+void
+lgl_db_free_paper_name_list (GList *names)
+{
+ GList *p;
+
+ for (p = names; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+
+ g_list_free (names);
+}
+
+
+/**
+ * lgl_db_lookup_paper_from_name:
+ * @name: localized paper name string
+ *
+ * Lookup paper definition from localized paper name string.
+ *
+ * Returns: pointer to a newly allocated #lglPaper structure.
+ *
+ */
+lglPaper *
+lgl_db_lookup_paper_from_name (const gchar *name)
+{
+ GList *p;
+ lglPaper *paper;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (name == NULL)
+ {
+ /* If no name, return first paper as a default */
+ return lgl_paper_dup ((lglPaper *) model->papers->data);
+ }
+
+ for (p = model->papers; p != NULL; p = p->next)
+ {
+ paper = (lglPaper *) p->data;
+ if (UTF8_EQUAL (paper->name, name))
+ {
+ return lgl_paper_dup (paper);
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * lgl_db_lookup_paper_from_id:
+ * @id: paper id string
+ *
+ * Lookup paper definition from id string.
+ *
+ * Returns: pointer to a newly allocated #lglPaper structure.
+ *
+ */
+lglPaper *
+lgl_db_lookup_paper_from_id (const gchar *id)
+{
+ GList *p;
+ lglPaper *paper;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (id == NULL)
+ {
+ /* If no id, return first paper as a default */
+ return lgl_paper_dup ((lglPaper *) model->papers->data);
+ }
+
+ for (p = model->papers; p != NULL; p = p->next)
+ {
+ paper = (lglPaper *) p->data;
+ if (ASCII_EQUAL (paper->id, id))
+ {
+ return lgl_paper_dup (paper);
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * lgl_db_lookup_paper_id_from_name:
+ * @name: localized paper name stringp
+ *
+ * Lookup paper name string from localized paper name string.
+ *
+ * Returns: pointer to a newly allocated id string.
+ *
+ */
+gchar *
+lgl_db_lookup_paper_id_from_name (const gchar *name)
+{
+ lglPaper *paper = NULL;
+ gchar *id = NULL;
+
+ if (name != NULL)
+ {
+ paper = lgl_db_lookup_paper_from_name (name);
+ if ( paper != NULL )
+ {
+ id = g_strdup (paper->id);
+ lgl_paper_free (paper);
+ paper = NULL;
+ }
+ }
+
+ return id;
+}
+
+
+/**
+ * lgl_db_lookup_paper_name_from_id:
+ * @id: paper id string
+ *
+ * Lookup localized paper name string from paper id string.
+ *
+ * Returns: pointer to a newly allocated localized paper name string.
+ *
+ */
+gchar *
+lgl_db_lookup_paper_name_from_id (const gchar *id)
+{
+ lglPaper *paper = NULL;
+ gchar *name = NULL;
+
+ if (id != NULL)
+ {
+ paper = lgl_db_lookup_paper_from_id (id);
+ if ( paper != NULL )
+ {
+ name = g_strdup (paper->name);
+ lgl_paper_free (paper);
+ paper = NULL;
+ }
+ }
+
+ return name;
+}
+
+
+/**
+ * lgl_db_is_paper_id_known:
+ * @id: paper id to test
+ *
+ * Determine if given paper id is known to libglabels.
+ *
+ * Returns: TRUE if id is known, otherwise FALSE.
+ *
+ */
+gboolean
+lgl_db_is_paper_id_known (const gchar *id)
+{
+ GList *p;
+ lglPaper *paper;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (id == NULL)
+ {
+ return FALSE;
+ }
+
+ for (p = model->papers; p != NULL; p = p->next)
+ {
+ paper = (lglPaper *) p->data;
+ if (ASCII_EQUAL (paper->id, id))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/**
+ * lgl_db_is_paper_id_other:
+ * @id: paper id to test
+ *
+ * Determine if given paper id is the special id "Other."
+ *
+ * Returns: TRUE if id is "Other", otherwise FALSE.
+ *
+ */
+gboolean
+lgl_db_is_paper_id_other (const gchar *id)
+{
+ if (id == NULL)
+ {
+ return FALSE;
+ }
+
+ return (ASCII_EQUAL (id, "Other"));
+}
+
+
+static GList *
+read_papers (void)
+{
+ gchar *data_dir;
+ GList *papers = NULL;
+
+ data_dir = SYSTEM_CONFIG_DIR;
+ papers = read_paper_files_from_dir (papers, data_dir);
+ g_free (data_dir);
+
+ data_dir = USER_CONFIG_DIR;
+ papers = read_paper_files_from_dir (papers, data_dir);
+ g_free (data_dir);
+
+ if (papers == NULL)
+ {
+ g_critical (_("Unable to locate paper size definitions. Libglabels may not be installed correctly!"));
+ }
+
+ return papers;
+}
+
+
+static GList *
+read_paper_files_from_dir (GList *papers,
+ const gchar *dirname)
+{
+ GDir *dp;
+ const gchar *filename, *extension;
+ gchar *full_filename = NULL;
+ GError *gerror = NULL;
+ GList *new_papers = NULL;
+
+ if (dirname == NULL)
+ {
+ return papers;
+ }
+
+ if (!g_file_test (dirname, G_FILE_TEST_EXISTS))
+ {
+ return papers;
+ }
+
+ dp = g_dir_open (dirname, 0, &gerror);
+ if (gerror != NULL)
+ {
+ g_message ("cannot open data directory: %s", gerror->message );
+ return papers;
+ }
+
+ while ((filename = g_dir_read_name (dp)) != NULL)
+ {
+
+ extension = strrchr (filename, '.');
+
+ if (extension != NULL)
+ {
+
+ if ( ASCII_EQUAL (filename, "paper-sizes.xml") )
+ {
+
+ full_filename =
+ g_build_filename (dirname, filename, NULL);
+ new_papers =
+ lgl_xml_paper_read_papers_from_file (full_filename);
+ g_free (full_filename);
+
+ papers = g_list_concat (papers, new_papers);
+ new_papers = NULL;
+
+ }
+
+ }
+
+ }
+
+ g_dir_close (dp);
+
+ return papers;
+}
+
+
+/**
+ * lgl_db_print_known_papers:
+ *
+ * For debugging purposes: print a list of all paper definitions known to
+ * libglabels.
+ *
+ */
+void
+lgl_db_print_known_papers (void)
+{
+ GList *p;
+ lglPaper *paper;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ g_print ("%s():\n", __FUNCTION__);
+ for (p = model->papers; p != NULL; p = p->next)
+ {
+ paper = (lglPaper *) p->data;
+
+ g_print ("PAPER id=\"%s\", name=\"%s\", width=%gpts, height=%gpts\n",
+ paper->id, paper->name, paper->width, paper->height);
+ }
+ g_print ("\n");
+
+}
+
+
+/*===========================================*/
+/* Category db functions. */
+/*===========================================*/
+
+/**
+ * lgl_db_get_category_id_list:
+ *
+ * Get a list of all category ids known to libglabels.
+ *
+ * Returns: a list of category ids.
+ *
+ */
+GList *
+lgl_db_get_category_id_list (void)
+{
+ GList *ids = NULL;
+ GList *p;
+ lglCategory *category;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ for ( p=model->categories; p != NULL; p=p->next )
+ {
+ category = (lglCategory *)p->data;
+ ids = g_list_append (ids, g_strdup (category->id));
+ }
+
+ return ids;
+}
+
+
+/**
+ * lgl_db_free_category_id_list:
+ * @ids: List of id strings to be freed.
+ *
+ * Free up all storage associated with an id list obtained with
+ * lgl_db_get_category_id_list().
+ *
+ */
+void
+lgl_db_free_category_id_list (GList *ids)
+{
+ GList *p;
+
+ for (p = ids; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+
+ g_list_free (ids);
+}
+
+
+/**
+ * lgl_db_get_category_name_list:
+ *
+ * Get a list of all localized category names known to libglabels.
+ *
+ * Returns: a list of localized category names.
+ *
+ */
+GList *
+lgl_db_get_category_name_list (void)
+{
+ GList *names = NULL;
+ GList *p;
+ lglCategory *category;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ for ( p=model->categories; p != NULL; p=p->next )
+ {
+ category = (lglCategory *)p->data;
+ names = g_list_append (names, g_strdup (category->name));
+ }
+
+ return names;
+}
+
+
+/**
+ * lgl_db_free_category_name_list:
+ * @names: List of localized category name strings to be freed.
+ *
+ * Free up all storage associated with a name list obtained with
+ * lgl_db_get_category_name_list().
+ *
+ */
+void
+lgl_db_free_category_name_list (GList *names)
+{
+ GList *p;
+
+ for (p = names; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+
+ g_list_free (names);
+}
+
+
+/**
+ * lgl_db_lookup_category_from_name:
+ * @name: localized category name string
+ *
+ * Lookup category definition from localized category name string.
+ *
+ * Returns: pointer to a newly allocated #lglCategory structure.
+ *
+ */
+lglCategory *
+lgl_db_lookup_category_from_name (const gchar *name)
+{
+ GList *p;
+ lglCategory *category;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (name == NULL)
+ {
+ /* If no name, return first category as a default */
+ return lgl_category_dup ((lglCategory *) model->categories->data);
+ }
+
+ for (p = model->categories; p != NULL; p = p->next)
+ {
+ category = (lglCategory *) p->data;
+ if (UTF8_EQUAL (category->name, name))
+ {
+ return lgl_category_dup (category);
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * lgl_db_lookup_category_from_id:
+ * @id: category id string
+ *
+ * Lookup category definition from id string.
+ *
+ * Returns: pointer to a newly allocated #lglCategory structure.
+ *
+ */
+lglCategory *
+lgl_db_lookup_category_from_id (const gchar *id)
+{
+ GList *p;
+ lglCategory *category;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (id == NULL)
+ {
+ /* If no id, return first category as a default */
+ return lgl_category_dup ((lglCategory *) model->categories->data);
+ }
+
+ for (p = model->categories; p != NULL; p = p->next)
+ {
+ category = (lglCategory *) p->data;
+ if (ASCII_EQUAL (category->id, id))
+ {
+ return lgl_category_dup (category);
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * lgl_db_lookup_category_id_from_name:
+ * @name: localized category name stringp
+ *
+ * Lookup category name string from localized category name string.
+ *
+ * Returns: pointer to a newly allocated id string.
+ *
+ */
+gchar *
+lgl_db_lookup_category_id_from_name (const gchar *name)
+{
+ lglCategory *category = NULL;
+ gchar *id = NULL;
+
+ if (name != NULL)
+ {
+ category = lgl_db_lookup_category_from_name (name);
+ if ( category != NULL )
+ {
+ id = g_strdup (category->id);
+ lgl_category_free (category);
+ category = NULL;
+ }
+ }
+
+ return id;
+}
+
+
+/**
+ * lgl_db_lookup_category_name_from_id:
+ * @id: category id string
+ *
+ * Lookup localized category name string from category id string.
+ *
+ * Returns: pointer to a newly allocated localized category name string.
+ *
+ */
+gchar *
+lgl_db_lookup_category_name_from_id (const gchar *id)
+{
+ lglCategory *category = NULL;
+ gchar *name = NULL;
+
+ if (id != NULL)
+ {
+ category = lgl_db_lookup_category_from_id (id);
+ if ( category != NULL )
+ {
+ name = g_strdup (category->name);
+ lgl_category_free (category);
+ category = NULL;
+ }
+ }
+
+ return name;
+}
+
+
+/**
+ * lgl_db_is_category_id_known:
+ * @id: category id to test
+ *
+ * Determine if given category id is known to libglabels.
+ *
+ * Returns: TRUE if id is known, otherwise FALSE.
+ *
+ */
+gboolean
+lgl_db_is_category_id_known (const gchar *id)
+{
+ GList *p;
+ lglCategory *category;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (id == NULL)
+ {
+ return FALSE;
+ }
+
+ for (p = model->categories; p != NULL; p = p->next)
+ {
+ category = (lglCategory *) p->data;
+ if (ASCII_EQUAL (category->id, id))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+static GList *
+read_categories (void)
+{
+ gchar *data_dir;
+ GList *categories = NULL;
+
+ data_dir = SYSTEM_CONFIG_DIR;
+ categories = read_category_files_from_dir (categories, data_dir);
+ g_free (data_dir);
+
+ data_dir = USER_CONFIG_DIR;
+ categories = read_category_files_from_dir (categories, data_dir);
+ g_free (data_dir);
+
+ if (categories == NULL)
+ {
+ g_critical (_("Unable to locate category definitions. Libglabels may not be installed correctly!"));
+ }
+
+ return categories;
+}
+
+
+static GList *
+read_category_files_from_dir (GList *categories,
+ const gchar *dirname)
+{
+ GDir *dp;
+ const gchar *filename, *extension;
+ gchar *full_filename = NULL;
+ GError *gerror = NULL;
+ GList *new_categories = NULL;
+
+ if (dirname == NULL)
+ {
+ return categories;
+ }
+
+ if (!g_file_test (dirname, G_FILE_TEST_EXISTS))
+ {
+ return categories;
+ }
+
+ dp = g_dir_open (dirname, 0, &gerror);
+ if (gerror != NULL)
+ {
+ g_message ("cannot open data directory: %s", gerror->message );
+ return categories;
+ }
+
+ while ((filename = g_dir_read_name (dp)) != NULL)
+ {
+
+ extension = strrchr (filename, '.');
+
+ if (extension != NULL)
+ {
+
+ if ( ASCII_EQUAL (filename, "categories.xml") )
+ {
+
+ full_filename =
+ g_build_filename (dirname, filename, NULL);
+ new_categories =
+ lgl_xml_category_read_categories_from_file (full_filename);
+ g_free (full_filename);
+
+ categories = g_list_concat (categories, new_categories);
+ new_categories = NULL;
+
+ }
+
+ }
+
+ }
+
+ g_dir_close (dp);
+
+ return categories;
+}
+
+
+/**
+ * lgl_db_print_known_categories:
+ *
+ * For debugging purposes: print a list of all category definitions known to
+ * libglabels.
+ *
+ */
+void
+lgl_db_print_known_categories (void)
+{
+ GList *p;
+ lglCategory *category;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ g_print ("%s():\n", __FUNCTION__);
+ for (p = model->categories; p != NULL; p = p->next)
+ {
+ category = (lglCategory *) p->data;
+
+ g_print ("CATEGORY id=\"%s\", name=\"%s\"\n", category->id, category->name);
+ }
+ g_print ("\n");
+
+}
+
+
+/*===========================================*/
+/* Vendor db functions. */
+/*===========================================*/
+
+/**
+ * lgl_db_get_vendor_name_list:
+ *
+ * Get a list of all localized vendor names known to libglabels.
+ *
+ * Returns: a list of localized vendor names.
+ *
+ */
+GList *
+lgl_db_get_vendor_name_list (void)
+{
+ GList *names = NULL;
+ GList *p;
+ lglVendor *vendor;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ for ( p=model->vendors; p != NULL; p=p->next )
+ {
+ vendor = (lglVendor *)p->data;
+ names = g_list_append (names, g_strdup (vendor->name));
+ }
+
+ return names;
+}
+
+
+/**
+ * lgl_db_free_vendor_name_list:
+ * @names: List of localized vendor name strings to be freed.
+ *
+ * Free up all storage associated with a name list obtained with
+ * lgl_db_get_vendor_name_list().
+ *
+ */
+void
+lgl_db_free_vendor_name_list (GList *names)
+{
+ GList *p;
+
+ for (p = names; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+
+ g_list_free (names);
+}
+
+
+/**
+ * lgl_db_lookup_vendor_from_name:
+ * @name: localized vendor name string
+ *
+ * Lookup vendor definition from localized vendor name string.
+ *
+ * Returns: pointer to a newly allocated #lglVendor structure.
+ *
+ */
+lglVendor *
+lgl_db_lookup_vendor_from_name (const gchar *name)
+{
+ GList *p;
+ lglVendor *vendor;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (name == NULL)
+ {
+ /* If no name, return first vendor as a default */
+ return lgl_vendor_dup ((lglVendor *) model->vendors->data);
+ }
+
+ for (p = model->vendors; p != NULL; p = p->next)
+ {
+ vendor = (lglVendor *) p->data;
+ if (UTF8_EQUAL (vendor->name, name))
+ {
+ return lgl_vendor_dup (vendor);
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * lgl_db_is_vendor_name_known:
+ * @name: vendor name to test
+ *
+ * Determine if given vendor id is known to libglabels.
+ *
+ * Returns: TRUE if id is known, otherwise FALSE.
+ *
+ */
+gboolean
+lgl_db_is_vendor_name_known (const gchar *name)
+{
+ GList *p;
+ lglVendor *vendor;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (name == NULL)
+ {
+ return FALSE;
+ }
+
+ for (p = model->vendors; p != NULL; p = p->next)
+ {
+ vendor = (lglVendor *) p->data;
+ if (UTF8_EQUAL (vendor->name, name))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+static GList *
+read_vendors (void)
+{
+ gchar *data_dir;
+ GList *vendors = NULL;
+
+ data_dir = SYSTEM_CONFIG_DIR;
+ vendors = read_vendor_files_from_dir (vendors, data_dir);
+ g_free (data_dir);
+
+ data_dir = USER_CONFIG_DIR;
+ vendors = read_vendor_files_from_dir (vendors, data_dir);
+ g_free (data_dir);
+
+ return vendors;
+}
+
+
+static GList *
+read_vendor_files_from_dir (GList *vendors,
+ const gchar *dirname)
+{
+ GDir *dp;
+ const gchar *filename, *extension;
+ gchar *full_filename = NULL;
+ GError *gerror = NULL;
+ GList *new_vendors = NULL;
+
+ if (dirname == NULL)
+ {
+ return vendors;
+ }
+
+ if (!g_file_test (dirname, G_FILE_TEST_EXISTS))
+ {
+ return vendors;
+ }
+
+ dp = g_dir_open (dirname, 0, &gerror);
+ if (gerror != NULL)
+ {
+ g_message ("cannot open data directory: %s", gerror->message );
+ return vendors;
+ }
+
+ while ((filename = g_dir_read_name (dp)) != NULL)
+ {
+
+ extension = strrchr (filename, '.');
+
+ if (extension != NULL)
+ {
+
+ if ( ASCII_EQUAL (filename, "vendors.xml") )
+ {
+
+ full_filename =
+ g_build_filename (dirname, filename, NULL);
+ new_vendors =
+ lgl_xml_vendor_read_vendors_from_file (full_filename);
+ g_free (full_filename);
+
+ vendors = g_list_concat (vendors, new_vendors);
+ new_vendors = NULL;
+
+ }
+
+ }
+
+ }
+
+ g_dir_close (dp);
+
+ return vendors;
+}
+
+
+/**
+ * lgl_db_print_known_vendors:
+ *
+ * For debugging purposes: print a list of all vendor definitions known to
+ * libglabels.
+ *
+ */
+void
+lgl_db_print_known_vendors (void)
+{
+ GList *p;
+ lglVendor *vendor;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ g_print ("%s():\n", __FUNCTION__);
+ for (p = model->vendors; p != NULL; p = p->next)
+ {
+ vendor = (lglVendor *) p->data;
+
+ g_print ("VENDOR name=\"%s\", url=\"%s\"\n",
+ vendor->name, vendor->url);
+ }
+ g_print ("\n");
+
+}
+
+
+/*===========================================*/
+/* Brand db functions. */
+/*===========================================*/
+
+/**
+ * lgl_db_get_brand_list:
+ * @paper_id: If non NULL, limit results to given page size.
+ * @category_id: If non NULL, limit results to given template category.
+ *
+ * Get a list of all valid brands of templates in the template database.
+ * Results can be filtered by page size and/or template category. A list of valid page
+ * sizes can be obtained using lgl_db_get_paper_id_list(). A list of valid template
+ * categories can be obtained using lgl_db_get_category_id_list().
+ *
+ * Returns: a list of brands
+ */
+GList *
+lgl_db_get_brand_list (const gchar *paper_id,
+ const gchar *category_id)
+{
+ GList *p_tmplt;
+ lglTemplate *template;
+ GList *brands = NULL;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
+ {
+ template = (lglTemplate *) p_tmplt->data;
+ if (lgl_template_does_page_size_match (template, paper_id) &&
+ lgl_template_does_category_match (template, category_id))
+ {
+
+ if ( !g_list_find_custom (brands, template->brand,
+ (GCompareFunc)lgl_str_utf8_casecmp) )
+ {
+ brands = g_list_insert_sorted (brands,
+ g_strdup (template->brand),
+ (GCompareFunc)lgl_str_utf8_casecmp);
+ }
+ }
+ }
+
+ return brands;
+}
+
+
+/**
+ * lgl_db_free_brand_list:
+ * @brands: List of template brand strings to be freed.
+ *
+ * Free up all storage associated with a list of template names obtained with
+ * lgl_db_get_brand_list().
+ *
+ */
+void
+lgl_db_free_brand_list (GList *brands)
+{
+ GList *p_brand;
+
+ for (p_brand = brands; p_brand != NULL; p_brand = p_brand->next)
+ {
+ g_free (p_brand->data);
+ p_brand->data = NULL;
+ }
+
+ g_list_free (brands);
+}
+
+
+/*===========================================*/
+/* Template db functions. */
+/*===========================================*/
+
+void
+_lgl_db_register_template_internal (const lglTemplate *template)
+{
+ lglTemplate *template_copy;
+
+ if (!lgl_db_does_template_exist (template->brand, template->part))
+ {
+ template_copy = lgl_template_dup (template);
+ model->templates = g_list_append (model->templates, template_copy);
+ add_to_template_cache (template_copy);
+ }
+ else
+ {
+ g_message ("Duplicate template: %s %s.", template->brand, template->part);
+ }
+}
+
+
+/**
+ * lgl_db_register_template:
+ * @template: Pointer to a template structure to add to database.
+ *
+ * Register a template. This function adds a template to the template database.
+ * The template will be stored in an individual XML file in the user template directory.
+ *
+ * Returns: Status of registration attempt (#lglDbRegStatus)
+ */
+lglDbRegStatus
+lgl_db_register_template (const lglTemplate *template)
+{
+ lglTemplate *template_copy;
+ gchar *dir, *filename, *abs_filename;
+ gint bytes_written;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (lgl_db_does_template_exist (template->brand, template->part))
+ {
+ return LGL_DB_REG_BRAND_PART_EXISTS;
+ }
+
+ if (lgl_db_is_paper_id_known (template->paper_id))
+ {
+ dir = USER_CONFIG_DIR;
+ g_mkdir_with_parents (dir, 0775); /* Try to make sure directory exists. */
+ filename = g_strdup_printf ("%s_%s.template", template->brand, template->part);
+ abs_filename = g_build_filename (dir, filename, NULL);
+ bytes_written = lgl_xml_template_write_template_to_file (template, abs_filename);
+ g_free (dir);
+ g_free (filename);
+ g_free (abs_filename);
+
+ if (bytes_written > 0)
+ {
+ template_copy = lgl_template_dup (template);
+ lgl_template_add_category (template_copy, "user-defined");
+ model->templates = g_list_append (model->templates, template_copy);
+ add_to_template_cache (template_copy);
+ g_signal_emit (G_OBJECT (model), signals[CHANGED], 0);
+ return LGL_DB_REG_OK;
+ }
+ else
+ {
+ return LGL_DB_REG_FILE_WRITE_ERROR;
+ }
+ }
+ else
+ {
+ g_message ("Cannot register new template with unknown page size.");
+ return LGL_DB_REG_BAD_PAPER_ID;
+ }
+
+}
+
+
+/**
+ * lgl_db_delete_template_by_name:
+ * @name: Name of template to be deleted.
+ *
+ * Delete a user defined template. This function deletes a template from
+ * the template database. The individual XML file in the user template
+ * directory will also be removed.
+ *
+ * Returns: Status of registration attempt (#lglDbDeleteStatus)
+ */
+lglDbDeleteStatus
+lgl_db_delete_template_by_name (const gchar *name)
+{
+ lglTemplate *template, *template1;
+ gchar *dir, *filename, *abs_filename;
+ GList *p;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (!lgl_db_does_template_name_exist (name))
+ {
+ return LGL_DB_DELETE_DOES_NOT_EXIST;
+ }
+
+ template = lgl_db_lookup_template_from_name (name);
+ if ( lgl_template_does_category_match (template, "user-defined") )
+ {
+ dir = USER_CONFIG_DIR;
+ filename = g_strdup_printf ("%s_%s.template", template->brand, template->part);
+ abs_filename = g_build_filename (dir, filename, NULL);
+
+ if (!g_file_test (abs_filename, G_FILE_TEST_EXISTS))
+ {
+ g_message ("File \"%s\" does not exist. Cannot delete template.", abs_filename);
+ return LGL_DB_DELETE_DOES_NOT_EXIST;
+ }
+
+ g_unlink (abs_filename);
+
+ g_free (dir);
+ g_free (filename);
+ g_free (abs_filename);
+
+ for ( p=model->templates; p != NULL; p=p->next )
+ {
+ template1 = (lglTemplate *)p->data;
+
+ if ( lgl_template_do_templates_match (template, template1) )
+ {
+ model->templates = g_list_delete_link (model->templates, p);
+ g_hash_table_remove (model->template_cache, name);
+ break;
+ }
+ }
+
+ lgl_template_free (template);
+
+ g_signal_emit (G_OBJECT (model), signals[CHANGED], 0);
+ return LGL_DB_DELETE_OK;
+ }
+ else
+ {
+ return LGL_DB_DELETE_NOT_USER_DEFINED;
+ }
+
+}
+
+
+/**
+ * lgl_db_delete_template_by_brand_part:
+ * @brand: Brand name or vendor of template to be deleted.
+ * @part: Part name or number of template to be deleted.
+ *
+ * Delete a user defined template. This function deletes a template from
+ * the template database. The individual XML file in the user template
+ * directory will also be removed.
+ *
+ * Returns: Status of registration attempt (#lglDbDeleteStatus)
+ */
+lglDbDeleteStatus
+lgl_db_delete_template_by_brand_part (const gchar *brand,
+ const gchar *part)
+{
+ gchar *name;
+ lglDbDeleteStatus status;
+
+ name = g_strdup_printf ("%s %s", brand, part);
+
+ status = lgl_db_delete_template_by_name (name);
+
+ g_free (name);
+
+ return status;
+}
+
+
+/**
+ * lgl_db_does_template_exist:
+ * @brand: Brand name.
+ * @part: Part name/number.
+ *
+ * This function tests whether a template with the given brand and part name/number exists.
+ *
+ * Returns: TRUE if such a template exists in the database.
+ */
+gboolean
+lgl_db_does_template_exist (const gchar *brand,
+ const gchar *part)
+{
+ GList *p_tmplt;
+ lglTemplate *template;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if ((brand == NULL) || (part == NULL))
+ {
+ return FALSE;
+ }
+
+ for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
+ {
+ template = (lglTemplate *) p_tmplt->data;
+
+ if ( UTF8_EQUAL (brand, template->brand) &&
+ UTF8_EQUAL (part, template->part) )
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/**
+ * lgl_db_does_template_name_exist:
+ * @name: name string
+ *
+ * This function test whether a template with the given name exists.
+ *
+ * Returns: TRUE if such a template exists in the database.
+ *
+ */
+gboolean
+lgl_db_does_template_name_exist (const gchar *name)
+{
+ GList *p_tmplt;
+ lglTemplate *template;
+ gchar *candidate_name;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (name == NULL)
+ {
+ return FALSE;
+ }
+
+ for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
+ {
+ template = (lglTemplate *) p_tmplt->data;
+ candidate_name = g_strdup_printf ("%s %s", template->brand, template->part);
+
+ if ( UTF8_EQUAL (candidate_name, name) )
+ {
+ g_free (candidate_name);
+ return TRUE;
+ }
+ g_free (candidate_name);
+ }
+
+ return FALSE;
+}
+
+
+/**
+ * lgl_db_get_template_name_list_all:
+ * @brand: If non NULL, limit results to given brand
+ * @paper_id: If non NULL, limit results to given page size.
+ * @category_id: If non NULL, limit results to given template category.
+ *
+ * Get a list of all valid names of templates in the template database.
+ * Results can be filtered by page size and/or template category. A list of valid page
+ * sizes can be obtained using lgl_db_get_paper_id_list(). A list of valid template
+ * categories can be obtained using lgl_db_get_category_id_list().
+ *
+ * Returns: a list of template names.
+ */
+GList *
+lgl_db_get_template_name_list_all (const gchar *brand,
+ const gchar *paper_id,
+ const gchar *category_id)
+{
+ GList *p_tmplt;
+ lglTemplate *template;
+ gchar *name;
+ GList *names = NULL;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
+ {
+ template = (lglTemplate *) p_tmplt->data;
+ if (lgl_template_does_brand_match (template, brand) &&
+ lgl_template_does_page_size_match (template, paper_id) &&
+ lgl_template_does_category_match (template, category_id))
+ {
+ name = g_strdup_printf ("%s %s", template->brand, template->part);
+ names = g_list_insert_sorted (names, name, (GCompareFunc)lgl_str_part_name_cmp);
+ }
+ }
+
+ return names;
+}
+
+
+/**
+ * lgl_db_get_similar_template_name_list:
+ * @name: Name of template under test.
+ *
+ * Get a list of all valid names of templates in the template database that
+ * have the same size and layout characteristics as the given template.
+ *
+ * Returns: a list of template names.
+ */
+GList *
+lgl_db_get_similar_template_name_list (const gchar *name)
+{
+ GList *p_tmplt;
+ lglTemplate *template1;
+ lglTemplate *template2;
+ gchar *name2;
+ GList *names = NULL;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if ( !name )
+ {
+ return NULL;
+ }
+
+ template1 = lgl_db_lookup_template_from_name (name);
+ if ( !template1 )
+ {
+ return NULL;
+ }
+
+ for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
+ {
+ template2 = (lglTemplate *) p_tmplt->data;
+
+ if ( lgl_template_are_templates_identical (template1, template2) )
+ {
+
+ name2 = g_strdup_printf ("%s %s", template2->brand, template2->part);
+ if ( !UTF8_EQUAL (name2, name) )
+ {
+ names = g_list_insert_sorted (names, name2,
+ (GCompareFunc)lgl_str_part_name_cmp);
+ }
+
+ }
+ }
+
+ return names;
+}
+
+
+/**
+ * lgl_db_free_template_name_list:
+ * @names: List of template name strings to be freed.
+ *
+ * Free up all storage associated with a list of template names obtained with
+ * lgl_db_get_template_name_list_all().
+ *
+ */
+void
+lgl_db_free_template_name_list (GList *names)
+{
+ GList *p_name;
+
+ for (p_name = names; p_name != NULL; p_name = p_name->next)
+ {
+ g_free (p_name->data);
+ p_name->data = NULL;
+ }
+
+ g_list_free (names);
+}
+
+
+/**
+ * lgl_db_lookup_template_from_name:
+ * @name: name string
+ *
+ * Lookup template in template database from name string.
+ *
+ * Returns: pointer to a newly allocated #lglTemplate structure.
+ *
+ */
+lglTemplate *
+lgl_db_lookup_template_from_name (const gchar *name)
+{
+ lglTemplate *template;
+ lglTemplate *new_template;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (name == NULL)
+ {
+ /* If no name, return first template as a default */
+ return lgl_template_dup ((lglTemplate *) model->templates->data);
+ }
+
+ template = g_hash_table_lookup (model->template_cache, name);
+
+ if (template)
+ {
+ new_template = lgl_template_dup (template);
+ return new_template;
+ }
+
+ /* No matching template has been found so return the first template */
+ return lgl_template_dup ((lglTemplate *) model->templates->data);
+}
+
+
+/**
+ * lgl_db_lookup_template_from_brand_part:
+ * @brand: brand name string
+ * @part: part name string
+ *
+ * Lookup template in template database from brand and part strings.
+ *
+ * Returns: pointer to a newly allocated #lglTemplate structure.
+ *
+ */
+lglTemplate *
+lgl_db_lookup_template_from_brand_part(const gchar *brand,
+ const gchar *part)
+{
+ gchar *name;
+ lglTemplate *template;
+ lglTemplate *new_template;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if ((brand == NULL) || (part == NULL))
+ {
+ /* If no name, return first template as a default */
+ return lgl_template_dup ((lglTemplate *) model->templates->data);
+ }
+
+ name = g_strdup_printf ("%s %s", brand, part);
+ template = g_hash_table_lookup (model->template_cache, name);
+
+ if (template)
+ {
+ new_template = lgl_template_dup (template);
+ return new_template;
+ }
+
+ /* No matching template has been found so return the first template */
+ g_free (name);
+ return lgl_template_dup ((lglTemplate *) model->templates->data);
+}
+
+
+static void
+add_to_template_cache (lglTemplate *template)
+{
+ gchar *name;
+
+ name = g_strdup_printf ("%s %s", template->brand, template->part);
+
+ g_hash_table_insert (model->template_cache, name, template);
+}
+
+
+void
+read_templates (void)
+{
+ gchar *data_dir;
+ GList *p;
+ lglTemplate *template;
+
+ /*
+ * User defined templates. Add to user-defined category.
+ */
+ data_dir = USER_CONFIG_DIR;
+ read_template_files_from_dir (data_dir);
+ g_free (data_dir);
+ for ( p=model->templates; p != NULL; p=p->next )
+ {
+ template = (lglTemplate *)p->data;
+ lgl_template_add_category (template, "user-defined");
+ }
+
+ /*
+ * Alternate user defined templates. (Used for manually created templates).
+ */
+ data_dir = ALT_USER_CONFIG_DIR;
+ read_template_files_from_dir (data_dir);
+ g_free (data_dir);
+
+ /*
+ * System templates.
+ */
+ data_dir = SYSTEM_CONFIG_DIR;
+ read_template_files_from_dir (data_dir);
+ g_free (data_dir);
+
+ if (model->templates == NULL)
+ {
+ g_critical (_("Unable to locate any template files. Libglabels may not be installed correctly!"));
+ }
+}
+
+
+void
+read_template_files_from_dir (const gchar *dirname)
+{
+ GDir *dp;
+ const gchar *filename, *extension, *extension2;
+ gchar *full_filename = NULL;
+ GError *gerror = NULL;
+
+ if (dirname == NULL)
+ return;
+
+ if (!g_file_test (dirname, G_FILE_TEST_EXISTS))
+ {
+ return;
+ }
+
+ dp = g_dir_open (dirname, 0, &gerror);
+ if (gerror != NULL)
+ {
+ g_message ("cannot open data directory: %s", gerror->message );
+ return;
+ }
+
+ while ((filename = g_dir_read_name (dp)) != NULL)
+ {
+
+ extension = strrchr (filename, '.');
+ extension2 = strrchr (filename, '-');
+
+ if ( (extension && ASCII_EQUAL (extension, ".template")) ||
+ (extension2 && ASCII_EQUAL (extension2, "-templates.xml")) )
+ {
+
+ full_filename = g_build_filename (dirname, filename, NULL);
+ lgl_xml_template_read_templates_from_file (full_filename);
+ g_free (full_filename);
+ }
+
+ }
+
+ g_dir_close (dp);
+}
+
+
+static lglTemplate *
+template_full_page (const gchar *paper_id)
+{
+ lglPaper *paper = NULL;
+ lglTemplate *template = NULL;
+ lglTemplateFrame *frame = NULL;
+ gchar *part;
+ gchar *desc;
+
+ g_return_val_if_fail (paper_id, NULL);
+
+ paper = lgl_db_lookup_paper_from_id (paper_id);
+ if ( paper == NULL )
+ {
+ return NULL;
+ }
+
+ part = g_strdup_printf ("%s-Full-Page", paper->id);
+ desc = g_strdup_printf (_("%s full page label"), paper->name);
+
+ template = lgl_template_new ("Generic", part, desc,
+ paper_id, paper->width, paper->height);
+
+
+ frame = lgl_template_frame_rect_new ("0",
+ paper->width,
+ paper->height,
+ 0.0,
+ 0.0,
+ 0.0);
+ lgl_template_add_frame (template, frame);
+
+ lgl_template_frame_add_layout (frame, lgl_template_layout_new (1, 1, 0., 0., 0., 0.));
+
+ lgl_template_frame_add_markup (frame, lgl_template_markup_margin_new (9.0));
+
+ g_free (desc);
+ desc = NULL;
+ lgl_paper_free (paper);
+ paper = NULL;
+
+ return template;
+}
+
+
+/**
+ * lgl_db_print_known_templates:
+ *
+ * Print all known templates (for debugging purposes).
+ *
+ */
+void
+lgl_db_print_known_templates (void)
+{
+ GList *p;
+ lglTemplate *template;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ g_print ("%s():\n", __FUNCTION__);
+ for (p=model->templates; p!=NULL; p=p->next)
+ {
+ template = (lglTemplate *)p->data;
+
+ g_print("TEMPLATE brand=\"%s\", part=\"%s\", description=\"%s\"\n",
+ template->brand, template->part, template->description);
+
+ }
+ g_print ("\n");
+
+}
+
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */