summaryrefslogtreecommitdiffstats
path: root/lib/gs-category-manager.c
blob: 0e372644a79a239a1401bcb993e2bd96bcbf1abc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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;
}