/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2016 Canonical Ltd. * Copyright (C) 2016 Richard Hughes * Copyright (C) 2020-2024 Matthias Klumpp * * 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, see . */ /** * SECTION:as-review * @title: AsReview * @include: appstream.h * @short_description: A user review * * This object represents a user-submitted software review. * * Since: 0.14.0 **/ #include "config.h" #include "as-review-private.h" #include "as-utils-private.h" typedef struct { AsReviewFlags flags; GRefString *id; GRefString *summary; GRefString *description; GRefString *locale; gint priority; gint rating; GRefString *version; GRefString *reviewer_id; GRefString *reviewer_name; GDateTime *date; GHashTable *metadata; /* GRefString : GRefString */ } AsReviewPrivate; typedef enum { PROP_ID = 1, PROP_SUMMARY, PROP_DESCRIPTION, PROP_LOCALE, PROP_PRIORITY, PROP_RATING, PROP_VERSION, PROP_REVIEWER_ID, PROP_REVIEWER_NAME, PROP_DATE, PROP_FLAGS, } AsReviewProperty; static GParamSpec *pspecs[PROP_FLAGS + 1] = { NULL, }; 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); as_ref_string_release (priv->id); as_ref_string_release (priv->summary); as_ref_string_release (priv->description); as_ref_string_release (priv->locale); as_ref_string_release (priv->version); as_ref_string_release (priv->reviewer_id); as_ref_string_release (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_init (AsReview *review) { AsReviewPrivate *priv = GET_PRIVATE (review); priv->metadata = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_ref_string_release, (GDestroyNotify) g_ref_string_release); } 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 ((AsReviewProperty) prop_id) { 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_PRIORITY: g_value_set_int (value, priv->priority); 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 ((AsReviewProperty) prop_id) { 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_PRIORITY: as_review_set_priority (review, g_value_get_int (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) { 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:id: * * Since: 0.14.0 **/ pspecs[PROP_ID] = g_param_spec_string ("id", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * AsReview:summary: * * Since: 0.14.0 **/ pspecs[PROP_SUMMARY] = g_param_spec_string ("summary", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * AsReview:description: * * Since: 0.14.0 **/ pspecs[PROP_DESCRIPTION] = g_param_spec_string ("description", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * AsReview:locale: * * Since: 0.14.0 **/ pspecs[PROP_LOCALE] = g_param_spec_string ("locale", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * AsReview:priority: * * The priority for the review, where positive numbers indicate * a better review for the specific user. * * Since: 0.15.6 */ pspecs[PROP_PRIORITY] = g_param_spec_int ("priority", NULL, NULL, G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * AsReview:rating: * * Since: 0.14.0 **/ pspecs[PROP_RATING] = g_param_spec_int ("rating", NULL, NULL, -1, 100, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * AsReview:flags: * * Since: 0.14.0 **/ pspecs[PROP_FLAGS] = 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_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * AsReview:version: * * Since: 0.14.0 **/ pspecs[PROP_VERSION] = g_param_spec_string ("version", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * AsReview:reviewer-id: * * Since: 0.14.0 **/ pspecs[PROP_REVIEWER_ID] = g_param_spec_string ("reviewer-id", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * AsReview:reviewer-name: * * Since: 0.14.0 **/ pspecs[PROP_REVIEWER_NAME] = g_param_spec_string ("reviewer-name", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); /** * AsReview:date: * * Since: 0.14.0 **/ pspecs[PROP_DATE] = g_param_spec_object ("date", NULL, NULL, AS_TYPE_REVIEW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (object_class, G_N_ELEMENTS (pspecs), pspecs); } /** * 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.14.0 **/ 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.14.0 **/ void as_review_set_priority (AsReview *review, gint priority) { AsReviewPrivate *priv = GET_PRIVATE (review); g_return_if_fail (AS_IS_REVIEW (review)); if (priv->priority != priority) { priv->priority = priority; g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_PRIORITY]); } } /** * as_review_get_id: * @review: a #AsReview * * Gets the review id. * * Returns: the review identifier, e.g. "deadbeef" * * Since: 0.14.0 **/ 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.14.0 **/ 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.14.0 **/ void as_review_set_id (AsReview *review, const gchar *id) { AsReviewPrivate *priv = GET_PRIVATE (review); g_return_if_fail (AS_IS_REVIEW (review)); as_ref_string_assign_safe (&priv->id, id); g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_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.14.0 **/ void as_review_set_summary (AsReview *review, const gchar *summary) { AsReviewPrivate *priv = GET_PRIVATE (review); g_return_if_fail (AS_IS_REVIEW (review)); as_ref_string_assign_safe (&priv->summary, summary); g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_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.14.0 **/ 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.14.0 **/ void as_review_set_description (AsReview *review, const gchar *description) { AsReviewPrivate *priv = GET_PRIVATE (review); g_return_if_fail (AS_IS_REVIEW (review)); as_ref_string_assign_safe (&priv->description, description); g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_DESCRIPTION]); } /** * as_review_get_locale: * @review: a #AsReview * * Gets the locale for the review. * * Returns: the string, or %NULL * * Since: 0.14.0 **/ 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: a BCP47 locale, e.g. "en-GB" * * Sets the locale for the review. * * Since: 0.14.0 **/ void as_review_set_locale (AsReview *review, const gchar *locale) { AsReviewPrivate *priv = GET_PRIVATE (review); g_return_if_fail (AS_IS_REVIEW (review)); as_ref_string_assign_safe (&priv->locale, locale); g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_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.14.0 **/ 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.14.0 **/ void as_review_set_rating (AsReview *review, gint rating) { AsReviewPrivate *priv = GET_PRIVATE (review); g_return_if_fail (AS_IS_REVIEW (review)); if (priv->rating != rating) { priv->rating = rating; g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_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.14.0 **/ AsReviewFlags as_review_get_flags (AsReview *review) { AsReviewPrivate *priv = GET_PRIVATE (review); g_return_val_if_fail (AS_IS_REVIEW (review), AS_REVIEW_FLAG_NONE); 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.14.0 **/ void as_review_set_flags (AsReview *review, AsReviewFlags flags) { AsReviewPrivate *priv = GET_PRIVATE (review); g_return_if_fail (AS_IS_REVIEW (review)); if (priv->flags != flags) { priv->flags = flags; g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_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.14.0 **/ void as_review_add_flags (AsReview *review, AsReviewFlags flags) { AsReviewPrivate *priv = GET_PRIVATE (review); g_return_if_fail (AS_IS_REVIEW (review)); if ((priv->flags & flags) != flags) { priv->flags |= flags; g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_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.14.0 **/ 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.14.0 **/ 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.14.0 **/ 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)); as_ref_string_assign_safe (&priv->reviewer_id, reviewer_id); g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_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.14.0 **/ 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)); as_ref_string_assign_safe (&priv->reviewer_name, reviewer_name); g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_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.14.0 **/ void as_review_set_version (AsReview *review, const gchar *version) { AsReviewPrivate *priv = GET_PRIVATE (review); g_return_if_fail (AS_IS_REVIEW (review)); as_ref_string_assign_safe (&priv->version, version); g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_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.14.0 **/ 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.14.0 **/ 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.14.0 **/ void as_review_set_date (AsReview *review, GDateTime *date) { AsReviewPrivate *priv = GET_PRIVATE (review); g_return_if_fail (AS_IS_REVIEW (review)); if ((date == NULL && priv->date == NULL) || (date != NULL && priv->date != NULL && g_date_time_equal (date, priv->date))) return; g_clear_pointer (&priv->date, g_date_time_unref); if (date != NULL) priv->date = g_date_time_ref (date); g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_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.14.0 **/ 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.14.0 **/ 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_ref_string_new_intern (key), g_ref_string_new_intern (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.14.0 **/ 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->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_load_from_xml: * @review: a #AsReview instance. * @ctx: the AppStream document context. * @node: the XML node. * @error: a #GError. * * Loads review data from an XML node. **/ gboolean as_review_load_from_xml (AsReview *review, AsContext *ctx, xmlNode *node, GError **error) { AsReviewPrivate *priv = GET_PRIVATE (review); gchar *str; gint itmp; as_ref_string_assign_transfer (&priv->id, as_xml_get_prop_value_refstr (node, "id")); str = as_xml_get_prop_value (node, "date"); if (str != NULL) { g_autoptr(GDateTime) dt = as_iso8601_to_datetime (str); if (dt != NULL) as_review_set_date (review, dt); g_free (str); } itmp = as_xml_get_prop_value_as_int (node, "rating"); if (itmp != G_MAXINT) as_review_set_rating (review, itmp); for (xmlNode *iter = node->children; iter != NULL; iter = iter->next) { if (iter->type != XML_ELEMENT_NODE) continue; if (g_strcmp0 ((gchar *) iter->name, "priority") == 0) { gint64 prio; str = as_xml_get_node_value (iter); prio = g_ascii_strtoll (str, NULL, 10); as_review_set_priority (review, (gint) prio); g_free (str); } else if (g_strcmp0 ((gchar *) iter->name, "summary") == 0) { as_ref_string_assign_transfer (&priv->summary, as_xml_get_node_value_refstr (iter)); g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_SUMMARY]); } else if (g_strcmp0 ((gchar *) iter->name, "description") == 0) { g_autofree gchar *desc = as_xml_dump_node_children (iter); as_ref_string_assign_transfer (&priv->description, g_ref_string_new_intern (desc)); g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_DESCRIPTION]); } else if (g_strcmp0 ((gchar *) iter->name, "version") == 0) { as_ref_string_assign_transfer (&priv->version, as_xml_get_node_value_refstr (iter)); g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_VERSION]); } else if (g_strcmp0 ((gchar *) iter->name, "reviewer_id") == 0) { as_ref_string_assign_transfer (&priv->reviewer_id, as_xml_get_node_value_refstr (iter)); g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_REVIEWER_ID]); } else if (g_strcmp0 ((gchar *) iter->name, "reviewer_name") == 0) { as_ref_string_assign_transfer (&priv->reviewer_name, as_xml_get_node_value_refstr (iter)); g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_REVIEWER_NAME]); } else if (g_strcmp0 ((gchar *) iter->name, "lang") == 0) { as_ref_string_assign_transfer (&priv->locale, as_xml_get_node_value_refstr (iter)); g_object_notify_by_pspec (G_OBJECT (review), pspecs[PROP_LOCALE]); } else if (g_strcmp0 ((gchar *) iter->name, "metadata") == 0) { as_xml_parse_custom_node (iter, priv->metadata); } } return TRUE; } /** * as_review_to_xml_node: * @review: a #AsReview instance. * @ctx: the AppStream document context. * @root: XML node to attach the new nodes to. * * Serializes the data to an XML node. **/ void as_review_to_xml_node (AsReview *review, AsContext *ctx, xmlNode *root) { AsReviewPrivate *priv = GET_PRIVATE (review); xmlNode *n_review; n_review = as_xml_add_node (root, "review"); if (priv->id != NULL) { as_xml_add_text_prop (n_review, "id", priv->id); } if (priv->date != NULL) { g_autofree gchar *str = g_date_time_format (priv->date, "%F"); as_xml_add_text_prop (n_review, "date", str); } if (priv->rating != 0) { g_autofree gchar *str = g_strdup_printf ("%i", priv->rating); as_xml_add_text_prop (n_review, "rating", str); } if (priv->priority != 0) { g_autofree gchar *str = g_strdup_printf ("%i", priv->priority); as_xml_add_text_node (n_review, "priority", str); } as_xml_add_text_node (n_review, "summary", priv->summary); as_xml_add_description_node_raw (n_review, priv->description); as_xml_add_text_node (n_review, "version", priv->version); as_xml_add_text_node (n_review, "reviewer_id", priv->reviewer_id); as_xml_add_text_node (n_review, "reviewer_name", priv->reviewer_name); as_xml_add_text_node (n_review, "lang", priv->locale); /* */ as_xml_add_custom_node (n_review, "metadata", priv->metadata); xmlAddChild (root, n_review); } /** * as_review_load_from_yaml: * @review: a #AsReview instance. * @ctx: the AppStream document context. * @node: the YAML node. * @error: a #GError. * * Loads data from a YAML field. **/ gboolean as_review_load_from_yaml (AsReview *review, AsContext *ctx, GNode *node, GError **error) { /* TODO */ return TRUE; } /** * as_review_emit_yaml: * @review: a #AsReview instance. * @ctx: the AppStream document context. * @emitter: The YAML emitter to emit data on. * * Emit YAML data for this object. **/ void as_review_emit_yaml (AsReview *review, AsContext *ctx, yaml_emitter_t *emitter) { /* TODO */ return; } /** * as_review_new: * * Creates a new #AsReview. * * Returns: (transfer full): a #AsReview * * Since: 0.14.0 **/ AsReview * as_review_new (void) { AsReview *review; review = g_object_new (AS_TYPE_REVIEW, NULL); return AS_REVIEW (review); }