summaryrefslogtreecommitdiffstats
path: root/lib/gs-plugin-event.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gs-plugin-event.c')
-rw-r--r--lib/gs-plugin-event.c453
1 files changed, 453 insertions, 0 deletions
diff --git a/lib/gs-plugin-event.c b/lib/gs-plugin-event.c
new file mode 100644
index 0000000..699e529
--- /dev/null
+++ b/lib/gs-plugin-event.c
@@ -0,0 +1,453 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2016 Richard Hughes <richard@hughsie.com>
+ * Copyright (C) 2016 Kalev Lember <klember@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/**
+ * SECTION:gs-plugin-event
+ * @title: GsPluginEvent
+ * @include: gnome-software.h
+ * @stability: Unstable
+ * @short_description: Information about a plugin event
+ *
+ * These functions provide a way for plugins to tell the UI layer about events
+ * that may require displaying to the user. Plugins should not assume that a
+ * specific event is actually shown to the user as it may be ignored
+ * automatically.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include "gs-enums.h"
+#include "gs-plugin-private.h"
+#include "gs-plugin-event.h"
+#include "gs-plugin-job.h"
+#include "gs-utils.h"
+
+struct _GsPluginEvent
+{
+ GObject parent_instance;
+ GsApp *app;
+ GsApp *origin;
+ GsPluginAction action;
+ GsPluginJob *job; /* (owned) (nullable) */
+ GError *error;
+ GsPluginEventFlag flags;
+ gchar *unique_id;
+};
+
+G_DEFINE_TYPE (GsPluginEvent, gs_plugin_event, G_TYPE_OBJECT)
+
+typedef enum {
+ PROP_APP = 1,
+ PROP_ORIGIN,
+ PROP_ACTION,
+ PROP_JOB,
+ PROP_ERROR,
+} GsPluginEventProperty;
+
+static GParamSpec *props[PROP_ERROR + 1] = { NULL, };
+
+/**
+ * gs_plugin_event_get_app:
+ * @event: A #GsPluginEvent
+ *
+ * Gets an application that created the event.
+ *
+ * Returns: (transfer none): a #GsApp, or %NULL if unset
+ *
+ * Since: 3.22
+ **/
+GsApp *
+gs_plugin_event_get_app (GsPluginEvent *event)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_EVENT (event), NULL);
+ return event->app;
+}
+
+/**
+ * gs_plugin_event_get_origin:
+ * @event: A #GsPluginEvent
+ *
+ * Gets an origin that created the event.
+ *
+ * Returns: (transfer none): a #GsApp, or %NULL if unset
+ *
+ * Since: 3.22
+ **/
+GsApp *
+gs_plugin_event_get_origin (GsPluginEvent *event)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_EVENT (event), NULL);
+ return event->origin;
+}
+
+/**
+ * gs_plugin_event_get_action:
+ * @event: A #GsPluginEvent
+ *
+ * Gets an action that created the event.
+ *
+ * Returns: (transfer none): a #GsPluginAction, e.g. %GS_PLUGIN_ACTION_UPDATE
+ *
+ * Since: 3.22
+ **/
+GsPluginAction
+gs_plugin_event_get_action (GsPluginEvent *event)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_EVENT (event), 0);
+ return event->action;
+}
+
+/**
+ * gs_plugin_event_get_job:
+ * @event: A #GsPluginEvent
+ *
+ * Gets the job that created the event.
+ *
+ * Returns: (transfer none) (nullable): a #GsPluginJob
+ *
+ * Since: 42
+ **/
+GsPluginJob *
+gs_plugin_event_get_job (GsPluginEvent *event)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_EVENT (event), NULL);
+ return event->job;
+}
+
+/**
+ * gs_plugin_event_get_unique_id:
+ * @event: A #GsPluginEvent
+ *
+ * Gets the unique ID for the event. In most cases (if an app has been set)
+ * this will just be the actual #GsApp unique-id. In the cases where only error
+ * has been set a virtual (but plausible) ID will be generated.
+ *
+ * Returns: a string, or %NULL for invalid
+ *
+ * Since: 3.22
+ **/
+const gchar *
+gs_plugin_event_get_unique_id (GsPluginEvent *event)
+{
+ /* just proxy */
+ if (event->origin != NULL &&
+ gs_app_get_unique_id (event->origin) != NULL) {
+ return gs_app_get_unique_id (event->origin);
+ }
+ if (event->app != NULL &&
+ gs_app_get_unique_id (event->app) != NULL) {
+ return gs_app_get_unique_id (event->app);
+ }
+
+ /* generate from error */
+ if (event->error != NULL) {
+ if (event->unique_id == NULL) {
+ g_autofree gchar *id = NULL;
+ id = g_strdup_printf ("%s.error",
+ gs_plugin_error_to_string (event->error->code));
+ event->unique_id = gs_utils_build_unique_id (AS_COMPONENT_SCOPE_UNKNOWN,
+ AS_BUNDLE_KIND_UNKNOWN,
+ NULL,
+ id,
+ NULL);
+ }
+ return event->unique_id;
+ }
+
+ /* failed */
+ return NULL;
+}
+
+/**
+ * gs_plugin_event_get_kind:
+ * @event: A #GsPluginEvent
+ * @flag: A #GsPluginEventFlag, e.g. %GS_PLUGIN_EVENT_FLAG_INVALID
+ *
+ * Adds a flag to the event.
+ *
+ * Since: 3.22
+ **/
+void
+gs_plugin_event_add_flag (GsPluginEvent *event, GsPluginEventFlag flag)
+{
+ g_return_if_fail (GS_IS_PLUGIN_EVENT (event));
+ event->flags |= flag;
+}
+
+/**
+ * gs_plugin_event_set_kind:
+ * @event: A #GsPluginEvent
+ * @flag: A #GsPluginEventFlag, e.g. %GS_PLUGIN_EVENT_FLAG_INVALID
+ *
+ * Removes a flag from the event.
+ *
+ * Since: 3.22
+ **/
+void
+gs_plugin_event_remove_flag (GsPluginEvent *event, GsPluginEventFlag flag)
+{
+ g_return_if_fail (GS_IS_PLUGIN_EVENT (event));
+ event->flags &= ~flag;
+}
+
+/**
+ * gs_plugin_event_has_flag:
+ * @event: A #GsPluginEvent
+ * @flag: A #GsPluginEventFlag, e.g. %GS_PLUGIN_EVENT_FLAG_INVALID
+ *
+ * Finds out if the event has a specific flag.
+ *
+ * Returns: %TRUE if the flag is set
+ *
+ * Since: 3.22
+ **/
+gboolean
+gs_plugin_event_has_flag (GsPluginEvent *event, GsPluginEventFlag flag)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_EVENT (event), FALSE);
+ return ((event->flags & flag) > 0);
+}
+
+/**
+ * gs_plugin_event_get_error:
+ * @event: A #GsPluginEvent
+ *
+ * Gets the event error.
+ *
+ * Returns: a #GError, or %NULL for unset
+ *
+ * Since: 3.22
+ **/
+const GError *
+gs_plugin_event_get_error (GsPluginEvent *event)
+{
+ return event->error;
+}
+
+static void
+gs_plugin_event_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsPluginEvent *self = GS_PLUGIN_EVENT (object);
+
+ switch ((GsPluginEventProperty) prop_id) {
+ case PROP_APP:
+ g_value_set_object (value, self->app);
+ break;
+ case PROP_ORIGIN:
+ g_value_set_object (value, self->origin);
+ break;
+ case PROP_ACTION:
+ g_value_set_enum (value, self->action);
+ break;
+ case PROP_JOB:
+ g_value_set_object (value, self->job);
+ break;
+ case PROP_ERROR:
+ g_value_set_boxed (value, self->error);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gs_plugin_event_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsPluginEvent *self = GS_PLUGIN_EVENT (object);
+
+ switch ((GsPluginEventProperty) prop_id) {
+ case PROP_APP:
+ /* Construct only. */
+ g_assert (self->app == NULL);
+ self->app = g_value_dup_object (value);
+ g_object_notify_by_pspec (object, props[prop_id]);
+ break;
+ case PROP_ORIGIN:
+ /* Construct only. */
+ g_assert (self->origin == NULL);
+ self->origin = g_value_dup_object (value);
+ g_object_notify_by_pspec (object, props[prop_id]);
+ break;
+ case PROP_ACTION:
+ /* Construct only. */
+ g_assert (self->action == GS_PLUGIN_ACTION_UNKNOWN);
+ self->action = g_value_get_enum (value);
+ g_object_notify_by_pspec (object, props[prop_id]);
+ break;
+ case PROP_JOB:
+ /* Construct only. */
+ g_assert (self->job == NULL);
+ self->job = g_value_dup_object (value);
+ g_object_notify_by_pspec (object, props[prop_id]);
+ break;
+ case PROP_ERROR:
+ /* Construct only. */
+ g_assert (self->error == NULL);
+ self->error = g_value_dup_boxed (value);
+ if (self->error) {
+ /* Just in case the caller left there any D-Bus remote error notes */
+ g_dbus_error_strip_remote_error (self->error);
+ }
+ g_object_notify_by_pspec (object, props[prop_id]);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gs_plugin_event_dispose (GObject *object)
+{
+ GsPluginEvent *event = GS_PLUGIN_EVENT (object);
+
+ g_clear_object (&event->app);
+ g_clear_object (&event->origin);
+ g_clear_object (&event->job);
+
+ G_OBJECT_CLASS (gs_plugin_event_parent_class)->dispose (object);
+}
+
+static void
+gs_plugin_event_finalize (GObject *object)
+{
+ GsPluginEvent *event = GS_PLUGIN_EVENT (object);
+
+ g_clear_error (&event->error);
+ g_free (event->unique_id);
+
+ G_OBJECT_CLASS (gs_plugin_event_parent_class)->finalize (object);
+}
+
+static void
+gs_plugin_event_class_init (GsPluginEventClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gs_plugin_event_get_property;
+ object_class->set_property = gs_plugin_event_set_property;
+ object_class->dispose = gs_plugin_event_dispose;
+ object_class->finalize = gs_plugin_event_finalize;
+
+ /**
+ * GsPluginEvent:app: (nullable)
+ *
+ * The application (or source, or whatever component) that caused the
+ * event to be created.
+ *
+ * Since: 42
+ */
+ props[PROP_APP] =
+ g_param_spec_object ("app", "App",
+ "The application (or source, or whatever component) that caused the event to be created.",
+ GS_TYPE_APP,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ /**
+ * GsPluginEvent:origin: (nullable)
+ *
+ * The origin that caused the event to be created.
+ *
+ * Since: 42
+ */
+ props[PROP_ORIGIN] =
+ g_param_spec_object ("origin", "Origin",
+ "The origin that caused the event to be created.",
+ GS_TYPE_APP,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ /**
+ * GsPluginEvent:action:
+ *
+ * The action that caused the event to be created.
+ *
+ * Since: 42
+ */
+ props[PROP_ACTION] =
+ g_param_spec_enum ("action", "Action",
+ "The action that caused the event to be created.",
+ GS_TYPE_PLUGIN_ACTION, GS_PLUGIN_ACTION_UNKNOWN,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ /**
+ * GsPluginEvent:job: (nullable)
+ *
+ * The job that caused the event to be created.
+ *
+ * Since: 42
+ */
+ props[PROP_JOB] =
+ g_param_spec_object ("job", "Job",
+ "The job that caused the event to be created.",
+ GS_TYPE_PLUGIN_JOB,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ /**
+ * GsPluginEvent:error: (nullable)
+ *
+ * The error the event is reporting.
+ *
+ * Since: 42
+ */
+ props[PROP_ERROR] =
+ g_param_spec_boxed ("error", "Error",
+ "The error the event is reporting.",
+ G_TYPE_ERROR,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ g_object_class_install_properties (object_class, G_N_ELEMENTS (props), props);
+}
+
+static void
+gs_plugin_event_init (GsPluginEvent *event)
+{
+}
+
+/**
+ * gs_plugin_event_new:
+ * @first_property_name: the name of the first property
+ * @...: the value of the first property, followed by zero or more pairs of
+ * property name/value pairs, then %NULL
+ *
+ * Creates a new event.
+ *
+ * The arguments are as for g_object_new(): property name/value pairs to set
+ * the properties of the event.
+ *
+ * Returns: (transfer full): A newly allocated #GsPluginEvent
+ *
+ * Since: 42
+ **/
+GsPluginEvent *
+gs_plugin_event_new (const gchar *first_property_name,
+ ...)
+{
+ GsPluginEvent *event;
+ va_list args;
+
+ va_start (args, first_property_name);
+ event = GS_PLUGIN_EVENT (g_object_new_valist (GS_TYPE_PLUGIN_EVENT, first_property_name, args));
+ va_end (args);
+
+ return GS_PLUGIN_EVENT (event);
+}