From 75bb13e531654a561dc7baa2f2bc594aa4a8fc52 Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Sun, 29 May 2011 19:00:44 +0200 Subject: Introduce new theming system This extends current templating system to another dimension, bringing the possibility to have multiple themes generated at once. The purpose is to be able to switch between multiple designs, from PC to mobile, classic vs. flat view, slideshow, etc. For the moment, only the classic theme is available. Rules: * for switching between themes, place a link inside your template manually - it's not a cgg concern, only your theming infrastructure * don't forget to define different file names for index and album pages across different themes * it's recommended to keep default theme named as "index.*" to avoid showing directory listing on webserver Notes: * some TODOs will be fixed when we have new theme using these advanced features (e.g. pictures in album pages) * TODO: introduce tag/block conditional system, allow custom user defines for each theme/page * TODO: deprecate , and in favor of conditionals (these tags belong to theming) --- src/setup.c | 348 ++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 259 insertions(+), 89 deletions(-) (limited to 'src/setup.c') diff --git a/src/setup.c b/src/setup.c index 68c3cd3..f09a908 100644 --- a/src/setup.c +++ b/src/setup.c @@ -21,11 +21,6 @@ #include #include -#include -#include -#include -#include - #include #include @@ -91,122 +86,264 @@ parse_setup_xml (const gchar *filename) setup = g_malloc0 (sizeof (TGallerySetup)); setup->setup_xml_path = g_strdup (filename); - setup->templates_path = xml_file_get_node_value (xml, "/gallery_setup/templates/path/text()"); - setup->template_index = xml_file_get_node_value (xml, "/gallery_setup/templates/index/text()"); - setup->template_album = xml_file_get_node_value (xml, "/gallery_setup/templates/album/text()"); - setup->template_photo = xml_file_get_node_value (xml, "/gallery_setup/templates/photo/text()"); - s = xml_file_get_node_value (xml, "/gallery_setup/templates/template_files/text()"); - if (s) { - setup->template_files = g_strsplit (s, "\n", -1); - g_free (s); - } - setup->support_files_use_common_root = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/templates/support_files_use_common_root", "value", FALSE); - setup->index_file_name = xml_file_get_node_value_with_default (xml, "/gallery_setup/templates/index_file/text()", DEFAULT_INDEX_FILENAME); - - setup->thumbnail_dir = xml_file_get_node_value_with_default (xml, "/gallery_setup/images/thumbnail_dir/text()", DEFAULT_THUMBNAIL_DIR); - setup->img_big_dir = xml_file_get_node_value_with_default (xml, "/gallery_setup/images/preview_dir/text()", DEFAULT_IMG_BIG_DIR); - setup->img_orig_dir = xml_file_get_node_value_with_default (xml, "/gallery_setup/images/original_dir/text()", DEFAULT_IMG_ORIG_DIR); - setup->thumbnail_name_format = xml_file_get_node_value_with_default (xml, "/gallery_setup/images/thumbnail_name_format/text()", DEFAULT_THUMBNAIL_NAME_FORMAT); - if (strstr (setup->thumbnail_name_format, "%s") == NULL) { - g_free (setup->thumbnail_name_format); - setup->thumbnail_name_format = g_strdup (DEFAULT_THUMBNAIL_NAME_FORMAT); - } + /* 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->thumbnail_landscape_width = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "landscape_w", 0); - setup->thumbnail_landscape_height = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "landscape_h", 0); - setup->thumbnail_portrait_width = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "portrait_w", 0); - setup->thumbnail_portrait_height = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "portrait_h", 0); - setup->thumbnail_square_size = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "square", 0); - setup->thumbnail_quality = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/thumbnail", "quality", -1); - setup->preview_landscape_width = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "landscape_w", 0); - setup->preview_landscape_height = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "landscape_h", 0); - setup->preview_portrait_width = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "portrait_w", 0); - setup->preview_portrait_height = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "portrait_h", 0); - setup->preview_quality = xml_file_get_node_attribute_long (xml, "/gallery_setup/images/preview", "quality", -1); - setup->footer = xml_file_get_node_value (xml, "/gallery_setup/footer/text()"); + /* images section */ setup->border_style = xml_file_get_node_attribute (xml, "/gallery_setup/images/border", "style"); + 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->nofullsize = xml_file_get_node_present (xml, "/gallery_setup/images/nofullsize"); + + s = xml_file_get_node_attribute (xml, "/gallery_setup/images/squared_thumbnails", "type"); + if (s && g_ascii_strcasecmp (s, "simple") == 0) + setup->squared_thumbnail_type = THUMBNAIL_SQUARE_TYPE_SIMPLE; + else + setup->squared_thumbnail_type = THUMBNAIL_SQUARE_TYPE_NONE; + g_free (s); + + /* meta section */ setup->meta_author = xml_file_get_node_value (xml, "/gallery_setup/meta/author/text()"); 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->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->use_title_as_meta = xml_file_get_node_attribute_boolean (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->show_go_up = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/navigation/show_go_up", "value", TRUE); setup->show_exif_table = xml_file_get_node_attribute_boolean (xml, "/gallery_setup/navigation/show_exif_table", "value", TRUE); - setup->nofullsize = xml_file_get_node_present (xml, "/gallery_setup/images/nofullsize"); - - 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"); - + /* feed section */ setup->feed_enabled = xml_file_get_node_attribute_boolean (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()"); setup->feed_base_url = xml_file_get_node_value (xml, "/gallery_setup/feed/base_url/text()"); - s = xml_file_get_node_attribute (xml, "/gallery_setup/images/squared_thumbnails", "type"); - if (s && g_ascii_strcasecmp (s, "simple") == 0) - setup->squared_thumbnail_type = THUMBNAIL_SQUARE_TYPE_SIMPLE; - else - setup->squared_thumbnail_type = THUMBNAIL_SQUARE_TYPE_NONE; - g_free (s); + /* footer section */ + setup->footer = xml_file_get_node_value (xml, "/gallery_setup/footer/text()"); xml_parser_free (xml); return setup; } - -static int -test_tmpl_access (const gchar *dir, const gchar *path) +/* + * parse_design_setup_xml: XML parser for design.xml file + */ +TGalleryDesign * +parse_design_setup_xml (const gchar *filename) { + TXMLFile *xml; gchar *s; - int b; + gchar *s2; + TGalleryDesign *design; + TImageSize *image_size; + TGalleryDesignTheme *theme; + int count; + int i; - s = g_build_filename (dir, path, NULL); - b = g_access (s, R_OK); - g_free (s); - return b; + xml = xml_parser_load (filename); + if (xml == NULL) + return NULL; + + design = g_malloc0 (sizeof (TGalleryDesign)); + + s2 = xml_file_get_node_value (xml, "/design_setup/supplemental_files/text()"); + if (s2) { + design->supplemental_files = g_strsplit (s2, "\n", -1); + g_free (s2); + } + + + /* image_sizes section */ + count = xml_file_node_get_children_count (xml, "/design_setup/image_sizes/size"); + for (i = 0; i < count; i++) { + image_size = g_malloc0 (sizeof (TImageSize)); + design->image_sizes = g_list_append (design->image_sizes, image_size); + + s = g_strdup_printf ("/design_setup/image_sizes/size[%d]", i + 1); + image_size->name = xml_file_get_node_attribute (xml, s, "name"); + 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); + 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); + 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); + 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); + g_free (s); + + s = g_strdup_printf ("/design_setup/image_sizes/size[%d]/no_resize", i + 1); + image_size->no_resize = xml_file_get_node_present (xml, s); + g_free (s); + } + + + /* theme section */ + count = xml_file_node_get_children_count (xml, "/design_setup/theme"); + for (i = 0; i < count; i++) { + theme = g_malloc0 (sizeof (TGalleryDesignTheme)); + 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); + g_free (s); + + s = g_strdup_printf ("/design_setup/theme[%d]/index/template/text()", i + 1); + theme->index_template = xml_file_get_node_value (xml, s); + g_free (s); + s = g_strdup_printf ("/design_setup/theme[%d]/index/target_filename/text()", i + 1); + theme->index_filename = xml_file_get_node_value_with_default (xml, s, DEFAULT_INDEX_FILENAME); + g_free (s); + + s = g_strdup_printf ("/design_setup/theme[%d]/album/template/text()", i + 1); + theme->album_template = xml_file_get_node_value (xml, s); + g_free (s); + s = g_strdup_printf ("/design_setup/theme[%d]/album/target_filename/text()", i + 1); + theme->album_filename = xml_file_get_node_value_with_default (xml, s, DEFAULT_INDEX_FILENAME); + g_free (s); + s = g_strdup_printf ("/design_setup/theme[%d]/album/picture_size/text()", i + 1); + theme->album_image_size = xml_file_get_node_value (xml, s); + g_free (s); + + s = g_strdup_printf ("/design_setup/theme[%d]/picture/template/text()", i + 1); + theme->picture_template = xml_file_get_node_value (xml, s); + g_free (s); + s = g_strdup_printf ("/design_setup/theme[%d]/picture/target_filename/text()", i + 1); + theme->picture_filename = xml_file_get_node_value (xml, s); + g_free (s); + s = g_strdup_printf ("/design_setup/theme[%d]/picture/picture_size/text()", i + 1); + theme->picture_image_size = xml_file_get_node_value (xml, s); + g_free (s); + + s = g_strdup_printf ("/design_setup/theme[%d]/supplemental_files/text()", i + 1); + s2 = xml_file_get_node_value (xml, s); + if (s2) { + theme->supplemental_files = g_strsplit (s2, "\n", -1); + g_free (s2); + } + g_free (s); + } + + xml_parser_free (xml); + return design; } -static int -test_tmpl_files (const gchar *dir, TGallerySetup *setup) + +static gboolean +lookup_image_size (TGalleryDesign *design, const gchar *image_size_name) +{ + GList *l; + TImageSize *image_size; + + g_return_val_if_fail (image_size_name != NULL, FALSE); + g_return_val_if_fail (strlen (image_size_name) > 0, FALSE); + + for (l = g_list_first (design->image_sizes); l; l = g_list_next (l)) { + image_size = l->data; + g_assert (image_size != NULL); + if (image_size->name == NULL || strlen (image_size->name) == 0) { + fprintf (stderr, "design validation warning: image size %p defined with no name\n", image_size); + continue; + } + if (image_size->landscape_width <= 0 || image_size->landscape_height <= 0 || + image_size->portrait_width <= 0 || image_size->portrait_height <= 0) { + fprintf (stderr, "design validation warning: image size %s defined with zero sized element\n", image_size->name); + continue; + } + if (g_ascii_strcasecmp (image_size_name, image_size->name) == 0) + return TRUE; + } + + return FALSE; +} + +/* + * validate_design_setup: validate design.xml file setup + */ +gboolean +validate_design_setup (TGalleryDesign *design) { - return test_tmpl_access (dir, setup->template_album) | - test_tmpl_access (dir, setup->template_photo) | - test_tmpl_access (dir, setup->template_index); + GList *l; + TGalleryDesignTheme *theme; + + /* validate sizes */ + if (g_list_length (design->image_sizes) == 0) { + fprintf (stderr, "design validation error: no image size defined\n"); + return FALSE; + } + + /* validate themes */ + if (g_list_length (design->themes) == 0) { + fprintf (stderr, "design validation error: no theme defined\n"); + return FALSE; + } + for (l = g_list_first (design->themes); l; l = g_list_next (l)) { + theme = l->data; + g_assert (theme != NULL); + if (theme->album_image_size && ! lookup_image_size (design, theme->album_image_size)) { + fprintf (stderr, "design validation error: theme-defined image size '%s' not found\n", theme->album_image_size); + return FALSE; + } + if (theme->picture_image_size == NULL || strlen (theme->picture_image_size) == 0) { + fprintf (stderr, "design validation error: theme does not define mandatory picture size argument\n"); + return FALSE; + } + if (! lookup_image_size (design, theme->picture_image_size)) { + fprintf (stderr, "design validation error: theme-defined image size '%s' not found\n", theme->picture_image_size); + return FALSE; + } + } + + return TRUE; } + /* - * find_templates_directory: absolute/relative path checks, trying to find templates directory - * - returned string should be freed + * find_design_directory: try to find design templates directory + * - returned string should be freed */ gchar * -find_templates_directory (TGallerySetup *setup) +find_design_directory (TGallerySetup *setup) { gchar *base_dir; - gchar *pth; + gchar *base_design_dir; + gchar *pth = NULL; - if (IS_DIR_SEP (*setup->templates_path)) { - if (! test_tmpl_files (setup->templates_path, setup)) - return g_strdup (setup->templates_path); + if (IS_DIR_SEP (*setup->design_setup_file)) { + pth = g_path_get_dirname (setup->design_setup_file); + if (g_access (pth, R_OK)) + return pth; } else { base_dir = g_path_get_dirname (setup->setup_xml_path); - pth = g_build_path (G_DIR_SEPARATOR_S, base_dir, setup->templates_path, NULL); + base_design_dir = g_path_get_dirname (setup->design_setup_file); + pth = g_build_path (G_DIR_SEPARATOR_S, base_dir, base_design_dir, NULL); g_free (base_dir); + g_free (base_design_dir); - if (! test_tmpl_files (pth, setup)) + if (g_access (pth, R_OK) == 0) return pth; } - log_error ("Couldn't find proper templates directory (tried '%s')\n", setup->templates_path); + log_error ("Couldn't find proper design templates directory (tried '%s')\n", pth); + g_free (pth); return NULL; } @@ -218,31 +355,64 @@ void free_setup_data (TGallerySetup *setup) { if (setup) { - g_free (setup->real_templates_dir); g_free (setup->setup_xml_path); - g_free (setup->templates_path); - g_free (setup->template_index); - g_free (setup->template_album); - g_free (setup->template_photo); - g_strfreev (setup->template_files); - g_free (setup->index_file_name); - g_free (setup->footer); + g_free (setup->design_setup_file); + g_free (setup->border_style); g_free (setup->meta_author); g_free (setup->meta_author_email); g_free (setup->meta_description); g_free (setup->meta_keywords); - g_free (setup->border_style); g_free (setup->site_title); g_free (setup->add_copyright); g_free (setup->favicon_file); g_free (setup->favicon_type); - g_free (setup->thumbnail_dir); - g_free (setup->img_big_dir); - g_free (setup->img_orig_dir); - g_free (setup->thumbnail_name_format); g_free (setup->feed_filename); g_free (setup->feed_title); g_free (setup->feed_base_url); + g_free (setup->footer); + free_design_setup_data (setup->design); g_free (setup); } } + +static void +free_image_size_data (TImageSize *image_size) +{ + if (image_size) { + g_free (image_size->name); + g_free (image_size); + } +} + +static void +free_design_theme_data (TGalleryDesignTheme *theme) +{ + if (theme) { + g_free (theme->index_template); + g_free (theme->index_filename); + g_free (theme->album_template); + g_free (theme->album_filename); + g_free (theme->album_image_size); + g_free (theme->picture_template); + g_free (theme->picture_filename); + g_free (theme->picture_image_size); + g_strfreev (theme->supplemental_files); + g_free (theme); + } +} + +/* + * free_design_setup_data: free allocated design setup data + */ +void +free_design_setup_data (TGalleryDesign *design) +{ + if (design) { + g_list_foreach (design->image_sizes, (GFunc) free_image_size_data, NULL); + g_list_free (design->image_sizes); + g_list_foreach (design->themes, (GFunc) free_design_theme_data, NULL); + g_list_free (design->themes); + g_strfreev (design->supplemental_files); + g_free (design); + } +} -- cgit v1.2.3