[gnome-software/1514-gnome-os-most-system-apps-have-no-icons-in-installed-list] appstream: Lookup app icons from .desktop files, if none found



commit 3d8083ee82f0d4508f49a8051de18808bd36c3dd
Author: Milan Crha <mcrha redhat com>
Date:   Wed Apr 13 12:29:39 2022 +0200

    appstream: Lookup app icons from .desktop files, if none found
    
    The installed apps, coming from .appdata.xml files, usually do not have
    set any icon. Try to lookup icons from the .desktop files in such cases,
    thus, when the .appdata.xml files have properly set references between
    then and their .desktop files, the expected icons are shown.
    
    Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/1514

 lib/gs-appstream.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 83 insertions(+), 7 deletions(-)
---
diff --git a/lib/gs-appstream.c b/lib/gs-appstream.c
index b0aea1f3e..ef0b03a93 100644
--- a/lib/gs-appstream.c
+++ b/lib/gs-appstream.c
@@ -251,13 +251,11 @@ app_add_icon (GsApp  *app,
 }
 
 static void
-gs_appstream_refine_icon (GsApp *app, XbNode *component)
+traverse_component_icons (GsApp *app,
+                         XbNode *component,
+                         GPtrArray *icons)
 {
-       g_autoptr(GError) local_error = NULL;
-       g_autoptr(GPtrArray) icons = NULL;  /* (element-type XbNode) */
-
-       icons = xb_node_query (component, "icon", 0, &local_error);
-       if (icons == NULL)
+       if (!icons)
                return;
 
        /* This code deliberately does *not* check that the icon files or theme
@@ -281,6 +279,84 @@ gs_appstream_refine_icon (GsApp *app, XbNode *component)
        }
 }
 
+static void
+traverse_components_xpath_for_icons (GsApp *app,
+                                    XbSilo *silo,
+                                    const gchar *xpath,
+                                    gboolean try_with_launchable)
+{
+       g_autoptr(GPtrArray) components = NULL;
+       g_autoptr(GError) local_error = NULL;
+
+       components = xb_silo_query (silo, xpath, 0, &local_error);
+       if (components) {
+               for (guint i = 0; i < components->len; i++) {
+                       g_autoptr(GPtrArray) icons = NULL;  /* (element-type XbNode) */
+                       XbNode *component = g_ptr_array_index (components, i);
+                       g_autofree gchar *xml = xb_node_export (component, 0, NULL);
+                       icons = xb_node_query (component, "icon", 0, NULL);
+                       traverse_component_icons (app, component, icons);
+
+                       if (try_with_launchable && gs_app_get_icons (app) == NULL) {
+                               const gchar *launchable_id = xb_node_query_text (component, 
"launchable[@type='desktop-id']", NULL);
+                               if (launchable_id != NULL) {
+                                       g_autofree gchar *xpath2 = NULL;
+
+                                       /* Inherit the icon from the .desktop file */
+                                       xpath2 = g_strdup_printf 
("/component[@type='desktop-application']/launchable[@type='desktop-id'][text()='%s']/..",
+                                                                 launchable_id);
+                                       traverse_components_xpath_for_icons (app, silo, xpath2, FALSE);
+                               }
+                       }
+               }
+       }
+}
+
+static void
+gs_appstream_refine_icon (GsApp *app,
+                         XbSilo *silo,
+                         XbNode *component)
+{
+       g_autoptr(GError) local_error = NULL;
+       g_autoptr(GPtrArray) icons = NULL;  /* (element-type XbNode) */
+
+       icons = xb_node_query (component, "icon", 0, &local_error);
+       traverse_component_icons (app, component, icons);
+       g_clear_pointer (&icons, g_ptr_array_unref);
+
+       /* If no icon found, try to inherit the icon from the .desktop file */
+       if (gs_app_get_icons (app) == NULL) {
+               g_autofree gchar *xpath = NULL;
+               const gchar *launchable_id = xb_node_query_text (component, "launchable[@type='desktop-id']", 
NULL);
+               if (launchable_id != NULL) {
+                       xpath = g_strdup_printf 
("/component[@type='desktop-application']/launchable[@type='desktop-id'][text()='%s']/..",
+                                                launchable_id);
+                       traverse_components_xpath_for_icons (app, silo, xpath, FALSE);
+                       g_clear_pointer (&xpath, g_free);
+               }
+
+               xpath = g_strdup_printf 
("/component[@type='desktop-application']/launchable[@type='desktop-id'][text()='%s']/..",
+                                        gs_app_get_id (app));
+               traverse_components_xpath_for_icons (app, silo, xpath, FALSE);
+       }
+
+       if (gs_app_get_icons (app) == NULL) {
+               const gchar *provides_id = xb_node_query_text (component, "provides/id", NULL);
+               if (provides_id != NULL) {
+                       g_autofree gchar *xpath = NULL;
+
+                       xpath = g_strdup_printf 
("/components/component[@type='desktop-application']/id[text()='%s']/..",
+                                                provides_id);
+                       traverse_components_xpath_for_icons (app, silo, xpath, TRUE);
+                       g_clear_pointer (&xpath, g_free);
+
+                       xpath = g_strdup_printf ("/component[@type='desktop-application']/id[text()='%s']/..",
+                                                provides_id);
+                       traverse_components_xpath_for_icons (app, silo, xpath, TRUE);
+               }
+       }
+}
+
 static gboolean
 gs_appstream_refine_add_addons (GsPlugin *plugin,
                                GsApp *app,
@@ -1101,7 +1177,7 @@ gs_appstream_refine_app (GsPlugin *plugin,
        /* set icon */
        if ((refine_flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON) > 0 &&
            gs_app_get_icons (app) == NULL)
-               gs_appstream_refine_icon (app, component);
+               gs_appstream_refine_icon (app, silo, component);
 
        /* set categories */
        if (refine_flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_CATEGORIES) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]