summaryrefslogtreecommitdiffstats
path: root/lib/gs-category-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gs-category-manager.c')
-rw-r--r--lib/gs-category-manager.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/lib/gs-category-manager.c b/lib/gs-category-manager.c
new file mode 100644
index 0000000..0e37264
--- /dev/null
+++ b/lib/gs-category-manager.c
@@ -0,0 +1,151 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2021 Endless OS Foundation LLC
+ *
+ * Author: Philip Withnall <pwithnall@endlessos.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/**
+ * SECTION:gs-category-manager
+ * @short_description: A container to store #GsCategory instances in
+ *
+ * #GsCategoryManager is a container object which stores #GsCategory instances,
+ * so that they can be consistently reused by other code, without creating
+ * multiple #GsCategory instances for the same category ID.
+ *
+ * It is intended to be used as a singleton, and typically accessed by calling
+ * gs_plugin_loader_get_category_manager().
+ *
+ * Since: 40
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include "gs-category-manager.h"
+#include "gs-desktop-data.h"
+
+struct _GsCategoryManager
+{
+ GObject parent;
+
+ /* Array of #GsCategory instances corresponding to the entries in gs_desktop_get_data()
+ * The +1 is for a NULL terminator */
+ GsCategory *categories[GS_DESKTOP_DATA_N_ENTRIES + 1];
+};
+
+G_DEFINE_TYPE (GsCategoryManager, gs_category_manager, G_TYPE_OBJECT)
+
+static void
+gs_category_manager_dispose (GObject *object)
+{
+ GsCategoryManager *self = GS_CATEGORY_MANAGER (object);
+
+ for (gsize i = 0; i < G_N_ELEMENTS (self->categories); i++)
+ g_clear_object (&self->categories[i]);
+
+ G_OBJECT_CLASS (gs_category_manager_parent_class)->dispose (object);
+}
+
+static void
+gs_category_manager_class_init (GsCategoryManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gs_category_manager_dispose;
+}
+
+static void
+gs_category_manager_init (GsCategoryManager *self)
+{
+ const GsDesktopData *msdata;
+
+ /* Set up the category data, and check our expectations about the length
+ * of gs_desktop_get_data() match reality. */
+ msdata = gs_desktop_get_data ();
+ for (gsize i = 0; msdata[i].id != NULL; i++) {
+ g_assert (i < G_N_ELEMENTS (self->categories) - 1);
+ self->categories[i] = gs_category_new_for_desktop_data (&msdata[i]);
+ }
+
+ g_assert (self->categories[G_N_ELEMENTS (self->categories) - 2] != NULL);
+ g_assert (self->categories[G_N_ELEMENTS (self->categories) - 1] == NULL);
+}
+
+/**
+ * gs_category_manager_new:
+ *
+ * Create a new #GsCategoryManager. It will contain all the categories, but
+ * their sizes will not be set until gs_category_increment_size() is called
+ * on them.
+ *
+ * Returns: (transfer full): a new #GsCategoryManager
+ * Since: 40
+ */
+GsCategoryManager *
+gs_category_manager_new (void)
+{
+ return g_object_new (GS_TYPE_CATEGORY_MANAGER, NULL);
+}
+
+/**
+ * gs_category_manager_lookup:
+ * @self: a #GsCategoryManager
+ * @id: ID of the category to look up
+ *
+ * Look up a category by its ID. If the category is not found, %NULL is
+ * returned.
+ *
+ * Returns: (transfer full) (nullable): the #GsCategory, or %NULL
+ * Since: 40
+ */
+GsCategory *
+gs_category_manager_lookup (GsCategoryManager *self,
+ const gchar *id)
+{
+ g_return_val_if_fail (GS_IS_CATEGORY_MANAGER (self), NULL);
+ g_return_val_if_fail (id != NULL && *id != '\0', NULL);
+
+ /* There are only on the order of 10 categories, so this is quick */
+ for (gsize i = 0; i < G_N_ELEMENTS (self->categories) - 1; i++) {
+ if (g_str_equal (gs_category_get_id (self->categories[i]), id))
+ return g_object_ref (self->categories[i]);
+ }
+
+ return NULL;
+}
+
+/**
+ * gs_category_manager_get_categories:
+ * @self: a #GsCategoryManager
+ * @out_n_categories: (optional) (out caller-allocates): return location for
+ * the number of categories in the return value, or %NULL to ignore
+ *
+ * Get the full list of categories from the category manager. The returned array
+ * is %NULL terminated and guaranteed to be non-%NULL (although it may be
+ * empty).
+ *
+ * If @out_n_categories is provided, it will be set to the number of #GsCategory
+ * objects in the return value, not including the %NULL terminator.
+ *
+ * Returns: (array length=out_n_categories) (transfer none) (not nullable): the
+ * categories; do not free this memory
+ * Since: 40
+ */
+GsCategory * const *
+gs_category_manager_get_categories (GsCategoryManager *self,
+ gsize *out_n_categories)
+{
+ g_return_val_if_fail (GS_IS_CATEGORY_MANAGER (self), NULL);
+
+ if (out_n_categories != NULL)
+ *out_n_categories = G_N_ELEMENTS (self->categories) - 1;
+
+ return self->categories;
+}