summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2016-04-13 17:33:50 +0100
committerRichard Hughes <richard@hughsie.com>2016-04-19 13:39:11 +0100
commit0daa0097cb97557f3b1887450490da958b3418f1 (patch)
tree8e6e5b18b09d9301933d3b377adb9ea9de645db0
parentc0081a38f73d3fa11de15431b418a3119999e88d (diff)
downloadappstream-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.c45
-rw-r--r--libappstream-glib/as-image.h5
-rw-r--r--libappstream-glib/as-screenshot.c78
-rw-r--r--libappstream-glib/as-screenshot.h8
-rw-r--r--libappstream-glib/as-self-test.c28
-rw-r--r--libappstream-glib/as-utils-private.h4
-rw-r--r--libappstream-glib/as-utils.c70
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
*