336 lines
13 KiB
Diff
336 lines
13 KiB
Diff
From f7e394840ff84ae8b55f13ff9692d6b02e8e6ea5 Mon Sep 17 00:00:00 2001
|
|
Date: Wed, 20 Dec 2023 12:21:24 +0100
|
|
Subject: [PATCH 1/3] gs-appstream: Increase limit to category apps lookup
|
|
|
|
The Overview page currently checks for 100 apps in all categories.
|
|
Lookup for the same count per category.
|
|
|
|
Note: The counts are not accurate, same apps can be in multiple
|
|
sub-categories, thus the parent category count suffers of duplicity,
|
|
which the following commit will correct in a different way than
|
|
checking for id duplicity.
|
|
---
|
|
lib/gs-appstream.c | 4 ++--
|
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/lib/gs-appstream.c b/lib/gs-appstream.c
|
|
index f110e3c47..d600cac53 100644
|
|
--- a/lib/gs-appstream.c
|
|
+++ b/lib/gs-appstream.c
|
|
@@ -1836,7 +1836,8 @@ static guint
|
|
gs_appstream_count_component_for_groups (XbSilo *silo,
|
|
const gchar *desktop_group)
|
|
{
|
|
- guint limit = 10;
|
|
+ /* the overview page checks for 100 apps, then try to get them */
|
|
+ const guint limit = 100;
|
|
g_autofree gchar *xpath = NULL;
|
|
g_auto(GStrv) split = g_strsplit (desktop_group, "::", -1);
|
|
g_autoptr(GPtrArray) array = NULL;
|
|
@@ -1896,7 +1897,6 @@ gs_appstream_refine_category_sizes (XbSilo *silo,
|
|
}
|
|
}
|
|
}
|
|
- continue;
|
|
}
|
|
return TRUE;
|
|
}
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 617af44a56f6f62e07fd3fc13ae43d688aa3b85f Mon Sep 17 00:00:00 2001
|
|
Date: Wed, 20 Dec 2023 12:24:25 +0100
|
|
Subject: [PATCH 2/3] gs-overview-page: Add debug prints about discovered
|
|
categories
|
|
|
|
For easier debugging, to see what the plugins returned.
|
|
---
|
|
src/gs-overview-page.c | 2 ++
|
|
1 file changed, 2 insertions(+)
|
|
|
|
diff --git a/src/gs-overview-page.c b/src/gs-overview-page.c
|
|
index 6ef5079e9..72000e257 100644
|
|
--- a/src/gs-overview-page.c
|
|
+++ b/src/gs-overview-page.c
|
|
@@ -496,6 +496,7 @@ gs_overview_page_get_categories_cb (GObject *source_object,
|
|
|
|
if (gs_category_get_icon_name (cat) != NULL) {
|
|
found_apps_cnt += gs_category_get_size (cat);
|
|
+ g_debug ("overview page found category '%s' which claims %u apps", gs_category_get_name (cat), gs_category_get_size (cat));
|
|
flowbox = GTK_FLOW_BOX (self->flowbox_categories);
|
|
} else
|
|
flowbox = GTK_FLOW_BOX (self->flowbox_iconless_categories);
|
|
@@ -524,6 +525,7 @@ out:
|
|
* See https://gitlab.gnome.org/GNOME/gnome-software/-/issues/2053 */
|
|
gtk_widget_set_visible (self->flowbox_categories, found_apps_cnt >= MIN_CATEGORIES_APPS);
|
|
|
|
+ g_debug ("overview page found %u category apps", found_apps_cnt);
|
|
if (found_apps_cnt < MIN_CATEGORIES_APPS && found_apps_cnt > 0) {
|
|
GsPluginListAppsFlags flags = GS_PLUGIN_LIST_APPS_FLAGS_INTERACTIVE;
|
|
GatherAppsData *gather_apps_data = g_new0 (GatherAppsData, 1);
|
|
--
|
|
GitLab
|
|
|
|
|
|
From 98086eca23dbd46284039722887852e8c760a0fe Mon Sep 17 00:00:00 2001
|
|
Date: Wed, 20 Dec 2023 12:32:21 +0100
|
|
Subject: [PATCH 3/3] gs-overview-page: Verify category sizes
|
|
|
|
The "list-categories" job can set inaccurate sizes for the categories,
|
|
thus check the actual category content to operate with proper numbers.
|
|
For example the appstream data can have information about apps, which
|
|
no plugin can provide due to disabled repository.
|
|
---
|
|
src/gs-overview-page.c | 176 +++++++++++++++++++++++++++++++++++------
|
|
1 file changed, 153 insertions(+), 23 deletions(-)
|
|
|
|
diff --git a/src/gs-overview-page.c b/src/gs-overview-page.c
|
|
index 72000e257..3ec689ac1 100644
|
|
--- a/src/gs-overview-page.c
|
|
+++ b/src/gs-overview-page.c
|
|
@@ -440,6 +440,7 @@ category_activated_cb (GsOverviewPage *self, GsCategoryTile *tile)
|
|
typedef struct {
|
|
GsOverviewPage *page; /* (unowned) */
|
|
GsPluginJobListCategories *job; /* (owned) */
|
|
+ guint n_pending_ops;
|
|
} GetCategoriesData;
|
|
|
|
static void
|
|
@@ -451,31 +452,18 @@ get_categories_data_free (GetCategoriesData *data)
|
|
|
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GetCategoriesData, get_categories_data_free)
|
|
|
|
-static void
|
|
-gs_overview_page_get_categories_cb (GObject *source_object,
|
|
- GAsyncResult *res,
|
|
- gpointer user_data)
|
|
+static guint
|
|
+update_categories_sections (GsOverviewPage *self,
|
|
+ GPtrArray *list) /* (element-type GsCategory) */
|
|
{
|
|
- g_autoptr(GetCategoriesData) data = g_steal_pointer (&user_data);
|
|
- GsOverviewPage *self = GS_OVERVIEW_PAGE (data->page);
|
|
- GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source_object);
|
|
- guint i;
|
|
GsCategory *cat;
|
|
GtkFlowBox *flowbox;
|
|
GtkWidget *tile;
|
|
guint added_cnt = 0;
|
|
guint found_apps_cnt = 0;
|
|
- g_autoptr(GError) error = NULL;
|
|
- GPtrArray *list = NULL; /* (element-type GsCategory) */
|
|
|
|
- if (!gs_plugin_loader_job_action_finish (plugin_loader, res, &error)) {
|
|
- if (!g_error_matches (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_CANCELLED) &&
|
|
- !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
- g_warning ("failed to get categories: %s", error->message);
|
|
- goto out;
|
|
- }
|
|
-
|
|
- list = gs_plugin_job_list_categories_get_result_list (data->job);
|
|
+ if (g_cancellable_is_cancelled (self->cancellable))
|
|
+ return found_apps_cnt;
|
|
|
|
gs_widget_remove_all (self->flowbox_categories, (GsRemoveFunc) gtk_flow_box_remove);
|
|
gs_widget_remove_all (self->flowbox_iconless_categories, (GsRemoveFunc) gtk_flow_box_remove);
|
|
@@ -488,7 +476,7 @@ gs_overview_page_get_categories_cb (GObject *source_object,
|
|
* be visually important, and are listed near the top of the page.
|
|
* Categories without icons are listed in a separate flowbox at the
|
|
* bottom of the page. Typically they are addons. */
|
|
- for (i = 0; i < list->len; i++) {
|
|
+ for (guint i = 0; list != NULL && i < list->len; i++) {
|
|
cat = GS_CATEGORY (g_ptr_array_index (list, i));
|
|
if (gs_category_get_size (cat) == 0)
|
|
continue;
|
|
@@ -510,7 +498,6 @@ gs_overview_page_get_categories_cb (GObject *source_object,
|
|
g_object_ref (cat));
|
|
}
|
|
|
|
-out:
|
|
/* Show the heading for the iconless categories iff there are any. */
|
|
gtk_widget_set_visible (self->iconless_categories_heading,
|
|
gtk_flow_box_get_child_at_index (GTK_FLOW_BOX (self->flowbox_iconless_categories), 0) != NULL);
|
|
@@ -525,6 +512,27 @@ out:
|
|
* See https://gitlab.gnome.org/GNOME/gnome-software/-/issues/2053 */
|
|
gtk_widget_set_visible (self->flowbox_categories, found_apps_cnt >= MIN_CATEGORIES_APPS);
|
|
|
|
+ return found_apps_cnt;
|
|
+}
|
|
+
|
|
+static void
|
|
+finish_verify_category_op (GetCategoriesData *op_data)
|
|
+{
|
|
+ g_autoptr(GetCategoriesData) data = g_steal_pointer (&op_data);
|
|
+ GsOverviewPage *self = GS_OVERVIEW_PAGE (data->page);
|
|
+ guint i, found_apps_cnt;
|
|
+ GPtrArray *list; /* (element-type GsCategory) */
|
|
+
|
|
+ data->n_pending_ops--;
|
|
+ if (data->n_pending_ops > 0) {
|
|
+ /* to not be freed */
|
|
+ g_steal_pointer (&data);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ list = gs_plugin_job_list_categories_get_result_list (data->job);
|
|
+ found_apps_cnt = update_categories_sections (self, list);
|
|
+
|
|
g_debug ("overview page found %u category apps", found_apps_cnt);
|
|
if (found_apps_cnt < MIN_CATEGORIES_APPS && found_apps_cnt > 0) {
|
|
GsPluginListAppsFlags flags = GS_PLUGIN_LIST_APPS_FLAGS_INTERACTIVE;
|
|
@@ -534,10 +542,10 @@ out:
|
|
gather_apps_data->self = g_object_ref (self);
|
|
gather_apps_data->list = gs_app_list_new ();
|
|
|
|
- for (i = 0; i < list->len; i++) {
|
|
+ for (i = 0; list != NULL && i < list->len; i++) {
|
|
g_autoptr(GsPluginJob) plugin_job = NULL;
|
|
g_autoptr(GsAppQuery) query = NULL;
|
|
- GsCategory *subcat;
|
|
+ GsCategory *cat, *subcat;
|
|
|
|
cat = GS_CATEGORY (g_ptr_array_index (list, i));
|
|
if (gs_category_get_size (cat) == 0 ||
|
|
@@ -578,6 +586,128 @@ out:
|
|
gs_overview_page_decrement_action_cnt (self);
|
|
}
|
|
|
|
+typedef struct {
|
|
+ GsOverviewPage *page; /* (unowned) */
|
|
+ GetCategoriesData *op_data; /* (unowned) */
|
|
+ GsCategory *category; /* (owned) */
|
|
+} VerifyCategoryData;
|
|
+
|
|
+static void
|
|
+verify_category_data_free (VerifyCategoryData *data)
|
|
+{
|
|
+ g_clear_object (&data->category);
|
|
+ g_free (data);
|
|
+}
|
|
+
|
|
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (VerifyCategoryData, verify_category_data_free)
|
|
+
|
|
+static void
|
|
+gs_overview_page_verify_category_cb (GObject *source_object,
|
|
+ GAsyncResult *res,
|
|
+ gpointer user_data)
|
|
+{
|
|
+ g_autoptr(VerifyCategoryData) data = user_data;
|
|
+ GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source_object);
|
|
+ g_autoptr(GError) local_error = NULL;
|
|
+ g_autoptr(GsAppList) list = NULL;
|
|
+
|
|
+ list = gs_plugin_loader_job_process_finish (plugin_loader, res, &local_error);
|
|
+ if (list == NULL) {
|
|
+ if (!g_error_matches (local_error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_CANCELLED) &&
|
|
+ !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
+ g_warning ("failed to get apps for category: %s", local_error->message);
|
|
+ g_debug ("Failed to get category content '%s' for overview page: %s", gs_category_get_id (data->category), local_error->message);
|
|
+ } else {
|
|
+ GsCategory *all_subcat = gs_category_find_child (data->category, "all");
|
|
+ guint size = gs_app_list_length (list);
|
|
+ g_debug ("overview page verify category '%s' size:%u~>%u subcat:'%s' size:%u~>%u",
|
|
+ gs_category_get_id (data->category), gs_category_get_size (data->category), size,
|
|
+ gs_category_get_id (all_subcat), gs_category_get_size (all_subcat), size);
|
|
+ gs_category_set_size (data->category, size);
|
|
+ gs_category_set_size (all_subcat, size);
|
|
+ }
|
|
+
|
|
+ finish_verify_category_op (data->op_data);
|
|
+}
|
|
+
|
|
+static void
|
|
+gs_overview_page_get_categories_list_cb (GObject *source_object,
|
|
+ GAsyncResult *res,
|
|
+ gpointer user_data)
|
|
+{
|
|
+ g_autoptr(GetCategoriesData) data = g_steal_pointer (&user_data);
|
|
+ GsOverviewPage *self = GS_OVERVIEW_PAGE (data->page);
|
|
+ GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source_object);
|
|
+ g_autoptr(GError) error = NULL;
|
|
+
|
|
+ g_assert (data->n_pending_ops == 0);
|
|
+
|
|
+ data->n_pending_ops++;
|
|
+
|
|
+ /* The apps can be mentioned in the appstream data, but no plugin may provide actual app,
|
|
+ thus try to get the content as the Categories page and fine tune the numbers appropriately. */
|
|
+ if (!gs_plugin_loader_job_action_finish (plugin_loader, res, &error)) {
|
|
+ if (!g_error_matches (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_CANCELLED) &&
|
|
+ !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
+ g_warning ("failed to get categories: %s", error->message);
|
|
+ } else {
|
|
+ g_autoptr(GPtrArray) verify_categories = NULL; /* (element-type GsCategory) */
|
|
+ GPtrArray *list = NULL; /* (element-type GsCategory) */
|
|
+ guint found_apps_cnt;
|
|
+
|
|
+ list = gs_plugin_job_list_categories_get_result_list (data->job);
|
|
+ found_apps_cnt = update_categories_sections (self, list);
|
|
+
|
|
+ if (found_apps_cnt >= MIN_CATEGORIES_APPS) {
|
|
+ verify_categories = g_ptr_array_new_full (list != NULL ? list->len : 0, g_object_unref);
|
|
+ for (guint i = 0; list != NULL && i < list->len; i++) {
|
|
+ GsCategory *category = g_ptr_array_index (list, i);
|
|
+ if (gs_category_get_size (category) > 0 &&
|
|
+ gs_category_find_child (category, "all") != NULL) {
|
|
+ g_ptr_array_add (verify_categories, g_object_ref (category));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (verify_categories != NULL && verify_categories->len > 0 && !g_cancellable_is_cancelled (self->cancellable)) {
|
|
+ for (guint i = 0; i < verify_categories->len; i++) {
|
|
+ GsCategory *category = g_ptr_array_index (verify_categories, i);
|
|
+ GsCategory *all_subcat = gs_category_find_child (category, "all");
|
|
+ g_autoptr(GsAppQuery) query = NULL;
|
|
+ g_autoptr(GsPluginJob) plugin_job = NULL;
|
|
+ VerifyCategoryData *ver_data;
|
|
+
|
|
+ g_assert (all_subcat != NULL);
|
|
+
|
|
+ data->n_pending_ops++;
|
|
+
|
|
+ ver_data = g_new0 (VerifyCategoryData, 1);
|
|
+ ver_data->page = self;
|
|
+ ver_data->op_data = data;
|
|
+ ver_data->category = g_object_ref (category);
|
|
+
|
|
+ query = gs_app_query_new ("category", all_subcat,
|
|
+ "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ID,
|
|
+ "dedupe-flags", GS_APP_LIST_FILTER_FLAG_KEY_ID_PROVIDES,
|
|
+ "license-type", gs_page_get_query_license_type (GS_PAGE (self)),
|
|
+ /*"developer-verified-type", gs_page_get_query_developer_verified_type (GS_PAGE (self)),*/
|
|
+ NULL);
|
|
+ plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
|
|
+ gs_plugin_loader_job_process_async (plugin_loader,
|
|
+ plugin_job,
|
|
+ self->cancellable,
|
|
+ gs_overview_page_verify_category_cb,
|
|
+ ver_data);
|
|
+ }
|
|
+
|
|
+ finish_verify_category_op (g_steal_pointer (&data));
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ finish_verify_category_op (g_steal_pointer (&data));
|
|
+}
|
|
+
|
|
static void
|
|
third_party_destroy_cb (GtkWindow *window,
|
|
GsOverviewPage *self)
|
|
@@ -967,7 +1097,7 @@ gs_overview_page_load (GsOverviewPage *self)
|
|
data->job = g_object_ref (GS_PLUGIN_JOB_LIST_CATEGORIES (plugin_job));
|
|
|
|
gs_plugin_loader_job_process_async (self->plugin_loader, plugin_job,
|
|
- self->cancellable, gs_overview_page_get_categories_cb,
|
|
+ self->cancellable, gs_overview_page_get_categories_list_cb,
|
|
g_steal_pointer (&data));
|
|
self->action_cnt++;
|
|
}
|
|
--
|
|
GitLab
|
|
|