diff options
Diffstat (limited to 'libappstream-glib')
-rw-r--r-- | libappstream-glib/Makefile.am | 5 | ||||
-rw-r--r-- | libappstream-glib/appstream-glib.h | 1 | ||||
-rw-r--r-- | libappstream-glib/as-app.c | 90 | ||||
-rw-r--r-- | libappstream-glib/as-app.h | 6 | ||||
-rw-r--r-- | libappstream-glib/as-review-private.h | 48 | ||||
-rw-r--r-- | libappstream-glib/as-review.c | 1068 | ||||
-rw-r--r-- | libappstream-glib/as-review.h | 124 | ||||
-rw-r--r-- | libappstream-glib/as-self-test.c | 70 | ||||
-rw-r--r-- | libappstream-glib/as-tag.c | 5 | ||||
-rw-r--r-- | libappstream-glib/as-tag.gperf | 5 | ||||
-rw-r--r-- | libappstream-glib/as-tag.h | 10 |
11 files changed, 1431 insertions, 1 deletions
diff --git a/libappstream-glib/Makefile.am b/libappstream-glib/Makefile.am index f58b826..39a2637 100644 --- a/libappstream-glib/Makefile.am +++ b/libappstream-glib/Makefile.am @@ -83,6 +83,7 @@ libappstream_glib_include_HEADERS = \ as-profile.h \ as-provide.h \ as-release.h \ + as-review.h \ as-screenshot.h \ as-store.h \ as-tag.h \ @@ -123,6 +124,8 @@ libappstream_glib_la_SOURCES = \ as-provide-private.h \ as-release.c \ as-release-private.h \ + as-review.c \ + as-review-private.h \ as-resources.c \ as-resources.h \ as-screenshot.c \ @@ -217,6 +220,8 @@ introspection_sources = \ as-provide.h \ as-release.c \ as-release.h \ + as-review.c \ + as-review.h \ as-screenshot.c \ as-screenshot.h \ as-store.c \ diff --git a/libappstream-glib/appstream-glib.h b/libappstream-glib/appstream-glib.h index ab5e631..55962dd 100644 --- a/libappstream-glib/appstream-glib.h +++ b/libappstream-glib/appstream-glib.h @@ -39,6 +39,7 @@ #include <as-profile.h> #include <as-provide.h> #include <as-release.h> +#include <as-review.h> #include <as-screenshot.h> #include <as-store.h> #include <as-tag.h> diff --git a/libappstream-glib/as-app.c b/libappstream-glib/as-app.c index e4d6531..1233277 100644 --- a/libappstream-glib/as-app.c +++ b/libappstream-glib/as-app.c @@ -45,6 +45,7 @@ #include "as-node-private.h" #include "as-provide-private.h" #include "as-release-private.h" +#include "as-review-private.h" #include "as-screenshot-private.h" #include "as-stemmer.h" #include "as-tag.h" @@ -78,6 +79,7 @@ typedef struct GPtrArray *releases; /* of AsRelease */ GPtrArray *provides; /* of AsProvide */ GPtrArray *screenshots; /* of AsScreenshot */ + GPtrArray *reviews; /* of AsReview */ GPtrArray *content_ratings; /* of AsContentRating */ GPtrArray *icons; /* of AsIcon */ GPtrArray *bundles; /* of AsBundle */ @@ -389,6 +391,7 @@ as_app_finalize (GObject *object) g_ptr_array_unref (priv->releases); g_ptr_array_unref (priv->provides); g_ptr_array_unref (priv->screenshots); + g_ptr_array_unref (priv->reviews); g_ptr_array_unref (priv->icons); g_ptr_array_unref (priv->bundles); g_ptr_array_unref (priv->translations); @@ -417,6 +420,7 @@ as_app_init (AsApp *app) priv->releases = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); priv->provides = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); priv->screenshots = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + priv->reviews = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); priv->icons = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); priv->bundles = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); priv->translations = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); @@ -839,6 +843,23 @@ as_app_get_screenshots (AsApp *app) } /** + * as_app_get_reviews: + * @app: a #AsApp instance. + * + * Gets any reviews the application has defined. + * + * Returns: (element-type AsScreenshot) (transfer none): an array + * + * Since: 0.5.18 + **/ +GPtrArray * +as_app_get_reviews (AsApp *app) +{ + AsAppPrivate *priv = GET_PRIVATE (app); + return priv->reviews; +} + +/** * as_app_get_content_ratings: * @app: a #AsApp instance. * @@ -2548,6 +2569,33 @@ as_app_add_screenshot (AsApp *app, AsScreenshot *screenshot) } /** + * as_app_add_review: + * @app: a #AsApp instance. + * @review: a #AsReview instance. + * + * Adds a review to an application. + * + * Since: 0.5.18 + **/ +void +as_app_add_review (AsApp *app, AsReview *review) +{ + AsAppPrivate *priv = GET_PRIVATE (app); + AsReview *review_tmp; + guint i; + + /* handle untrusted */ + if ((priv->trust_flags & AS_APP_TRUST_FLAG_CHECK_DUPLICATES) > 0) { + for (i = 0; i < priv->reviews->len; i++) { + review_tmp = g_ptr_array_index (priv->reviews, i); + if (as_review_equal (review_tmp, review)) + return; + } + } + g_ptr_array_add (priv->reviews, g_object_ref (review)); +} + +/** * as_app_add_content_rating: * @app: a #AsApp instance. * @content_rating: a #AsContentRating instance. @@ -2995,6 +3043,7 @@ as_app_subsume_private (AsApp *app, AsApp *donor, AsAppSubsumeFlags flags) AsAppPrivate *papp = GET_PRIVATE (app); AsBundle *bundle; AsTranslation *translation; + AsReview *review; AsScreenshot *ss; AsProvide *pr; const gchar *tmp; @@ -3084,6 +3133,12 @@ as_app_subsume_private (AsApp *app, AsApp *donor, AsAppSubsumeFlags flags) as_app_add_screenshot (app, ss); } + /* reviews */ + for (i = 0; i < priv->reviews->len; i++) { + review = g_ptr_array_index (priv->reviews, i); + as_app_add_review (app, review); + } + /* content_ratings */ for (i = 0; i < priv->content_ratings->len; i++) { AsContentRating *content_rating; @@ -3544,6 +3599,16 @@ as_app_node_insert (AsApp *app, GNode *parent, AsNodeContext *ctx) } } + /* <reviews> */ + if (priv->reviews->len > 0) { + AsReview *review; + node_tmp = as_node_insert (node_app, "reviews", NULL, 0, NULL); + for (i = 0; i < priv->reviews->len; i++) { + review = g_ptr_array_index (priv->reviews, i); + as_review_node_insert (review, node_tmp, ctx); + } + } + /* <content_ratings> */ if (priv->content_ratings->len > 0) { for (i = 0; i < priv->content_ratings->len; i++) { @@ -3923,6 +3988,21 @@ as_app_node_parse_child (AsApp *app, GNode *n, AsAppParseFlags flags, } break; + /* <reviews> */ + case AS_TAG_REVIEWS: + if (!(flags & AS_APP_PARSE_FLAG_APPEND_DATA)) + g_ptr_array_set_size (priv->reviews, 0); + for (c = n->children; c != NULL; c = c->next) { + g_autoptr(AsReview) review = NULL; + if (as_node_get_tag (c) != AS_TAG_REVIEW) + continue; + review = as_review_new (); + if (!as_review_node_parse (review, c, ctx, error)) + return FALSE; + as_app_add_review (app, review); + } + break; + /* <content_ratings> */ case AS_TAG_CONTENT_RATING: { @@ -4328,6 +4408,16 @@ as_app_node_parse_dep11 (AsApp *app, GNode *node, } continue; } + if (g_strcmp0 (tmp, "Reviews") == 0) { + for (c = n->children; c != NULL; c = c->next) { + g_autoptr(AsReview) review = NULL; + review = as_review_new (); + if (!as_review_node_parse_dep11 (review, c, ctx, error)) + return FALSE; + as_app_add_review (app, review); + } + continue; + } if (g_strcmp0 (tmp, "Extends") == 0) { for (c = n->children; c != NULL; c = c->next) as_app_add_extends (app, as_yaml_node_get_key (c)); diff --git a/libappstream-glib/as-app.h b/libappstream-glib/as-app.h index f027924..d642333 100644 --- a/libappstream-glib/as-app.h +++ b/libappstream-glib/as-app.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * Copyright (C) 2014-2015 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 * @@ -34,6 +34,7 @@ #include "as-provide.h" #include "as-release.h" #include "as-screenshot.h" +#include "as-review.h" #include "as-content-rating.h" #include "as-translation.h" @@ -305,6 +306,7 @@ GPtrArray *as_app_get_architectures (AsApp *app); GPtrArray *as_app_get_releases (AsApp *app); GPtrArray *as_app_get_provides (AsApp *app); GPtrArray *as_app_get_screenshots (AsApp *app); +GPtrArray *as_app_get_reviews (AsApp *app); GPtrArray *as_app_get_content_ratings (AsApp *app); GPtrArray *as_app_get_icons (AsApp *app); GPtrArray *as_app_get_bundles (AsApp *app); @@ -420,6 +422,8 @@ void as_app_add_provide (AsApp *app, AsProvide *provide); void as_app_add_screenshot (AsApp *app, AsScreenshot *screenshot); +void as_app_add_review (AsApp *app, + AsReview *review); void as_app_add_content_rating (AsApp *app, AsContentRating *content_rating); void as_app_add_icon (AsApp *app, diff --git a/libappstream-glib/as-review-private.h b/libappstream-glib/as-review-private.h new file mode 100644 index 0000000..a8322ab --- /dev/null +++ b/libappstream-glib/as-review-private.h @@ -0,0 +1,48 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2016 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library 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 2.1 of the License, or (at your option) any later version. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if !defined (__APPSTREAM_GLIB_PRIVATE_H) && !defined (AS_COMPILATION) +#error "Only <appstream-glib.h> can be included directly." +#endif + +#ifndef __AS_REVIEW_PRIVATE_H +#define __AS_REVIEW_PRIVATE_H + +#include "as-review.h" +#include "as-node-private.h" + +G_BEGIN_DECLS + +GNode *as_review_node_insert (AsReview *review, + GNode *parent, + AsNodeContext *ctx); +gboolean as_review_node_parse (AsReview *review, + GNode *node, + AsNodeContext *ctx, + GError **error); +gboolean as_review_node_parse_dep11 (AsReview *review, + GNode *node, + AsNodeContext *ctx, + GError **error); + +G_END_DECLS + +#endif /* __AS_REVIEW_PRIVATE_H */ diff --git a/libappstream-glib/as-review.c b/libappstream-glib/as-review.c new file mode 100644 index 0000000..ed739da --- /dev/null +++ b/libappstream-glib/as-review.c @@ -0,0 +1,1068 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2016 Canonical Ltd. + * Copyright (C) 2016 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library 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 2.1 of the License, or (at your option) any later version. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * SECTION:as-review + * @title: AsReview + * @include: appstream-glib.h + * @stability: Stable + * @short_description: An application user review + * + * This object represents a user-submitted application review. + * + * Since: 0.5.18 + **/ + +#include "config.h" + +#include "as-review-private.h" +#include "as-node-private.h" +#include "as-utils-private.h" +#include "as-yaml.h" + +typedef struct +{ + AsReviewFlags flags; + gchar *id; + gchar *summary; + gchar *description; + gchar *locale; + gint karma; + gint priority; + gint rating; + gchar *version; + gchar *reviewer_id; + gchar *reviewer_name; + GDateTime *date; + GHashTable *metadata; +} AsReviewPrivate; + +enum { + PROP_0, + PROP_ID, + PROP_KARMA, + PROP_SUMMARY, + PROP_DESCRIPTION, + PROP_LOCALE, + PROP_RATING, + PROP_VERSION, + PROP_REVIEWER_ID, + PROP_REVIEWER_NAME, + PROP_DATE, + PROP_FLAGS, + PROP_LAST +}; + +G_DEFINE_TYPE_WITH_PRIVATE (AsReview, as_review, G_TYPE_OBJECT) + +#define GET_PRIVATE(o) (as_review_get_instance_private (o)) + +static void +as_review_finalize (GObject *object) +{ + AsReview *review = AS_REVIEW (object); + AsReviewPrivate *priv = GET_PRIVATE (review); + + g_free (priv->id); + g_free (priv->summary); + g_free (priv->description); + g_free (priv->locale); + g_free (priv->reviewer_id); + g_free (priv->reviewer_name); + g_hash_table_unref (priv->metadata); + if (priv->date != NULL) + g_date_time_unref (priv->date); + + G_OBJECT_CLASS (as_review_parent_class)->finalize (object); +} + +static void +as_review_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + AsReview *review = AS_REVIEW (object); + AsReviewPrivate *priv = GET_PRIVATE (review); + + switch (prop_id) { + case PROP_KARMA: + g_value_set_int (value, priv->karma); + break; + case PROP_ID: + g_value_set_string (value, priv->id); + break; + case PROP_SUMMARY: + g_value_set_string (value, priv->summary); + break; + case PROP_DESCRIPTION: + g_value_set_string (value, priv->description); + break; + case PROP_LOCALE: + g_value_set_string (value, priv->locale); + break; + case PROP_RATING: + g_value_set_int (value, priv->rating); + break; + case PROP_FLAGS: + g_value_set_uint64 (value, priv->flags); + break; + case PROP_VERSION: + g_value_set_string (value, priv->version); + break; + case PROP_REVIEWER_ID: + g_value_set_string (value, priv->reviewer_id); + break; + case PROP_REVIEWER_NAME: + g_value_set_string (value, priv->reviewer_name); + break; + case PROP_DATE: + g_value_set_object (value, priv->date); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +as_review_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + AsReview *review = AS_REVIEW (object); + + switch (prop_id) { + case PROP_KARMA: + as_review_set_karma (review, g_value_get_int (value)); + break; + case PROP_ID: + as_review_set_id (review, g_value_get_string (value)); + break; + case PROP_SUMMARY: + as_review_set_summary (review, g_value_get_string (value)); + break; + case PROP_DESCRIPTION: + as_review_set_description (review, g_value_get_string (value)); + break; + case PROP_LOCALE: + as_review_set_locale (review, g_value_get_string (value)); + break; + case PROP_RATING: + as_review_set_rating (review, g_value_get_int (value)); + break; + case PROP_FLAGS: + as_review_set_flags (review, g_value_get_uint64 (value)); + break; + case PROP_VERSION: + as_review_set_version (review, g_value_get_string (value)); + break; + case PROP_REVIEWER_ID: + as_review_set_reviewer_id (review, g_value_get_string (value)); + break; + case PROP_REVIEWER_NAME: + as_review_set_reviewer_name (review, g_value_get_string (value)); + break; + case PROP_DATE: + as_review_set_date (review, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +as_review_class_init (AsReviewClass *klass) +{ + GParamSpec *pspec; + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->finalize = as_review_finalize; + object_class->get_property = as_review_get_property; + object_class->set_property = as_review_set_property; + + /** + * AsReview:karma: + * + * Since: 0.5.18 + **/ + pspec = g_param_spec_int ("karma", NULL, NULL, + G_MININT, G_MAXINT, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property (object_class, PROP_KARMA, pspec); + + /** + * AsReview:id: + * + * Since: 0.5.18 + **/ + pspec = g_param_spec_string ("id", NULL, NULL, + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property (object_class, PROP_ID, pspec); + + /** + * AsReview:summary: + * + * Since: 0.5.18 + **/ + pspec = g_param_spec_string ("summary", NULL, NULL, + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property (object_class, PROP_SUMMARY, pspec); + + /** + * AsReview:description: + * + * Since: 0.5.18 + **/ + pspec = g_param_spec_string ("description", NULL, NULL, + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property (object_class, PROP_DESCRIPTION, pspec); + + /** + * AsReview:locale: + * + * Since: 0.5.18 + **/ + pspec = g_param_spec_string ("locale", NULL, NULL, + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property (object_class, PROP_LOCALE, pspec); + + /** + * AsReview:rating: + * + * Since: 0.5.18 + **/ + pspec = g_param_spec_int ("rating", NULL, NULL, + -1, 100, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property (object_class, PROP_RATING, pspec); + + /** + * AsReview:flags: + * + * Since: 0.5.18 + **/ + pspec = g_param_spec_uint64 ("flags", NULL, NULL, + AS_REVIEW_FLAG_NONE, + AS_REVIEW_FLAG_LAST, + AS_REVIEW_FLAG_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property (object_class, PROP_FLAGS, pspec); + + /** + * AsReview:version: + * + * Since: 0.5.18 + **/ + pspec = g_param_spec_string ("version", NULL, NULL, + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property (object_class, PROP_VERSION, pspec); + + /** + * AsReview:reviewer-id: + * + * Since: 0.5.18 + **/ + pspec = g_param_spec_string ("reviewer-id", NULL, NULL, + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property (object_class, PROP_REVIEWER_ID, pspec); + + /** + * AsReview:reviewer-name: + * + * Since: 0.5.18 + **/ + pspec = g_param_spec_string ("reviewer-name", NULL, NULL, + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property (object_class, PROP_REVIEWER_NAME, pspec); + + /** + * AsReview:date: + * + * Since: 0.5.18 + **/ + pspec = g_param_spec_object ("date", NULL, NULL, + AS_TYPE_REVIEW, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property (object_class, PROP_DATE, pspec); +} + +static void +as_review_init (AsReview *review) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + priv->metadata = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_free); +} + +/** + * as_review_get_karma: + * @review: a #AsReview + * + * Gets the karma for the review, where positive numbers indicate + * more positive feedback for the review. + * + * Returns: the karma value, or 0 for unset. + * + * Since: 0.5.18 + **/ +gint +as_review_get_karma (AsReview *review) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_val_if_fail (AS_IS_REVIEW (review), 0); + return priv->karma; +} + +/** + * as_review_set_karma: + * @review: a #AsReview + * @karma: a karma value + * + * Sets the karma for the review, where positive numbers indicate + * more positive feedback for the review. + * + * Karma can be positive or negative, or 0 for unset. + * + * Since: 0.5.18 + **/ +void +as_review_set_karma (AsReview *review, gint karma) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_if_fail (AS_IS_REVIEW (review)); + priv->karma = karma; +} + +/** + * as_review_get_priority: + * @review: a #AsReview + * + * This allows the UI to sort reviews into the correct order. + * Higher numbers indicate a more important or relevant review. + * + * Returns: the review priority, or 0 for unset. + * + * Since: 0.5.18 + **/ +gint +as_review_get_priority (AsReview *review) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_val_if_fail (AS_IS_REVIEW (review), 0); + return priv->priority; +} + +/** + * as_review_set_priority: + * @review: a #AsReview + * @priority: a priority value + * + * Sets the priority for the review, where positive numbers indicate + * a better review for the specific user. + * + * Since: 0.5.18 + **/ +void +as_review_set_priority (AsReview *review, gint priority) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_if_fail (AS_IS_REVIEW (review)); + priv->priority = priority; +} + +/** + * as_review_get_id: + * @review: a #AsReview + * + * Gets the review id. + * + * Returns: the review identifier, e.g. "deadbeef" + * + * Since: 0.5.18 + **/ +const gchar * +as_review_get_id (AsReview *review) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_val_if_fail (AS_IS_REVIEW (review), NULL); + return priv->id; +} + +/** + * as_review_get_summary: + * @review: a #AsReview + * + * Gets the review summary. + * + * Returns: the one-line summary, e.g. "Awesome application" + * + * Since: 0.5.18 + **/ +const gchar * +as_review_get_summary (AsReview *review) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_val_if_fail (AS_IS_REVIEW (review), NULL); + return priv->summary; +} + +/** + * as_review_set_id: + * @review: a #AsReview + * @id: review identifier, e.g. "deadbeef" + * + * Sets the review identifier that is unique to each review. + * + * Since: 0.5.18 + **/ +void +as_review_set_id (AsReview *review, const gchar *id) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_if_fail (AS_IS_REVIEW (review)); + g_free (priv->id); + priv->id = g_strdup (id); +} + +/** + * as_review_set_summary: + * @review: a #AsReview + * @summary: a one-line summary, e.g. "Awesome application" + * + * Sets the one-line summary that may be displayed in bold. + * + * Since: 0.5.18 + **/ +void +as_review_set_summary (AsReview *review, const gchar *summary) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_if_fail (AS_IS_REVIEW (review)); + g_free (priv->summary); + priv->summary = g_strdup (summary); +} + +/** + * as_review_get_description: + * @review: a #AsReview + * + * Gets the multi-line review text that forms the body of the review. + * + * Returns: the string, or %NULL + * + * Since: 0.5.18 + **/ +const gchar * +as_review_get_description (AsReview *review) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_val_if_fail (AS_IS_REVIEW (review), NULL); + return priv->description; +} + +/** + * as_review_set_description: + * @review: a #AsReview + * @description: multi-line description + * + * Sets the multi-line review text that forms the body of the review. + * + * Since: 0.5.18 + **/ +void +as_review_set_description (AsReview *review, const gchar *description) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_if_fail (AS_IS_REVIEW (review)); + g_free (priv->description); + priv->description = g_strdup (description); +} + +/** + * as_review_get_locale: + * @review: a #AsReview + * + * Gets the locale for the review. + * + * Returns: the string, or %NULL + * + * Since: 0.5.18 + **/ +const gchar * +as_review_get_locale (AsReview *review) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_val_if_fail (AS_IS_REVIEW (review), NULL); + return priv->locale; +} + +/** + * as_review_set_locale: + * @review: a #AsReview + * @locale: locale, e.g. "en_GB" + * + * Sets the locale for the review. + * + * Since: 0.5.18 + **/ +void +as_review_set_locale (AsReview *review, const gchar *locale) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_if_fail (AS_IS_REVIEW (review)); + g_free (priv->locale); + priv->locale = g_strdup (locale); +} + +/** + * as_review_get_rating: + * @review: a #AsReview + * + * Gets the star rating of the review, where 100 is 5 stars. + * + * Returns: integer as a percentage, or 0 for unset + * + * Since: 0.5.18 + **/ +gint +as_review_get_rating (AsReview *review) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_val_if_fail (AS_IS_REVIEW (review), 0); + return priv->rating; +} + +/** + * as_review_set_rating: + * @review: a #AsReview + * @rating: a integer as a percentage, or 0 for unset + * + * Sets the star rating of the review, where 100 is 5 stars.. + * + * Since: 0.5.18 + **/ +void +as_review_set_rating (AsReview *review, gint rating) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_if_fail (AS_IS_REVIEW (review)); + priv->rating = rating; +} + +/** + * as_review_get_flags: + * @review: a #AsReview + * + * Gets any flags set on the review, for example if the user has already + * voted on the review or if the user wrote the review themselves. + * + * Returns: a #AsReviewFlags, e.g. %AS_REVIEW_FLAG_SELF + * + * Since: 0.5.18 + **/ +AsReviewFlags +as_review_get_flags (AsReview *review) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_val_if_fail (AS_IS_REVIEW (review), 0); + return priv->flags; +} + +/** + * as_review_set_flags: + * @review: a #AsReview + * @flags: a #AsReviewFlags, e.g. %AS_REVIEW_FLAG_SELF + * + * Gets any flags set on the review, for example if the user has already + * voted on the review or if the user wrote the review themselves. + * + * Since: 0.5.18 + **/ +void +as_review_set_flags (AsReview *review, AsReviewFlags flags) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_if_fail (AS_IS_REVIEW (review)); + priv->flags = flags; +} + +/** + * as_review_add_flags: + * @review: a #AsReview + * @flags: a #AsReviewFlags, e.g. %AS_REVIEW_FLAG_SELF + * + * Adds flags to an existing review without replacing the other flags. + * + * Since: 0.5.18 + **/ +void +as_review_add_flags (AsReview *review, AsReviewFlags flags) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_if_fail (AS_IS_REVIEW (review)); + priv->flags |= flags; +} + +/** + * as_review_get_reviewer_id: + * @review: a #AsReview + * + * Gets the name of the reviewer. + * + * Returns: the reviewer ID, e.g. "deadbeef", or %NULL + * + * Since: 0.5.18 + **/ +const gchar * +as_review_get_reviewer_id (AsReview *review) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_val_if_fail (AS_IS_REVIEW (review), NULL); + return priv->reviewer_id; +} + +/** + * as_review_get_reviewer_name: + * @review: a #AsReview + * + * Gets the name of the reviewer. + * + * Returns: the reviewer name, e.g. "David Smith", or %NULL + * + * Since: 0.5.18 + **/ +const gchar * +as_review_get_reviewer_name (AsReview *review) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_val_if_fail (AS_IS_REVIEW (review), NULL); + return priv->reviewer_name; +} + +/** + * as_review_set_reviewer_id: + * @review: a #AsReview + * @reviewer_id: the reviewer ID, e.g. "deadbeef" + * + * Sets the name of the reviewer, which can be left unset. + * + * Since: 0.5.18 + **/ +void +as_review_set_reviewer_id (AsReview *review, const gchar *reviewer_id) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_if_fail (AS_IS_REVIEW (review)); + g_free (priv->reviewer_id); + priv->reviewer_id = g_strdup (reviewer_id); +} + +/** + * as_review_set_reviewer_name: + * @review: a #AsReview + * @reviewer_name: the reviewer name, e.g. "David Smith" + * + * Sets the name of the reviewer, which can be left unset. + * + * Since: 0.5.18 + **/ +void +as_review_set_reviewer_name (AsReview *review, const gchar *reviewer_name) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_if_fail (AS_IS_REVIEW (review)); + g_free (priv->reviewer_name); + priv->reviewer_name = g_strdup (reviewer_name); +} + +/** + * as_review_set_version: + * @review: a #AsReview + * @version: a version string, e.g. "0.1.2" + * + * Sets the version string for the application being reviewed. + * + * Since: 0.5.18 + **/ +void +as_review_set_version (AsReview *review, const gchar *version) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_if_fail (AS_IS_REVIEW (review)); + g_free (priv->version); + priv->version = g_strdup (version); +} + +/** + * as_review_get_version: + * @review: a #AsReview + * + * Gets the version string for the application being reviewed.. + * + * Returns: the version string, e.g. "0.1.2", or %NULL for unset + * + * Since: 0.5.18 + **/ +const gchar * +as_review_get_version (AsReview *review) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_val_if_fail (AS_IS_REVIEW (review), NULL); + return priv->version; +} + +/** + * as_review_get_date: + * @review: a #AsReview + * + * Gets the date the review was originally submitted. + * + * Returns: (transfer none): the #GDateTime, or %NULL for unset + * + * Since: 0.5.18 + **/ +GDateTime * +as_review_get_date (AsReview *review) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_val_if_fail (AS_IS_REVIEW (review), NULL); + return priv->date; +} + +/** + * as_review_set_date: + * @review: a #AsReview + * @date: a #GDateTime, or %NULL + * + * Sets the date the review was originally submitted. + * + * Since: 0.5.18 + **/ +void +as_review_set_date (AsReview *review, GDateTime *date) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_if_fail (AS_IS_REVIEW (review)); + g_clear_pointer (&priv->date, g_date_time_unref); + if (date != NULL) + priv->date = g_date_time_ref (date); +} + +/** + * as_review_get_metadata_item: + * @review: a #AsReview + * @key: a string + * + * Gets some metadata from a review object. + * It is left for the the plugin to use this method as required, but a + * typical use would be to retrieve some secure authentication token. + * + * Returns: A string value, or %NULL for not found + * + * Since: 0.5.18 + **/ +const gchar * +as_review_get_metadata_item (AsReview *review, const gchar *key) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_val_if_fail (AS_IS_REVIEW (review), NULL); + g_return_val_if_fail (key != NULL, NULL); + return g_hash_table_lookup (priv->metadata, key); +} + +/** + * as_review_add_metadata: + * @review: a #AsReview + * @key: a string + * @value: a string + * + * Adds metadata to the review object. + * It is left for the the plugin to use this method as required, but a + * typical use would be to store some secure authentication token. + * + * Since: 0.5.18 + **/ +void +as_review_add_metadata (AsReview *review, const gchar *key, const gchar *value) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + g_return_if_fail (AS_IS_REVIEW (review)); + g_hash_table_insert (priv->metadata, g_strdup (key), g_strdup (value)); +} + +/** + * as_review_equal: + * @review1: a #AsReview instance. + * @review2: a #AsReview instance. + * + * Checks if two reviews are the same. + * + * Returns: %TRUE for success + * + * Since: 0.5.18 + **/ +gboolean +as_review_equal (AsReview *review1, AsReview *review2) +{ + AsReviewPrivate *priv1 = GET_PRIVATE (review1); + AsReviewPrivate *priv2 = GET_PRIVATE (review2); + + /* trivial */ + if (review1 == review2) + return TRUE; + + /* check for equality */ + if (!g_date_time_equal (priv1->date, priv2->date)) + return FALSE; + if (priv1->karma != priv2->karma) + return FALSE; + if (priv1->priority != priv2->priority) + return FALSE; + if (priv1->rating != priv2->rating) + return FALSE; + if (g_strcmp0 (priv1->id, priv2->id) != 0) + return FALSE; + if (g_strcmp0 (priv1->summary, priv2->summary) != 0) + return FALSE; + if (g_strcmp0 (priv1->description, priv2->description) != 0) + return FALSE; + if (g_strcmp0 (priv1->locale, priv2->locale) != 0) + return FALSE; + if (g_strcmp0 (priv1->version, priv2->version) != 0) + return FALSE; + + /* success */ + return TRUE; +} + +/** + * as_review_node_insert: (skip) + * @review: a #AsReview instance. + * @parent: the parent #GNode to use.. + * @ctx: the #AsNodeContext + * + * Inserts the review into the DOM tree. + * + * Returns: (transfer none): A populated #GNode + * + * Since: 0.5.18 + **/ +GNode * +as_review_node_insert (AsReview *review, GNode *parent, AsNodeContext *ctx) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + GNode *n; + + n = as_node_insert (parent, "review", NULL, + AS_NODE_INSERT_FLAG_NONE, + NULL); + if (priv->id != NULL) + as_node_add_attribute (n, "id", priv->id); + if (priv->karma != 0) { + g_autofree gchar *str = g_strdup_printf ("%i", priv->karma); + as_node_add_attribute (n, "karma", str); + } + if (priv->priority != 0) { + g_autofree gchar *str = g_strdup_printf ("%i", priv->priority); + as_node_insert (n, "priority", str, + AS_NODE_INSERT_FLAG_NONE, + NULL); + } + if (priv->rating != 0) { + g_autofree gchar *str = g_strdup_printf ("%i", priv->rating); + as_node_add_attribute (n, "rating", str); + } + if (priv->date != NULL) { + g_autofree gchar *str = g_date_time_format (priv->date, "%F"); + as_node_add_attribute (n, "date", str); + } + if (priv->summary != NULL) { + as_node_insert (n, "summary", priv->summary, + AS_NODE_INSERT_FLAG_NONE, + NULL); + } + if (priv->description != NULL) { + as_node_insert (n, "description", priv->description, + AS_NODE_INSERT_FLAG_PRE_ESCAPED, + NULL); + } + if (priv->version != NULL) { + as_node_insert (n, "version", priv->version, + AS_NODE_INSERT_FLAG_NONE, + NULL); + } + if (priv->reviewer_id != NULL) { + as_node_insert (n, "reviewer_id", priv->reviewer_id, + AS_NODE_INSERT_FLAG_NONE, + NULL); + } + if (priv->reviewer_name != NULL) { + as_node_insert (n, "reviewer_name", priv->reviewer_name, + AS_NODE_INSERT_FLAG_NONE, + NULL); + } + if (priv->locale != NULL) { + as_node_insert (n, "lang", priv->locale, + AS_NODE_INSERT_FLAG_NONE, + NULL); + } + + /* <metadata> */ + if (g_hash_table_size (priv->metadata) > 0) { + AsNode *node_tmp; + node_tmp = as_node_insert (n, "metadata", NULL, 0, NULL); + as_node_insert_hash (node_tmp, "value", "key", priv->metadata, FALSE); + } + + return n; +} + +/** + * as_review_node_parse: + * @review: a #AsReview instance. + * @node: a #GNode. + * @ctx: a #AsNodeContext. + * @error: A #GError or %NULL. + * + * Populates the object from a DOM node. + * + * Returns: %TRUE for success + * + * Since: 0.5.18 + **/ +gboolean +as_review_node_parse (AsReview *review, GNode *node, + AsNodeContext *ctx, GError **error) +{ + AsReviewPrivate *priv = GET_PRIVATE (review); + AsNode *c; + const gchar *tmp; + gint itmp; + + itmp = as_node_get_attribute_as_int (node, "karma"); + if (itmp != G_MAXINT) + as_review_set_karma (review, itmp); + itmp = as_node_get_attribute_as_int (node, "rating"); + if (itmp != G_MAXINT) + as_review_set_rating (review, itmp); + tmp = as_node_get_attribute (node, "date"); + if (tmp != NULL) { + g_autoptr(GDateTime) dt = as_utils_iso8601_to_datetime (tmp); + if (dt != NULL) + as_review_set_date (review, dt); + } + tmp = as_node_get_attribute (node, "id"); + if (tmp != NULL) + as_review_set_id (review, tmp); + for (c = node->children; c != NULL; c = c->next) { + if (as_node_get_tag (c) == AS_TAG_SUMMARY) { + as_review_set_summary (review, as_node_get_data (c)); + continue; + } + if (as_node_get_tag (c) == AS_TAG_PRIORITY) { + gint64 prio = g_ascii_strtoll (as_node_get_data (c), + NULL, 10); + as_review_set_priority (review, (gint) prio); + continue; + } + if (as_node_get_tag (c) == AS_TAG_DESCRIPTION) { + g_autoptr(GString) xml = NULL; + xml = as_node_to_xml (c->children, AS_NODE_TO_XML_FLAG_INCLUDE_SIBLINGS); + as_review_set_description (review, xml->str); + continue; + } + if (as_node_get_tag (c) == AS_TAG_VERSION) { + as_review_set_version (review, as_node_get_data (c)); + continue; + } + if (as_node_get_tag (c) == AS_TAG_REVIEWER_ID) { + as_review_set_reviewer_id (review, as_node_get_data (c)); + continue; + } + if (as_node_get_tag (c) == AS_TAG_REVIEWER_NAME) { + as_review_set_reviewer_name (review, as_node_get_data (c)); + continue; + } + if (as_node_get_tag (c) == AS_TAG_LANG) { + as_review_set_locale (review, as_node_get_data (c)); + continue; + } + if (as_node_get_tag (c) == AS_TAG_METADATA) { + AsNode *c2; + gchar *taken; + for (c2 = c->children; c2 != NULL; c2 = c2->next) { + gchar *key; + if (as_node_get_tag (c2) != AS_TAG_VALUE) + continue; + key = as_node_take_attribute (c2, "key"); + taken = as_node_take_data (c2); + if (taken == NULL) + taken = g_strdup (""); + g_hash_table_insert (priv->metadata, key, taken); + } + continue; + } + } + return TRUE; +} + +/** + * as_review_node_parse_dep11: + * @review: a #AsReview instance. + * @node: a #GNode. + * @ctx: a #AsNodeContext. + * @error: A #GError or %NULL. + * + * Populates the object from a DEP-11 node. + * + * Returns: %TRUE for success + * + * Since: 0.5.18 + **/ +gboolean +as_review_node_parse_dep11 (AsReview *im, GNode *node, + AsNodeContext *ctx, GError **error) +{ + return TRUE; +} + +/** + * as_review_new: + * + * Creates a new #AsReview. + * + * Returns: (transfer full): a #AsReview + * + * Since: 0.5.18 + **/ +AsReview * +as_review_new (void) +{ + AsReview *review; + review = g_object_new (AS_TYPE_REVIEW, NULL); + return AS_REVIEW (review); +} diff --git a/libappstream-glib/as-review.h b/libappstream-glib/as-review.h new file mode 100644 index 0000000..35026bc --- /dev/null +++ b/libappstream-glib/as-review.h @@ -0,0 +1,124 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2016 Canonical Ltd. + * Copyright (C) 2016 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library 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 2.1 of the License, or (at your option) any later version. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if !defined (__APPSTREAM_GLIB_H) && !defined (AS_COMPILATION) +#error "Only <appstream-glib.h> can be included directly." +#endif + +#ifndef __AS_REVIEW_H +#define __AS_REVIEW_H + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define AS_TYPE_REVIEW (as_review_get_type ()) +G_DECLARE_DERIVABLE_TYPE (AsReview, as_review, AS, REVIEW, GObject) + +struct _AsReviewClass +{ + GObjectClass parent_class; + /*< private >*/ + void (*_as_reserved1) (void); + void (*_as_reserved2) (void); + void (*_as_reserved3) (void); + void (*_as_reserved4) (void); + void (*_as_reserved5) (void); + void (*_as_reserved6) (void); + void (*_as_reserved7) (void); + void (*_as_reserved8) (void); +}; + +/** + * AsReviewFlags: + * @AS_REVIEW_FLAG_NONE: No special flags set + * @AS_REVIEW_FLAG_SELF: The user wrote the review themselves + * @AS_REVIEW_FLAG_VOTED: The user voted on the review + * + * The flags for the review. + * + * Since: 0.5.18 + **/ +typedef enum { + AS_REVIEW_FLAG_NONE = 0, + AS_REVIEW_FLAG_SELF = 1 << 0, + AS_REVIEW_FLAG_VOTED = 1 << 1, + /*< private >*/ + AS_REVIEW_FLAG_LAST +} AsReviewFlags; + +AsReview *as_review_new (void); + +/* getters */ +gint as_review_get_karma (AsReview *review); +gint as_review_get_priority (AsReview *review); +const gchar *as_review_get_id (AsReview *review); +const gchar *as_review_get_summary (AsReview *review); +const gchar *as_review_get_description (AsReview *review); +const gchar *as_review_get_locale (AsReview *review); +gint as_review_get_rating (AsReview *review); +const gchar *as_review_get_version (AsReview *review); +const gchar *as_review_get_reviewer_id (AsReview *review); +const gchar *as_review_get_reviewer_name (AsReview *review); +GDateTime *as_review_get_date (AsReview *review); +AsReviewFlags as_review_get_flags (AsReview *review); +const gchar *as_review_get_metadata_item (AsReview *review, + const gchar *key); + +/* setters */ +void as_review_set_karma (AsReview *review, + gint karma); +void as_review_set_priority (AsReview *review, + gint priority); +void as_review_set_id (AsReview *review, + const gchar *id); +void as_review_set_summary (AsReview *review, + const gchar *summary); +void as_review_set_description (AsReview *review, + const gchar *description); +void as_review_set_locale (AsReview *review, + const gchar *locale); +void as_review_set_rating (AsReview *review, + gint rating); +void as_review_set_version (AsReview *review, + const gchar *version); +void as_review_set_reviewer_id (AsReview *review, + const gchar *reviewer_id); +void as_review_set_reviewer_name (AsReview *review, + const gchar *reviewer_name); +void as_review_set_date (AsReview *review, + GDateTime *date); +void as_review_set_flags (AsReview *review, + AsReviewFlags flags); +void as_review_add_flags (AsReview *review, + AsReviewFlags flags); +void as_review_add_metadata (AsReview *review, + const gchar *key, + const gchar *value); + +/* helpers */ +gboolean as_review_equal (AsReview *review1, + AsReview *review2); + +G_END_DECLS + +#endif /* __AS_REVIEW_H */ diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c index 84a8d4c..87ec000 100644 --- a/libappstream-glib/as-self-test.c +++ b/libappstream-glib/as-self-test.c @@ -35,6 +35,7 @@ #include "as-enums.h" #include "as-icon-private.h" #include "as-image-private.h" +#include "as-review-private.h" #include "as-inf.h" #include "as-markup.h" #include "as-monitor.h" @@ -1173,6 +1174,69 @@ as_test_image_func (void) } static void +as_test_review_func (void) +{ + GError *error = NULL; + AsNode *n; + AsNode *root; + GString *xml; + const gchar *src = + "<review date=\"2016-09-15\" rating=\"80\" karma=\"-1\" id=\"17\">\n" + "<priority>5</priority>\n" + "<summary>Hello world</summary>\n" + "<description><p>Mighty Fine</p></description>\n" + "<version>1.2.3</version>\n" + "<reviewer_id>deadbeef</reviewer_id>\n" + "<reviewer_name>Richard Hughes</reviewer_name>\n" + "<lang>en_GB</lang>\n" + "<metadata>\n" + "<value key=\"foo\">bar</value>\n" + "</metadata>\n" + "</review>\n"; + gboolean ret; + g_autofree AsNodeContext *ctx = NULL; + g_autoptr(AsReview) review = NULL; + + review = as_review_new (); + + /* to object */ + root = as_node_from_xml (src, 0, &error); + g_assert_no_error (error); + g_assert (root != NULL); + n = as_node_find (root, "review"); + g_assert (n != NULL); + ctx = as_node_context_new (); + ret = as_review_node_parse (review, n, ctx, &error); + g_assert_no_error (error); + g_assert (ret); + as_node_unref (root); + + /* verify */ + g_assert_cmpint (as_review_get_karma (review), ==, -1); + g_assert_cmpint (as_review_get_priority (review), ==, 5); + g_assert (as_review_get_date (review) != NULL); + g_assert_cmpstr (as_review_get_id (review), ==, "17"); + g_assert_cmpstr (as_review_get_version (review), ==, "1.2.3"); + g_assert_cmpstr (as_review_get_reviewer_id (review), ==, "deadbeef"); + g_assert_cmpstr (as_review_get_reviewer_name (review), ==, "Richard Hughes"); + g_assert_cmpstr (as_review_get_summary (review), ==, "Hello world"); + g_assert_cmpstr (as_review_get_locale (review), ==, "en_GB"); + g_assert_cmpstr (as_review_get_description (review), ==, "<p>Mighty Fine</p>"); + g_assert_cmpstr (as_review_get_metadata_item (review, "foo"), ==, "bar"); + + /* back to node */ + root = as_node_new (); + as_node_context_set_version (ctx, 0.4); + n = as_review_node_insert (review, root, ctx); + xml = as_node_to_xml (n, AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE); + ret = as_test_compare_lines (xml->str, src, &error); + g_assert_no_error (error); + g_assert (ret); + g_string_free (xml, TRUE); + as_node_unref (root); +} + +static void as_test_bundle_func (void) { GError *error = NULL; @@ -1430,6 +1494,11 @@ as_test_app_func (void) "<image type=\"thumbnail\">http://b.png</image>\n" "</screenshot>\n" "</screenshots>\n" + "<reviews>\n" + "<review date=\"2016-09-15\">\n" + "<summary>Hello world</summary>\n" + "</review>\n" + "</reviews>\n" "<content_rating type=\"oars-1.0\">\n" "<content_attribute id=\"drugs-alcohol\">moderate</content_attribute>\n" "</content_rating>\n" @@ -4858,6 +4927,7 @@ main (int argc, char **argv) g_test_add_func ("/AppStream/icon", as_test_icon_func); g_test_add_func ("/AppStream/icon{embedded}", as_test_icon_embedded_func); g_test_add_func ("/AppStream/bundle", as_test_bundle_func); + g_test_add_func ("/AppStream/review", as_test_review_func); g_test_add_func ("/AppStream/translation", as_test_translation_func); g_test_add_func ("/AppStream/image", as_test_image_func); g_test_add_func ("/AppStream/image{resize}", as_test_image_resize_func); diff --git a/libappstream-glib/as-tag.c b/libappstream-glib/as-tag.c index 1bb78d4..820eddd 100644 --- a/libappstream-glib/as-tag.c +++ b/libappstream-glib/as-tag.c @@ -194,6 +194,11 @@ as_tag_to_string (AsTag tag) "translation", "content_rating", "content_attribute", + "version", + "reviews", + "review", + "reviewer_name", + "reviewer_id", NULL }; if (tag > AS_TAG_LAST) tag = AS_TAG_LAST; diff --git a/libappstream-glib/as-tag.gperf b/libappstream-glib/as-tag.gperf index 7e13f72..5508e65 100644 --- a/libappstream-glib/as-tag.gperf +++ b/libappstream-glib/as-tag.gperf @@ -58,3 +58,8 @@ size, AS_TAG_SIZE translation, AS_TAG_TRANSLATION content_rating, AS_TAG_CONTENT_RATING content_attribute, AS_TAG_CONTENT_ATTRIBUTE +version, AS_TAG_VERSION +reviews, AS_TAG_REVIEWS +review, AS_TAG_REVIEW +reviewer_name, AS_TAG_REVIEWER_NAME +reviewer_id, AS_TAG_REVIEWER_ID diff --git a/libappstream-glib/as-tag.h b/libappstream-glib/as-tag.h index 8579745..f4eab76 100644 --- a/libappstream-glib/as-tag.h +++ b/libappstream-glib/as-tag.h @@ -83,6 +83,11 @@ G_BEGIN_DECLS * @AS_TAG_TRANSLATION: `translation` * @AS_TAG_CONTENT_RATING: `content_rating` * @AS_TAG_CONTENT_ATTRIBUTE: `content_attribute` + * @AS_TAG_VERSION: `version` + * @AS_TAG_REVIEWS: `reviews` + * @AS_TAG_REVIEW: `review` + * @AS_TAG_REVIEWER_NAME: `reviewer_name` + * @AS_TAG_REVIEWER_ID: `reviewer_id` * * The tag type. **/ @@ -138,6 +143,11 @@ typedef enum { AS_TAG_TRANSLATION, /* Since: 0.5.8 */ AS_TAG_CONTENT_RATING, /* Since: 0.5.12 */ AS_TAG_CONTENT_ATTRIBUTE, /* Since: 0.5.12 */ + AS_TAG_VERSION, /* Since: 0.5.18 */ + AS_TAG_REVIEWS, /* Since: 0.5.18 */ + AS_TAG_REVIEW, /* Since: 0.5.18 */ + AS_TAG_REVIEWER_NAME, /* Since: 0.5.18 */ + AS_TAG_REVIEWER_ID, /* Since: 0.5.18 */ /*< private >*/ AS_TAG_LAST } AsTag; |