diff options
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/generators.c | 71 | ||||
| -rw-r--r-- | src/items.c | 109 | ||||
| -rw-r--r-- | src/items.h | 50 | ||||
| -rw-r--r-- | src/properties-table.c | 227 | ||||
| -rw-r--r-- | src/properties-table.h | 62 | ||||
| -rw-r--r-- | src/setup.c | 56 | ||||
| -rw-r--r-- | src/xml-parser.c | 74 | ||||
| -rw-r--r-- | src/xml-parser.h | 61 |
9 files changed, 581 insertions, 131 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 0553245..5a4d3b2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -33,6 +33,8 @@ cgg_SOURCES = \ job-manager.c \ jpeg-utils.cpp \ jpeg-utils.h \ + properties-table.c \ + properties-table.h \ replace-table.c \ replace-table.h \ setup.c \ diff --git a/src/generators.c b/src/generators.c index c51f24e..2483175 100644 --- a/src/generators.c +++ b/src/generators.c @@ -159,21 +159,11 @@ metadata_apply_overrides (ExifData *exif_data, g_free (exif_data->override_copyright); exif_data->override_copyright = g_strdup (setup->add_copyright); - exif_data->timezone_shift = item->metadata_tz_shift; - if (exif_data->timezone_shift == 0) - exif_data->timezone_shift = items->metadata_tz_shift; + exif_data->timezone_shift = get_prop_int (items, item, PROP_METADATA_TZ_SHIFT, 0); - exif_data->override_datetime = item->metadata_override_datetime; - if (exif_data->override_datetime == (time_t) -1) - exif_data->override_datetime = items->metadata_override_datetime; - - exif_data->override_aperture = item->metadata_override_aperture; - if (exif_data->override_aperture == -1) - exif_data->override_aperture = items->metadata_override_aperture; - - exif_data->override_focal_length = item->metadata_override_focal_length; - if (exif_data->override_focal_length == -1) - exif_data->override_focal_length = items->metadata_override_focal_length; + exif_data->override_datetime = get_prop_double (items, item, PROP_METADATA_OVERRIDE_DATETIME, (time_t) -1); + exif_data->override_aperture = get_prop_double (items, item, PROP_METADATA_OVERRIDE_APERTURE, -1); + exif_data->override_focal_length = get_prop_double (items, item, PROP_METADATA_OVERRIDE_FOCAL_LENGTH, -1); g_free (exif_data->external_exif_data); exif_data->external_exif_data = NULL; @@ -182,9 +172,7 @@ metadata_apply_overrides (ExifData *exif_data, exif_data->squared_thumbnail_type = setup->squared_thumbnail_type; - exif_data->thumbnail_crop_hint = item->thumbnail_crop_hint; - if (exif_data->thumbnail_crop_hint == CROP_HINT_UNDEFINED) - exif_data->thumbnail_crop_hint = items->thumbnail_crop_hint; + exif_data->thumbnail_crop_hint = get_prop_int (items, item, PROP_THUMB_CROP_HINT, CROP_HINT_UNDEFINED); } @@ -206,6 +194,7 @@ generate_image (TGallerySetup *setup, gchar *img_src; gchar *img_dst; unsigned long img_w, img_h; + unsigned long tmpw, tmph; int quality; GList *l; TImageSize *image_size; @@ -251,29 +240,37 @@ generate_image (TGallerySetup *setup, if (img_w > 0 && img_h > 0) { stats_images_inc (); - /* Calculate sizes */ + /* Only the "preview" size is affected by deprecated item and album overrides */ + if (is_preview) { + tmpw = get_prop_int (items, item, PROP_WIDTH, img_w); + tmph = get_prop_int (items, item, PROP_HEIGHT, img_h); + calculate_sizes (tmpw, tmph, &img_w, &img_h); + } if (is_thumbnail && setup->squared_thumbnail_type != THUMBNAIL_SQUARE_TYPE_NONE) - img_w = img_h = image_size->square_size; + tmpw = tmph = image_size->square_size; else - if (is_preview && item->width > 0 && item->height > 0) - calculate_sizes (item->width, item->height, &img_w, &img_h); + /* Calculate sizes */ if (img_w > img_h) { - if (is_preview && items->landscape_width > 0 && items->landscape_height > 0) - calculate_sizes (items->landscape_width, items->landscape_height, &img_w, &img_h); - else - calculate_sizes (image_size->landscape_width, image_size->landscape_height, &img_w, &img_h); + tmpw = image_size->landscape_width; + tmph = image_size->landscape_height; + if (is_preview) { + tmpw = get_prop_int (items, item, PROP_LANDSCAPE_W, tmpw); + tmph = get_prop_int (items, item, PROP_LANDSCAPE_H, tmph); + } } else { - if (is_preview && items->portrait_width > 0 && items->portrait_height > 0) - calculate_sizes (items->portrait_width, items->portrait_height, &img_w, &img_h); - else - calculate_sizes (image_size->portrait_width, image_size->portrait_height, &img_w, &img_h); + tmpw = image_size->portrait_width; + tmph = image_size->portrait_height; + if (is_preview) { + tmpw = get_prop_int (items, item, PROP_PORTRAIT_W, tmpw); + tmph = get_prop_int (items, item, PROP_PORTRAIT_H, tmph); + } } + calculate_sizes (tmpw, tmph, &img_w, &img_h); /* Calculate quality */ - quality = image_size->quality; - if (is_preview && items->quality > 0 && items->quality <= 100) - quality = items->quality; - if (is_preview && item->quality > 0 && item->quality <= 100) - quality = item->quality; + if (is_preview) + quality = get_prop_int (items, item, PROP_QUALITY, image_size->quality); + else + quality = image_size->quality; /* Perform resize and strip */ if (! resize_image (img_src, img_dst, img_w, img_h, quality, is_thumbnail, setup->autorotate, exif_data)) @@ -946,11 +943,9 @@ write_html_image (TGallerySetup *setup, block_parser_register_function (block_parser, "has_exif_key", has_exif_key_cb, exif); /* Border style */ - s1 = item->border_style; - if (s1 == NULL) - s1 = parent_items->border_style; + s1 = get_prop_string (parent_items, item, PROP_BORDER_STYLE, NULL); if (s1) - g_hash_table_replace (defines, g_strdup ("BORDER_STYLE"), g_strdup (s1)); + g_hash_table_replace (defines, g_strdup ("BORDER_STYLE"), s1); /* Next/Previous links */ if (next_item) { diff --git a/src/items.c b/src/items.c index 2434c77..d720415 100644 --- a/src/items.c +++ b/src/items.c @@ -131,6 +131,7 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info) return NULL; index = g_malloc0 (sizeof (TAlbum)); + index->properties = properties_table_new (); /* Retrieve gallery type */ gallery_type = xml_file_get_node_attribute (xml, "/gallery", "type"); @@ -160,36 +161,35 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info) g_free (s); } - index->quality = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "quality", -1); - index->landscape_width = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "landscape_w", 0); - index->landscape_height = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "landscape_h", 0); - index->portrait_width = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "portrait_w", 0); - index->portrait_height = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "portrait_h", 0); + prop_xml_attr_long (index->properties, PROP_QUALITY, xml, "/gallery/general/images", "quality"); + prop_xml_attr_long (index->properties, PROP_LANDSCAPE_W, xml, "/gallery/general/images", "landscape_w"); + prop_xml_attr_long (index->properties, PROP_LANDSCAPE_H, xml, "/gallery/general/images", "landscape_h"); + prop_xml_attr_long (index->properties, PROP_PORTRAIT_W, xml, "/gallery/general/images", "portrait_w"); + prop_xml_attr_long (index->properties, PROP_PORTRAIT_H, xml, "/gallery/general/images", "portrait_h"); - index->border_style = xml_file_get_node_attribute (xml, "/gallery/general/border", "style"); + prop_xml_attr (index->properties, PROP_BORDER_STYLE, xml, "/gallery/general/border", "style"); index->meta_author = xml_file_get_node_value (xml, "/gallery/general/meta/author/text()"); index->meta_description = xml_file_get_node_value (xml, "/gallery/general/meta/description/text()"); index->meta_keywords = xml_file_get_node_value (xml, "/gallery/general/meta/keywords/text()"); s = xml_file_get_node_attribute (xml, "/gallery/general/metadata/timezone", "shift"); if (s != NULL) { - index->metadata_tz_shift = parse_timezone_string (s); + properties_table_add_int (index->properties, PROP_METADATA_TZ_SHIFT, parse_timezone_string (s)); g_free (s); } - index->metadata_override_datetime = (time_t) -1; s = xml_file_get_node_attribute (xml, "/gallery/general/metadata/override", "date"); if (s != NULL) { - index->metadata_override_datetime = parse_datetime_string (s); + properties_table_add_double (index->properties, PROP_METADATA_OVERRIDE_DATETIME, parse_datetime_string (s)); g_free (s); } - index->metadata_override_aperture = xml_file_get_node_attribute_double (xml, "/gallery/general/metadata/override", "aperture", -1); - index->metadata_override_focal_length = xml_file_get_node_attribute_double (xml, "/gallery/general/metadata/override", "focal_length", -1); + prop_xml_attr_double (index->properties, PROP_METADATA_OVERRIDE_APERTURE, xml, "/gallery/general/metadata/override", "aperture"); + prop_xml_attr_double (index->properties, PROP_METADATA_OVERRIDE_FOCAL_LENGTH, xml, "/gallery/general/metadata/override", "focal_length"); /* TODO: add support for lens name */ s = xml_file_get_node_attribute (xml, "/gallery/general/thumbnail", "crop"); if (s != NULL) { - index->thumbnail_crop_hint = parse_thumbnail_crop_hint (s); + properties_table_add_int (index->properties, PROP_THUMB_CROP_HINT, parse_thumbnail_crop_hint (s)); g_free (s); } @@ -253,6 +253,7 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info) continue; item = g_malloc0 (sizeof (TIndexItem)); + item->properties = properties_table_new (); if (strcmp (node_name, "item") == 0) { item->type = INDEX_ITEM_TYPE_PICTURE; @@ -263,10 +264,10 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info) else item->path = xml_file_get_node_attribute (xml, s, "src"); item->preview = xml_file_get_node_attribute (xml, s, "preview"); - item->quality = xml_file_get_node_attribute_long (xml, s, "quality", -1); - item->width = xml_file_get_node_attribute_long (xml, s, "width", 0); - item->height = xml_file_get_node_attribute_long (xml, s, "height", 0); - item->border_style = xml_file_get_node_attribute (xml, s, "border"); + prop_xml_attr_long (item->properties, PROP_QUALITY, xml, s, "quality"); + prop_xml_attr_long (item->properties, PROP_WIDTH, xml, s, "width"); + prop_xml_attr_long (item->properties, PROP_HEIGHT, xml, s, "height"); + prop_xml_attr (item->properties, PROP_BORDER_STYLE, xml, s, "border"); if (index->type == GALLERY_TYPE_ALBUM) item->thumbnail = xml_file_get_node_attribute (xml, s, "thumbnail"); g_free (s); @@ -325,19 +326,18 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info) s2 = xml_file_get_node_attribute (xml, s, "shift"); g_free (s); if (s2 != NULL) { - item->metadata_tz_shift = parse_timezone_string (s2); + properties_table_add_int (item->properties, PROP_METADATA_TZ_SHIFT, parse_timezone_string (s2)); g_free (s2); } - item->metadata_override_datetime = (time_t) -1; s = g_strdup_printf ("/gallery/items/*[%d]/metadata/override", i + 1); s2 = xml_file_get_node_attribute (xml, s, "date"); if (s2 != NULL) { - item->metadata_override_datetime = parse_datetime_string (s2); + properties_table_add_double (item->properties, PROP_METADATA_OVERRIDE_DATETIME, parse_datetime_string (s2)); g_free (s2); } - item->metadata_override_aperture = xml_file_get_node_attribute_double (xml, s, "aperture", -1); - item->metadata_override_focal_length = xml_file_get_node_attribute_double (xml, s, "focal_length", -1); + prop_xml_attr_double (item->properties, PROP_METADATA_OVERRIDE_APERTURE, xml, s, "aperture"); + prop_xml_attr_double (item->properties, PROP_METADATA_OVERRIDE_FOCAL_LENGTH, xml, s, "focal_length"); /* TODO: add support for lens name */ g_free (s); @@ -345,7 +345,7 @@ parse_album_xml (const gchar *filename, TPathInfo *path_info) s2 = xml_file_get_node_attribute (xml, s, "crop"); g_free (s); if (s2 != NULL) { - item->thumbnail_crop_hint = parse_thumbnail_crop_hint (s2); + properties_table_add_int (item->properties, PROP_THUMB_CROP_HINT, parse_thumbnail_crop_hint (s2)); g_free (s2); } @@ -408,8 +408,8 @@ dup_index_item (TIndexItem *item) i->title_description = g_strdup (item->title_description); i->thumbnail = g_strdup (item->thumbnail); i->preview = g_strdup (item->preview); - i->border_style = g_strdup (item->border_style); i->metadata_external_exif = g_strdup (item->metadata_external_exif); + i->properties = properties_table_dup (item->properties); return i; } @@ -426,8 +426,8 @@ free_index_item (TIndexItem *item) g_free (item->title_description); g_free (item->thumbnail); g_free (item->preview); - g_free (item->border_style); g_free (item->metadata_external_exif); + properties_table_free (item->properties); g_free (item); } } @@ -443,7 +443,6 @@ free_album_data (TAlbum *album) g_free (album->title); g_free (album->desc); g_free (album->footnote); - g_free (album->border_style); g_free (album->meta_author); g_free (album->meta_description); g_free (album->meta_keywords); @@ -456,6 +455,7 @@ free_album_data (TAlbum *album) g_ptr_array_foreach (album->items, (GFunc) free_index_item, NULL); g_ptr_array_free (album->items, TRUE); } + properties_table_free (album->properties); g_free (album); } } @@ -565,3 +565,62 @@ free_path_info (TPathInfo *path_info) g_free (path_info); } } + + +/* + * get_prop_*: retrieve attribute value from properties tables, with item taking priority, using items otherwise or falling back to default if not set anywhere + */ +gchar * +get_prop_string (TAlbum *items, TIndexItem *item, PropertyName name, const gchar *_default) +{ + const gchar *s = NULL; + + if (item) + s = properties_table_get_string (item->properties, name); + if (!s && items) + s = properties_table_get_string (items->properties, name); + + return g_strdup (s ? s : _default); +} + +long int +get_prop_int (TAlbum *items, TIndexItem *item, PropertyName name, const long int _default) +{ + long int i = _default; + gboolean res = FALSE; + + if (item) + res = properties_table_get_int (item->properties, name, &i); + if (!res && items) + res = properties_table_get_int (items->properties, name, &i); + + return i; +} + +gboolean +get_prop_bool (TAlbum *items, TIndexItem *item, PropertyName name, const gboolean _default) +{ + gboolean b = _default; + gboolean res = FALSE; + + if (item) + res = properties_table_get_bool (item->properties, name, &b); + if (!res && items) + res = properties_table_get_bool (items->properties, name, &b); + + return b; +} + +double +get_prop_double (TAlbum *items, TIndexItem *item, PropertyName name, const double _default) +{ + double d = _default; + gboolean res = FALSE; + + if (item) + res = properties_table_get_double (item->properties, name, &d); + if (!res && items) + res = properties_table_get_double (items->properties, name, &d); + + return d; +} diff --git a/src/items.h b/src/items.h index 792b7f0..46b4c38 100644 --- a/src/items.h +++ b/src/items.h @@ -19,6 +19,7 @@ #define __CGG__ITEMS_H__ #include <glib.h> +#include "properties-table.h" G_BEGIN_DECLS @@ -57,12 +58,6 @@ typedef struct { GPtrArray *items; void *parent_index; /* pointer to the parent TAlbum structure */ int parent_item_index; /* item index in the parent album */ - int quality; - unsigned long landscape_width; - unsigned long landscape_height; - unsigned long portrait_width; - unsigned long portrait_height; - gchar *border_style; gchar *meta_author; gchar *meta_description; gchar *meta_keywords; @@ -73,33 +68,21 @@ typedef struct { gchar *auth_username; gchar *auth_passwd; TAuthType auth_type; - int metadata_tz_shift; /* minutes */ - time_t metadata_override_datetime; - double metadata_override_aperture; - double metadata_override_focal_length; - TCropHint thumbnail_crop_hint; + PropertiesTable *properties; } TAlbum; typedef struct { + TIndexItemType type; gchar *path; gchar *title; gchar *title_description; gchar *thumbnail; gchar *preview; - int quality; - unsigned long width; - unsigned long height; gboolean force_nofullsize; gboolean force_fullsize; - gchar *border_style; - TIndexItemType type; gboolean hidden; gchar *metadata_external_exif; - int metadata_tz_shift; /* minutes */ - time_t metadata_override_datetime; - double metadata_override_aperture; - double metadata_override_focal_length; - TCropHint thumbnail_crop_hint; + PropertiesTable *properties; } TIndexItem; typedef struct { @@ -111,6 +94,21 @@ typedef struct { gchar *album_path; /* current path in the gallery hierarchy, starting with '/' */ } TPathInfo; +typedef enum { + PROP_QUALITY, + PROP_WIDTH, + PROP_HEIGHT, + PROP_LANDSCAPE_W, + PROP_LANDSCAPE_H, + PROP_PORTRAIT_W, + PROP_PORTRAIT_H, + PROP_BORDER_STYLE, + PROP_THUMB_CROP_HINT, + PROP_METADATA_TZ_SHIFT, /* minutes */ + PROP_METADATA_OVERRIDE_DATETIME, + PROP_METADATA_OVERRIDE_APERTURE, + PROP_METADATA_OVERRIDE_FOCAL_LENGTH, +} PropertyName; /* * GET_ITEM_TARGET_FILENAME: get target item filename @@ -157,6 +155,16 @@ TIndexItem *dup_index_item (TIndexItem *item); */ void free_index_item (TIndexItem *item); + +/* + * get_prop_*: retrieve attribute value from properties tables, with item taking priority, using items otherwise or falling back to default if not set anywhere + */ +gchar * get_prop_string (TAlbum *items, TIndexItem *item, PropertyName name, const gchar *_default); +long int get_prop_int (TAlbum *items, TIndexItem *item, PropertyName name, const long int _default); +gboolean get_prop_bool (TAlbum *items, TIndexItem *item, PropertyName name, const gboolean _default); +double get_prop_double (TAlbum *items, TIndexItem *item, PropertyName name, const double _default); + + G_END_DECLS #endif /* __CGG__ITEMS_H__ */ diff --git a/src/properties-table.c b/src/properties-table.c new file mode 100644 index 0000000..19d7a36 --- /dev/null +++ b/src/properties-table.c @@ -0,0 +1,227 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2014 Tomas Bzatek <tbzatek@users.sourceforge.net> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include <string.h> + +#include <glib.h> + +#include "properties-table.h" + + +typedef enum { + PROP_DATA_TYPE_STRING, + PROP_DATA_TYPE_INT, + PROP_DATA_TYPE_BOOL, + PROP_DATA_TYPE_DOUBLE +} PropertyDataType; + +typedef struct { + PropertyDataType type; + union { + gchar *s; + long int i; + gboolean b; + double d; + } data; +} PropertyData; + + +static void +free_property_data (PropertyData *data) +{ + if (data == NULL) + return; + + switch (data->type) { + case PROP_DATA_TYPE_STRING: + g_free (data->data.s); + break; + default: + break; + } + g_free (data); +} + + +/* + * properties_table_new: creates new property table + */ +PropertiesTable * +properties_table_new () +{ + return g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) free_property_data); +} + +/* + * properties_table_dup: creates deep copy of the table + */ +PropertiesTable * +properties_table_dup (PropertiesTable *table) +{ + PropertiesTable *t; + GHashTableIter iter; + gpointer key, value; + PropertyData *data; + + g_return_val_if_fail (table != NULL, NULL); + + t = properties_table_new (); + g_hash_table_iter_init (&iter, table); + while (g_hash_table_iter_next (&iter, &key, &value)) { + data = (PropertyData *) value; + switch (data->type) { + case PROP_DATA_TYPE_STRING: + properties_table_add_string (t, GPOINTER_TO_INT (key), data->data.s); + break; + case PROP_DATA_TYPE_INT: + properties_table_add_int (t, GPOINTER_TO_INT (key), data->data.i); + break; + case PROP_DATA_TYPE_BOOL: + properties_table_add_bool (t, GPOINTER_TO_INT (key), data->data.b); + break; + case PROP_DATA_TYPE_DOUBLE: + properties_table_add_double (t, GPOINTER_TO_INT (key), data->data.d); + break; + } + } + + return t; +} + +/* + * properties_table_free: destroys properties table and frees all data + */ +void +properties_table_free (PropertiesTable *table) +{ + g_assert (table != NULL); + g_hash_table_destroy (table); +} + +void +properties_table_add_string (PropertiesTable *table, int property_id, const gchar *value) +{ + PropertyData *data; + + g_assert (table != NULL); + + data = g_malloc0 (sizeof (PropertyData)); + data->type = PROP_DATA_TYPE_STRING; + data->data.s = g_strdup (value); + g_hash_table_replace (table, GINT_TO_POINTER (property_id), data); +} + +void +properties_table_add_int (PropertiesTable *table, int property_id, long int value) +{ + PropertyData *data; + + g_assert (table != NULL); + + data = g_malloc0 (sizeof (PropertyData)); + data->type = PROP_DATA_TYPE_INT; + data->data.i = value; + g_hash_table_replace (table, GINT_TO_POINTER (property_id), data); +} + +void +properties_table_add_bool (PropertiesTable *table, int property_id, gboolean value) +{ + PropertyData *data; + + g_assert (table != NULL); + + data = g_malloc0 (sizeof (PropertyData)); + data->type = PROP_DATA_TYPE_BOOL; + data->data.b = value; + g_hash_table_replace (table, GINT_TO_POINTER (property_id), data); +} + +void +properties_table_add_double (PropertiesTable *table, int property_id, double value) +{ + PropertyData *data; + + g_assert (table != NULL); + + data = g_malloc0 (sizeof (PropertyData)); + data->type = PROP_DATA_TYPE_DOUBLE; + data->data.d = value; + g_hash_table_replace (table, GINT_TO_POINTER (property_id), data); +} + + +/* + * properties_table_get_*: gets data for the specified id + */ +const gchar * +properties_table_get_string (PropertiesTable *table, int property_id) +{ + PropertyData *data; + + g_assert (table != NULL); + + data = g_hash_table_lookup (table, GINT_TO_POINTER (property_id)); + if (data && data->type == PROP_DATA_TYPE_STRING) + return data->data.s; + return NULL; +} + +gboolean +properties_table_get_int (PropertiesTable *table, int property_id, long int *value) +{ + PropertyData *data; + + g_assert (table != NULL); + + data = g_hash_table_lookup (table, GINT_TO_POINTER (property_id)); + if (data && data->type == PROP_DATA_TYPE_INT) { + *value = data->data.i; + return TRUE; + } + return FALSE; +} + +gboolean +properties_table_get_bool (PropertiesTable *table, int property_id, gboolean *value) +{ + PropertyData *data; + + g_assert (table != NULL); + + data = g_hash_table_lookup (table, GINT_TO_POINTER (property_id)); + if (data && data->type == PROP_DATA_TYPE_BOOL) { + *value = data->data.b; + return TRUE; + } + return FALSE; +} + +gboolean +properties_table_get_double (PropertiesTable *table, int property_id, double *value) +{ + PropertyData *data; + + g_assert (table != NULL); + + data = g_hash_table_lookup (table, GINT_TO_POINTER (property_id)); + if (data && data->type == PROP_DATA_TYPE_DOUBLE) { + *value = data->data.d; + return TRUE; + } + return FALSE; +} diff --git a/src/properties-table.h b/src/properties-table.h new file mode 100644 index 0000000..4a1a9ed --- /dev/null +++ b/src/properties-table.h @@ -0,0 +1,62 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2014 Tomas Bzatek <tbzatek@users.sourceforge.net> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __CGG__PROPERTIES_TABLE_H__ +#define __CGG__PROPERTIES_TABLE_H__ + +#include <glib.h> + +G_BEGIN_DECLS + + +typedef GHashTable PropertiesTable; + +/* + * properties_table_new: creates new property table + */ +PropertiesTable * properties_table_new (); + +/* + * properties_table_dup: creates deep copy of the table + */ +PropertiesTable * properties_table_dup (PropertiesTable *table); + +/* + * properties_table_add_*: adds new item in the table, duplicating data + */ +void properties_table_add_string (PropertiesTable *table, int property_id, const gchar *value); +void properties_table_add_int (PropertiesTable *table, int property_id, long int value); +void properties_table_add_bool (PropertiesTable *table, int property_id, gboolean value); +void properties_table_add_double (PropertiesTable *table, int property_id, double value); + +/* + * properties_table_get_*: gets data for the specified id, setting *value, returning TRUE if found + */ +const gchar * properties_table_get_string (PropertiesTable *table, int property_id); +gboolean properties_table_get_int (PropertiesTable *table, int property_id, long int *value); +gboolean properties_table_get_bool (PropertiesTable *table, int property_id, gboolean *value); +gboolean properties_table_get_double (PropertiesTable *table, int property_id, double *value); + +/* + * properties_table_free: destroys properties table and frees all data + */ +void properties_table_free (PropertiesTable *table); + + +G_END_DECLS + +#endif /* __CGG__PROPERTIES_TABLE_H__ */ diff --git a/src/setup.c b/src/setup.c index d9b5ed3..cf4ca3f 100644 --- a/src/setup.c +++ b/src/setup.c @@ -91,20 +91,20 @@ parse_setup_xml (const gchar *filename) setup = g_malloc0 (sizeof (TGallerySetup)); setup->setup_xml_path = g_strdup (filename); - setup->version = nearbyint (xml_file_get_node_attribute_double (xml, "/gallery_setup", "version", -1) * 100); + setup->version = nearbyint (xml_file_get_node_attribute_double_with_default (xml, "/gallery_setup", "version", -1) * 100); /* design section */ setup->design_setup_file = xml_file_get_node_value (xml, "/gallery_setup/design/setup_file/text()"); - setup->supplemental_files_use_common_root = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/design/supplemental_files_use_common_root", "value", FALSE); + setup->supplemental_files_use_common_root = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/design/supplemental_files_use_common_root", "value", FALSE); /* images section */ - setup->preload = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/images/preload", "value", TRUE); - setup->use_iptc_exif = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/images/use_iptc_exif", "value", FALSE); - setup->erase_exif_thumbnail = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/images/erase_embed_thumbnail", "value", FALSE); - setup->strip_xmp = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/images/strip_xmp", "value", TRUE); - setup->write_supplied_exif = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/images/write_supplied_exif", "value", FALSE); + setup->preload = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/images/preload", "value", TRUE); + setup->use_iptc_exif = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/images/use_iptc_exif", "value", FALSE); + setup->erase_exif_thumbnail = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/images/erase_embed_thumbnail", "value", FALSE); + setup->strip_xmp = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/images/strip_xmp", "value", TRUE); + setup->write_supplied_exif = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/images/write_supplied_exif", "value", FALSE); setup->nofullsize = xml_file_get_node_present (xml, "/gallery_setup/images/nofullsize"); - setup->autorotate = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/images/autorotate", "value", TRUE); + setup->autorotate = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/images/autorotate", "value", TRUE); s = xml_file_get_node_attribute (xml, "/gallery_setup/images/squared_thumbnails", "type"); if (s && g_ascii_strcasecmp (s, "simple") == 0) @@ -118,17 +118,17 @@ parse_setup_xml (const gchar *filename) setup->meta_author_email = xml_file_get_node_value (xml, "/gallery_setup/meta/author_email/text()"); setup->meta_description = xml_file_get_node_value (xml, "/gallery_setup/meta/description/text()"); setup->meta_keywords = xml_file_get_node_value (xml, "/gallery_setup/meta/keywords/text()"); - setup->use_title_as_meta = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/meta/use_title_as_meta", "value", TRUE); + setup->use_title_as_meta = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/meta/use_title_as_meta", "value", TRUE); setup->site_title = xml_file_get_node_attribute (xml, "/gallery_setup/meta/site", "title"); setup->add_copyright = xml_file_get_node_value (xml, "/gallery_setup/meta/add_copyright/text()"); setup->favicon_file = xml_file_get_node_value (xml, "/gallery_setup/meta/favicon/text()"); setup->favicon_type = xml_file_get_node_attribute (xml, "/gallery_setup/meta/favicon", "type"); /* navigation section */ - setup->use_inpage_links = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/navigation/use_inpage_links", "value", TRUE); + setup->use_inpage_links = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/navigation/use_inpage_links", "value", TRUE); /* feed section */ - setup->feed_enabled = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/feed", "enable", FALSE); + setup->feed_enabled = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/feed", "enable", FALSE); setup->feed_filename = xml_file_get_node_value (xml, "/gallery_setup/feed/filename/text()"); setup->feed_title = xml_file_get_node_value (xml, "/gallery_setup/feed/title/text()"); @@ -142,7 +142,7 @@ parse_setup_xml (const gchar *filename) /* legacy mode */ if (SETUP_IS_LEGACY (setup)) { setup->design_setup_file = xml_file_get_node_value (xml, "/gallery_setup/templates/path/text()"); - setup->supplemental_files_use_common_root = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/templates/support_files_use_common_root", "value", FALSE); + setup->supplemental_files_use_common_root = xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/templates/support_files_use_common_root", "value", FALSE); setup->location_base_url = xml_file_get_node_value (xml, "/gallery_setup/feed/base_url/text()"); } @@ -172,7 +172,7 @@ parse_design_setup_xml (const gchar *filename) return NULL; design = g_malloc0 (sizeof (TGalleryDesign)); - design->version = nearbyint (xml_file_get_node_attribute_double (xml, "/design_setup", "version", -1) * 100); + design->version = nearbyint (xml_file_get_node_attribute_double_with_default (xml, "/design_setup", "version", -1) * 100); s2 = xml_file_get_node_value (xml, "/design_setup/supplemental_files/text()"); if (s2) { @@ -192,21 +192,21 @@ parse_design_setup_xml (const gchar *filename) g_free (s); s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/landscape", i + 1); - image_size->landscape_width = xml_file_get_node_attribute_long (xml, s, "w", 0); - image_size->landscape_height = xml_file_get_node_attribute_long (xml, s, "h", 0); + image_size->landscape_width = xml_file_get_node_attribute_long_with_default (xml, s, "w", 0); + image_size->landscape_height = xml_file_get_node_attribute_long_with_default (xml, s, "h", 0); g_free (s); s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/portrait", i + 1); - image_size->portrait_width = xml_file_get_node_attribute_long (xml, s, "w", 0); - image_size->portrait_height = xml_file_get_node_attribute_long (xml, s, "h", 0); + image_size->portrait_width = xml_file_get_node_attribute_long_with_default (xml, s, "w", 0); + image_size->portrait_height = xml_file_get_node_attribute_long_with_default (xml, s, "h", 0); g_free (s); s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/square", i + 1); - image_size->square_size = xml_file_get_node_attribute_long (xml, s, "size", 0); + image_size->square_size = xml_file_get_node_attribute_long_with_default (xml, s, "size", 0); g_free (s); s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/quality", i + 1); - image_size->quality = xml_file_get_node_attribute_long (xml, s, "value", -1); + image_size->quality = xml_file_get_node_attribute_long_with_default (xml, s, "value", -1); g_free (s); s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/no_resize", i + 1); @@ -222,7 +222,7 @@ parse_design_setup_xml (const gchar *filename) design->themes = g_list_append (design->themes, theme); s = g_strdup_printf ("/design_setup/theme[%d]", i + 1); - theme->enabled = xml_file_get_node_attribute_boolean (xml, s, "enabled", TRUE); + theme->enabled = xml_file_get_node_attribute_boolean_with_default (xml, s, "enabled", TRUE); g_free (s); s = g_strdup_printf ("/design_setup/theme[%d]/index/template/text()", i + 1); @@ -312,12 +312,12 @@ makeup_legacy_design (const gchar *filename) image_size = g_malloc0 (sizeof (TImageSize)); image_size->name = g_strdup (image_sizes[i]); s = g_strdup_printf ("/gallery_setup/images/%s", image_sizes[i]); - image_size->landscape_width = xml_file_get_node_attribute_long (xml, s, "landscape_w", 0); - image_size->landscape_height = xml_file_get_node_attribute_long (xml, s, "landscape_h", 0); - image_size->portrait_width = xml_file_get_node_attribute_long (xml, s, "portrait_w", 0); - image_size->portrait_height = xml_file_get_node_attribute_long (xml, s, "portrait_h", 0); - image_size->square_size = xml_file_get_node_attribute_long (xml, s, "square", 0); - image_size->quality = xml_file_get_node_attribute_long (xml, s, "quality", -1); + image_size->landscape_width = xml_file_get_node_attribute_long_with_default (xml, s, "landscape_w", 0); + image_size->landscape_height = xml_file_get_node_attribute_long_with_default (xml, s, "landscape_h", 0); + image_size->portrait_width = xml_file_get_node_attribute_long_with_default (xml, s, "portrait_w", 0); + image_size->portrait_height = xml_file_get_node_attribute_long_with_default (xml, s, "portrait_h", 0); + image_size->square_size = xml_file_get_node_attribute_long_with_default (xml, s, "square", 0); + image_size->quality = xml_file_get_node_attribute_long_with_default (xml, s, "quality", -1); image_size->no_resize = (i == G_N_ELEMENTS (image_sizes) - 1); g_free (s); design->image_sizes = g_list_append (design->image_sizes, image_size); @@ -352,9 +352,9 @@ makeup_legacy_design (const gchar *filename) theme->picture_image_size = g_strdup (image_sizes[1]); theme->defines = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - if (xml_file_get_node_attribute_boolean (xml, "/gallery_setup/navigation/show_go_up", "value", TRUE)) + if (xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/navigation/show_go_up", "value", TRUE)) g_hash_table_replace (theme->defines, g_strdup ("SHOW_GO_UP"), g_strdup ("")); - if (xml_file_get_node_attribute_boolean (xml, "/gallery_setup/navigation/show_exif_table", "value", TRUE)) + if (xml_file_get_node_attribute_boolean_with_default (xml, "/gallery_setup/navigation/show_exif_table", "value", TRUE)) g_hash_table_replace (theme->defines, g_strdup ("SHOW_EXIF_TABLE"), g_strdup ("")); s = xml_file_get_node_attribute (xml, "/gallery_setup/images/border", "style"); g_hash_table_replace (theme->defines, g_strdup ("BORDER_STYLE"), s ? s : g_strdup ("border_single")); diff --git a/src/xml-parser.c b/src/xml-parser.c index 9f95cf3..a13e502 100644 --- a/src/xml-parser.c +++ b/src/xml-parser.c @@ -158,13 +158,13 @@ xml_file_get_node_value_with_default (TXMLFile *file, const gchar *x_path, const gchar *s; s = xml_file_get_node_value (file, x_path); - return s ? s : g_strdup (_default); } /* * xml_file_get_node_attribute: retrieve attribute value from XPath node + * - returns NULL if node is not present */ gchar * xml_file_get_node_attribute (TXMLFile *file, const gchar *x_path, const gchar *attr) @@ -198,35 +198,67 @@ xml_file_get_node_attribute (TXMLFile *file, const gchar *x_path, const gchar *a return attrv; } -long int -xml_file_get_node_attribute_long (TXMLFile *file, const gchar *x_path, const gchar *attr, const int _default) +gchar * +xml_file_get_node_attribute_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const gchar *_default) +{ + gchar *s = xml_file_get_node_attribute (file, x_path, attr); + return s != NULL ? s : g_strdup (_default); +} + +/* + * xml_file_get_node_attribute_*: retrieve attribute value from XPath node, storing it in *value, returning TRUE if value has been set. + */ +gboolean +xml_file_get_node_attribute_long (TXMLFile *file, const gchar *x_path, const gchar *attr, long int *value) { gchar *s; long int i; + char *endptr = NULL; s = xml_file_get_node_attribute (file, x_path, attr); if (s == NULL) - return _default; + return FALSE; - i = atol (s); + i = strtol (s, &endptr, 10); + if (endptr != NULL && *endptr != '\0') { + g_free (s); + return FALSE; + } g_free (s); - return i; + *value = i; + return TRUE; +} + +long int +xml_file_get_node_attribute_long_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const long int _default) +{ + long int i; + return xml_file_get_node_attribute_long (file, x_path, attr, &i) ? i : _default; } gboolean -xml_file_get_node_attribute_boolean (TXMLFile *file, const gchar *x_path, const gchar *attr, const gboolean _default) +xml_file_get_node_attribute_boolean (TXMLFile *file, const gchar *x_path, const gchar *attr, gboolean *value) { gchar *s; - gboolean b; s = xml_file_get_node_attribute (file, x_path, attr); - b = s ? (strcasecmp (s, "yes") == 0 || strcasecmp (s, "true") == 0) : _default; + if (s == NULL) + return FALSE; + + *value = (strcasecmp (s, "yes") == 0 || strcasecmp (s, "true") == 0); g_free (s); - return b; + return TRUE; } -double -xml_file_get_node_attribute_double (TXMLFile *file, const gchar *x_path, const gchar *attr, const double _default) +gboolean +xml_file_get_node_attribute_boolean_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const gboolean _default) +{ + gboolean b; + return xml_file_get_node_attribute_boolean (file, x_path, attr, &b) ? b : _default; +} + +gboolean +xml_file_get_node_attribute_double (TXMLFile *file, const gchar *x_path, const gchar *attr, double *value) { gchar *s; double d; @@ -234,13 +266,23 @@ xml_file_get_node_attribute_double (TXMLFile *file, const gchar *x_path, const g s = xml_file_get_node_attribute (file, x_path, attr); if (s == NULL) - return _default; + return FALSE; d = strtod (s, &endptr); - if (endptr != NULL && *endptr != '\0') - d = _default; + if (endptr != NULL && *endptr != '\0') { + g_free (s); + return FALSE; + } g_free (s); - return d; + *value = d; + return TRUE; +} + +double +xml_file_get_node_attribute_double_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const double _default) +{ + double d; + return xml_file_get_node_attribute_double (file, x_path, attr, &d) ? d : _default; } diff --git a/src/xml-parser.h b/src/xml-parser.h index 3ea3e90..27e8d83 100644 --- a/src/xml-parser.h +++ b/src/xml-parser.h @@ -23,6 +23,8 @@ #include <libxml/xmlmemory.h> #include <libxml/xpath.h> +#include "properties-table.h" + G_BEGIN_DECLS @@ -57,11 +59,22 @@ gchar * xml_file_get_node_value_with_default (TXMLFile *file, const gchar *x_pat /* * xml_file_get_node_attribute: retrieve attribute value from XPath node + * - returns NULL if node is not present */ gchar * xml_file_get_node_attribute (TXMLFile *file, const gchar *x_path, const gchar *attr); -long int xml_file_get_node_attribute_long (TXMLFile *file, const gchar *x_path, const gchar *attr, const int _default); -gboolean xml_file_get_node_attribute_boolean (TXMLFile *file, const gchar *x_path, const gchar *attr, const gboolean _default); -double xml_file_get_node_attribute_double (TXMLFile *file, const gchar *x_path, const gchar *attr, const double _default); +gchar * xml_file_get_node_attribute_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const gchar *_default); + +/* + * xml_file_get_node_attribute_*: retrieve attribute value from XPath node, storing it in *value, returning TRUE if value has been set. + */ +gboolean xml_file_get_node_attribute_long (TXMLFile *file, const gchar *x_path, const gchar *attr, long int *value); +long int xml_file_get_node_attribute_long_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const long int _default); + +gboolean xml_file_get_node_attribute_boolean (TXMLFile *file, const gchar *x_path, const gchar *attr, gboolean *value); +gboolean xml_file_get_node_attribute_boolean_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const gboolean _default); + +gboolean xml_file_get_node_attribute_double (TXMLFile *file, const gchar *x_path, const gchar *attr, double *value); +double xml_file_get_node_attribute_double_with_default (TXMLFile *file, const gchar *x_path, const gchar *attr, const double _default); /* * xml_file_get_node_present: existency test of the XPath node @@ -74,6 +87,48 @@ gboolean xml_file_get_node_present (TXMLFile *file, const gchar *x_path); int xml_file_node_get_children_count (TXMLFile *file, const gchar *x_path); +/* + * prop_xml_attr_*: retrieve data from the XML file and set the property if suceeded + * prop_xml_attr_*def: retrieve data from the XML file and set the property or default value on failure + */ +#define prop_xml_attr(t, n, xml, x_path, attr) { \ + gchar *xxxs = xml_file_get_node_attribute (xml, x_path, attr); \ + if (xxxs != NULL) \ + properties_table_add_string (t, n, xxxs); \ + g_free (xxxs); \ + } +#define prop_xml_attr_def(t, n, xml, x_path, attr, _default) { \ + gchar *xxxs = xml_file_get_node_attribute_with_default (xml, x_path, attr, _default); \ + properties_table_add_string (t, n, xxxs); \ + g_free (xxxs); \ + } + +#define prop_xml_attr_long(t, n, xml, x_path, attr) { \ + long int xxxi; \ + if (xml_file_get_node_attribute_long (xml, x_path, attr, &xxxi)) \ + properties_table_add_int (t, n, xxxi); \ + } +#define prop_xml_attr_long_def(t, n, xml, x_path, attr, _default) \ + properties_table_add_int (t, n, xml_file_get_node_attribute_long_with_default (xml, x_path, attr, _default)) + +#define prop_xml_attr_bool(t, n, xml, x_path, attr) { \ + gboolean xxxb; \ + if (xml_file_get_node_attribute_boolean (xml, x_path, attr, &xxxb)) \ + properties_table_add_bool (t, n, xxxb); \ + } +#define prop_xml_attr_bool_def(t, n, xml, x_path, attr, _default) \ + properties_table_add_bool (t, n, xml_file_get_node_attribute_boolean_with_default (xml, x_path, attr, _default)) + +#define prop_xml_attr_double(t, n, xml, x_path, attr) { \ + double xxxd; \ + if (xml_file_get_node_attribute_double (xml, x_path, attr, &xxxd)) \ + properties_table_add_double (t, n, xxxd); \ + } +#define prop_xml_attr_double_def(t, n, xml, x_path, attr, _default) \ + properties_table_add_double (t, n, xml_file_get_node_attribute_double_with_default (xml, x_path, attr, _default)) + + + G_END_DECLS #endif /* __CGG__XML_PARSER_H__ */ |
