diff options
author | Richard Hughes <richard@hughsie.com> | 2016-04-13 17:33:50 +0100 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2016-04-19 13:39:11 +0100 |
commit | 0daa0097cb97557f3b1887450490da958b3418f1 (patch) | |
tree | 8e6e5b18b09d9301933d3b377adb9ea9de645db0 | |
parent | c0081a38f73d3fa11de15431b418a3119999e88d (diff) | |
download | appstream-glib-0daa0097cb97557f3b1887450490da958b3418f1.tar.gz |
Add as_screenshot_get_image_for_locale()
The AppStream specification has recently added the ability to have translated
screenshot images. To support this add new methods to restrict the AsImage
selection to compatible locales.
-rw-r--r-- | libappstream-glib/as-image.c | 45 | ||||
-rw-r--r-- | libappstream-glib/as-image.h | 5 | ||||
-rw-r--r-- | libappstream-glib/as-screenshot.c | 78 | ||||
-rw-r--r-- | libappstream-glib/as-screenshot.h | 8 | ||||
-rw-r--r-- | libappstream-glib/as-self-test.c | 28 | ||||
-rw-r--r-- | libappstream-glib/as-utils-private.h | 4 | ||||
-rw-r--r-- | libappstream-glib/as-utils.c | 70 |
7 files changed, 224 insertions, 14 deletions
diff --git a/libappstream-glib/as-image.c b/libappstream-glib/as-image.c index f59d13f..43abd39 100644 --- a/libappstream-glib/as-image.c +++ b/libappstream-glib/as-image.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * Copyright (C) 2014 Richard Hughes <richard@hughsie.com> + * Copyright (C) 2014-2016 Richard Hughes <richard@hughsie.com> * * Licensed under the GNU Lesser General Public License Version 2.1 * @@ -42,6 +42,7 @@ typedef struct { AsImageKind kind; + gchar *locale; gchar *url; gchar *md5; gchar *basename; @@ -68,6 +69,7 @@ as_image_finalize (GObject *object) g_free (priv->url); g_free (priv->md5); g_free (priv->basename); + g_free (priv->locale); G_OBJECT_CLASS (as_image_parent_class)->finalize (object); } @@ -166,6 +168,23 @@ as_image_get_basename (AsImage *image) } /** + * as_image_get_locale: + * @image: a #AsImage instance. + * + * Gets the locale of the image. + * + * Returns: locale, or %NULL + * + * Since: 0.5.14 + **/ +const gchar * +as_image_get_locale (AsImage *image) +{ + AsImagePrivate *priv = GET_PRIVATE (image); + return priv->locale; +} + +/** * as_image_get_md5: * @image: a #AsImage instance. * @@ -285,6 +304,23 @@ as_image_set_basename (AsImage *image, const gchar *basename) } /** + * as_image_set_locale: + * @image: a #AsImage instance. + * @locale: the new image locale, e.g. "en_GB" or %NULL. + * + * Sets the image locale. + * + * Since: 0.5.14 + **/ +void +as_image_set_locale (AsImage *image, const gchar *locale) +{ + AsImagePrivate *priv = GET_PRIVATE (image); + g_free (priv->locale); + priv->locale = g_strdup (locale); +} + +/** * as_image_set_width: * @image: a #AsImage instance. * @width: the width in pixels. @@ -395,6 +431,8 @@ as_image_node_insert (AsImage *image, GNode *parent, AsNodeContext *ctx) "type", as_image_kind_to_string (priv->kind), NULL); } + if (priv->locale != NULL) + as_node_add_attribute (n, "xml:lang", priv->locale); return n; } @@ -436,6 +474,11 @@ as_image_node_parse (AsImage *image, GNode *node, g_free (priv->url); priv->url = taken; } + taken = as_node_take_attribute (node, "xml:lang"); + if (taken != NULL) { + g_free (priv->locale); + priv->locale = taken; + } return TRUE; } diff --git a/libappstream-glib/as-image.h b/libappstream-glib/as-image.h index 376670d..c0d829c 100644 --- a/libappstream-glib/as-image.h +++ b/libappstream-glib/as-image.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * Copyright (C) 2014 Richard Hughes <richard@hughsie.com> + * Copyright (C) 2014-2016 Richard Hughes <richard@hughsie.com> * * Licensed under the GNU Lesser General Public License Version 2.1 * @@ -142,6 +142,7 @@ const gchar *as_image_kind_to_string (AsImageKind kind); const gchar *as_image_get_url (AsImage *image); const gchar *as_image_get_md5 (AsImage *image); const gchar *as_image_get_basename (AsImage *image); +const gchar *as_image_get_locale (AsImage *image); guint as_image_get_width (AsImage *image); guint as_image_get_height (AsImage *image); AsImageKind as_image_get_kind (AsImage *image); @@ -152,6 +153,8 @@ void as_image_set_url (AsImage *image, const gchar *url); void as_image_set_basename (AsImage *image, const gchar *basename); +void as_image_set_locale (AsImage *image, + const gchar *locale); void as_image_set_width (AsImage *image, guint width); void as_image_set_height (AsImage *image, diff --git a/libappstream-glib/as-screenshot.c b/libappstream-glib/as-screenshot.c index a574e94..9be5061 100644 --- a/libappstream-glib/as-screenshot.c +++ b/libappstream-glib/as-screenshot.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * Copyright (C) 2014 Richard Hughes <richard@hughsie.com> + * Copyright (C) 2014-2016 Richard Hughes <richard@hughsie.com> * * Licensed under the GNU Lesser General Public License Version 2.1 * @@ -168,7 +168,7 @@ as_screenshot_get_priority (AsScreenshot *screenshot) * as_screenshot_get_images: * @screenshot: a #AsScreenshot instance. * - * Gets the image sizes included in the screenshot. + * Gets the images included in the screenshot of all sizes and locales. * * Returns: (element-type AsImage) (transfer none): an array * @@ -182,21 +182,58 @@ as_screenshot_get_images (AsScreenshot *screenshot) } /** - * as_screenshot_get_image: + * as_screenshot_get_images_for_locale: * @screenshot: a #AsScreenshot instance. + * + * Returns all images of all sizes that are compatible with a specific locale. + * + * Returns: (element-type AsImage) (transfer container): an array + * + * Since: 0.5.14 + **/ +GPtrArray * +as_screenshot_get_images_for_locale (AsScreenshot *screenshot, + const gchar *locale) +{ + AsImage *im; + AsScreenshotPrivate *priv = GET_PRIVATE (screenshot); + GPtrArray *array; + guint i; + + /* user wants a specific locale */ + array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + for (i = 0; i < priv->images->len; i++) { + im = g_ptr_array_index (priv->images, i); + if (!as_utils_locale_is_compatible (as_image_get_locale (im), + locale)) + continue; + g_ptr_array_add (array, g_object_ref (im)); + } + return array; +} + +/** + * as_screenshot_get_image_for_locale: + * @screenshot: a #AsScreenshot instance. + * @locale: locale, or %NULL * @width: target width * @height: target height * - * Gets the AsImage closest to the target size. The #AsImage may not actually - * be the requested size, and the application may have to pad / rescale the - * image to make it fit. + * Gets the AsImage closest to the target size with the specified locale. + * The #AsImage may not actually be the requested size, and the application may + * have to pad / rescale the image to make it fit. + * + * FIXME: This function assumes the images are ordered in preference order, e.g. + * "en_GB -> en -> NULL" * * Returns: (transfer none): an #AsImage, or %NULL * - * Since: 0.2.2 + * Since: 0.5.14 **/ AsImage * -as_screenshot_get_image (AsScreenshot *screenshot, guint width, guint height) +as_screenshot_get_image_for_locale (AsScreenshot *screenshot, + const gchar *locale, + guint width, guint height) { AsImage *im; AsImage *im_best = NULL; @@ -209,6 +246,8 @@ as_screenshot_get_image (AsScreenshot *screenshot, guint width, guint height) for (i = 0; i < priv->images->len; i++) { im = g_ptr_array_index (priv->images, i); + if (!as_utils_locale_is_compatible (as_image_get_locale (im), locale)) + continue; tmp = ABS ((gint64) (width * height) - (gint64) (as_image_get_width (im) * as_image_get_height (im))); if (tmp < best_size) { @@ -220,6 +259,29 @@ as_screenshot_get_image (AsScreenshot *screenshot, guint width, guint height) } /** + * as_screenshot_get_image: + * @screenshot: a #AsScreenshot instance. + * @width: target width + * @height: target height + * + * Gets the AsImage closest to the target size. The #AsImage may not actually + * be the requested size, and the application may have to pad / rescale the + * image to make it fit. + * + * Returns: (transfer none): an #AsImage, or %NULL + * + * Since: 0.2.2 + **/ +AsImage * +as_screenshot_get_image (AsScreenshot *screenshot, guint width, guint height) +{ + return as_screenshot_get_image_for_locale (screenshot, + NULL, /* locale */ + width, + height); +} + +/** * as_screenshot_get_source: * @screenshot: a #AsScreenshot instance. * diff --git a/libappstream-glib/as-screenshot.h b/libappstream-glib/as-screenshot.h index 74a39c7..a56be90 100644 --- a/libappstream-glib/as-screenshot.h +++ b/libappstream-glib/as-screenshot.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * Copyright (C) 2014 Richard Hughes <richard@hughsie.com> + * Copyright (C) 2014-2016 Richard Hughes <richard@hughsie.com> * * Licensed under the GNU Lesser General Public License Version 2.1 * @@ -77,9 +77,15 @@ gint as_screenshot_get_priority (AsScreenshot *screenshot); const gchar *as_screenshot_get_caption (AsScreenshot *screenshot, const gchar *locale); GPtrArray *as_screenshot_get_images (AsScreenshot *screenshot); +GPtrArray *as_screenshot_get_images_for_locale (AsScreenshot *screenshot, + const gchar *locale); AsImage *as_screenshot_get_image (AsScreenshot *screenshot, guint width, guint height); +AsImage *as_screenshot_get_image_for_locale (AsScreenshot *screenshot, + const gchar *locale, + guint width, + guint height); AsImage *as_screenshot_get_source (AsScreenshot *screenshot); /* setters */ diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c index 453884c..d463983 100644 --- a/libappstream-glib/as-self-test.c +++ b/libappstream-glib/as-self-test.c @@ -1114,7 +1114,7 @@ as_test_image_func (void) AsNode *root; GString *xml; const gchar *src = - "<image type=\"thumbnail\" height=\"12\" width=\"34\">" + "<image xml:lang=\"en_GB\" type=\"thumbnail\" height=\"12\" width=\"34\">" "http://www.hughsie.com/a.jpg</image>"; gboolean ret; g_autofree AsNodeContext *ctx = NULL; @@ -1140,6 +1140,7 @@ as_test_image_func (void) g_assert_cmpint (as_image_get_kind (image), ==, AS_IMAGE_KIND_THUMBNAIL); g_assert_cmpint (as_image_get_height (image), ==, 12); g_assert_cmpint (as_image_get_width (image), ==, 34); + g_assert_cmpstr (as_image_get_locale (image), ==, "en_GB"); g_assert_cmpstr (as_image_get_url (image), ==, "http://www.hughsie.com/a.jpg"); /* back to node */ @@ -4706,6 +4707,30 @@ as_test_utils_string_replace_func (void) } static void +as_test_utils_locale_compat_func (void) +{ + /* empty */ + g_assert (as_utils_locale_is_compatible (NULL, NULL)); + + /* same */ + g_assert (as_utils_locale_is_compatible ("en_GB", "en_GB")); + + /* forward and reverse compatible */ + g_assert (as_utils_locale_is_compatible ("en_GB", "en")); + g_assert (as_utils_locale_is_compatible ("en", "en_GB")); + + /* different language and locale */ + g_assert (!as_utils_locale_is_compatible ("en_GB", "fr_FR")); + + /* politics */ + g_assert (!as_utils_locale_is_compatible ("zh_CN", "zh_TW")); + + /* never going to match system locale or language */ + g_assert (!as_utils_locale_is_compatible ("xx_XX", NULL)); + g_assert (!as_utils_locale_is_compatible (NULL, "xx_XX")); +} + +static void as_test_markup_import_html (void) { const gchar *input; @@ -4778,6 +4803,7 @@ main (int argc, char **argv) g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL); /* tests go here */ + g_test_add_func ("/AppStream/utils{locale-compat}", as_test_utils_locale_compat_func); g_test_add_func ("/AppStream/utils{string-replace}", as_test_utils_string_replace_func); g_test_add_func ("/AppStream/tag", as_test_tag_func); g_test_add_func ("/AppStream/provide", as_test_provide_func); diff --git a/libappstream-glib/as-utils-private.h b/libappstream-glib/as-utils-private.h index 19294be..0ea7e5a 100644 --- a/libappstream-glib/as-utils-private.h +++ b/libappstream-glib/as-utils-private.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * Copyright (C) 2014 Richard Hughes <richard@hughsie.com> + * Copyright (C) 2014-2016 Richard Hughes <richard@hughsie.com> * * Licensed under the GNU Lesser General Public License Version 2.1 * @@ -42,6 +42,8 @@ void as_pixbuf_blur (GdkPixbuf *src, gint iterations); const gchar *as_ptr_array_find_string (GPtrArray *array, const gchar *value); +gboolean as_utils_locale_is_compatible (const gchar *locale1, + const gchar *locale2); G_END_DECLS diff --git a/libappstream-glib/as-utils.c b/libappstream-glib/as-utils.c index 1f1140c..7e19ea6 100644 --- a/libappstream-glib/as-utils.c +++ b/libappstream-glib/as-utils.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * Copyright (C) 2014 Richard Hughes <richard@hughsie.com> + * Copyright (C) 2014-2016 Richard Hughes <richard@hughsie.com> * Copyright (C) 2011 Paolo Bacchilega <paobac@src.gnome.org> * * Licensed under the GNU Lesser General Public License Version 2.1 @@ -96,6 +96,74 @@ as_hash_lookup_by_locale (GHashTable *hash, const gchar *locale) } /** + * as_utils_locale_to_language: + **/ +static gchar * +as_utils_locale_to_language (const gchar *locale) +{ + gchar *tmp; + gchar *country_code; + + /* invalid */ + if (locale == NULL) + return NULL; + + /* return the part before the _ (not always 2 chars!) */ + country_code = g_strdup (locale); + tmp = g_strstr_len (country_code, -1, "_"); + if (tmp != NULL) + *tmp = '\0'; + return country_code; +} + +/** + * as_utils_locale_is_compatible: + * @locale1: a locale string, or %NULL + * @locale2: a locale string, or %NULL + * + * Calculates if one locale is compatible with another. + * When doing the calculation the locale and language code is taken into + * account if possible. + * + * Returns: %TRUE if the locale is compatible. + * + * Since: 0.5.14 + **/ +gboolean +as_utils_locale_is_compatible (const gchar *locale1, const gchar *locale2) +{ + g_autofree gchar *lang1 = as_utils_locale_to_language (locale1); + g_autofree gchar *lang2 = as_utils_locale_to_language (locale2); + + /* we've specified "don't care" and locale unspecified */ + if (locale1 == NULL && locale2 == NULL) + return TRUE; + + /* forward */ + if (locale1 == NULL && locale2 != NULL) { + const gchar *const *locales = g_get_language_names (); + return g_strv_contains (locales, locale2) || + g_strv_contains (locales, lang2); + } + + /* backwards */ + if (locale1 != NULL && locale2 == NULL) { + const gchar *const *locales = g_get_language_names (); + return g_strv_contains (locales, locale1) || + g_strv_contains (locales, lang1); + } + + /* both specified */ + if (g_strcmp0 (locale1, locale2) == 0) + return TRUE; + if (g_strcmp0 (locale1, lang2) == 0) + return TRUE; + if (g_strcmp0 (lang1, locale2) == 0) + return TRUE; + return FALSE; +} + +/** * as_utils_is_stock_icon_name: * @name: an icon name * |