[gnome-software] Allow plugins to add more than one icon



commit 6dc4e947835052f0a8e3e5bf35d17c0f78a23f4d
Author: Richard Hughes <richard hughsie com>
Date:   Fri May 27 15:11:51 2016 +0100

    Allow plugins to add more than one icon
    
    This will allow us to add a stock icon that falls back to a 128x128 cached icon
    on failure to load in the future.

 doc/api/gnome-software-docs.xml                |    2 +-
 src/gs-app.c                                   |   65 ++++++++++++----------
 src/gs-app.h                                   |    4 +-
 src/gs-plugin-loader.c                         |    6 +-
 src/plugins/gs-appstream.c                     |    8 ++--
 src/plugins/gs-plugin-dummy.c                  |    6 +-
 src/plugins/gs-plugin-epiphany.c               |   12 ++++-
 src/plugins/gs-plugin-fedora-distro-upgrades.c |    2 +-
 src/plugins/gs-plugin-flatpak.c                |    4 +-
 src/plugins/gs-plugin-fwupd.c                  |    2 +-
 src/plugins/gs-plugin-icons.c                  |   70 ++++++++++++++----------
 src/plugins/gs-plugin-packagekit.c             |    2 +-
 src/plugins/gs-plugin-shell-extensions.c       |    2 +-
 13 files changed, 106 insertions(+), 79 deletions(-)
---
diff --git a/doc/api/gnome-software-docs.xml b/doc/api/gnome-software-docs.xml
index 1e111a2..2f473f7 100644
--- a/doc/api/gnome-software-docs.xml
+++ b/doc/api/gnome-software-docs.xml
@@ -225,7 +225,7 @@ gs_plugin_add_installed (GsPlugin *plugin,
   icon = as_icon_new ();
   as_icon_set_kind (icon, AS_ICON_KIND_STOCK);
   as_icon_set_name (icon, "input-gaming");
-  gs_app_set_icon (app, icon);
+  gs_app_add_icon (app, icon);
 
   /* return new app */
   gs_app_list_add (list, app);
diff --git a/src/gs-app.c b/src/gs-app.c
index ddb6d60..323fde1 100644
--- a/src/gs-app.c
+++ b/src/gs-app.c
@@ -61,7 +61,7 @@ struct _GsApp
        gchar                   *id;
        gchar                   *name;
        GsAppQuality             name_quality;
-       AsIcon                  *icon;
+       GPtrArray               *icons;
        GPtrArray               *sources;
        GPtrArray               *source_ids;
        gchar                   *project_group;
@@ -111,6 +111,7 @@ struct _GsApp
        gboolean                 license_is_free;
        GsApp                   *runtime;
        GFile                   *local_file;
+       GdkPixbuf               *pixbuf;
 };
 
 enum {
@@ -230,20 +231,22 @@ gs_app_to_string (GsApp *app)
                          gs_app_get_kudos_percentage (app));
        if (app->name != NULL)
                gs_app_kv_lpad (str, "name", app->name);
-       if (app->icon != NULL) {
+       gs_app_kv_printf (str, "pixbuf", "%p", app->pixbuf);
+       for (i = 0; i < app->icons->len; i++) {
+               AsIcon *icon = g_ptr_array_index (app->icons, i);
                gs_app_kv_lpad (str, "icon-kind",
-                               as_icon_kind_to_string (as_icon_get_kind (app->icon)));
+                               as_icon_kind_to_string (as_icon_get_kind (icon)));
                gs_app_kv_printf (str, "icon-pixbuf", "%p",
-                                 as_icon_get_pixbuf (app->icon));
-               if (as_icon_get_name (app->icon) != NULL)
+                                 as_icon_get_pixbuf (icon));
+               if (as_icon_get_name (icon) != NULL)
                        gs_app_kv_lpad (str, "icon-name",
-                                       as_icon_get_name (app->icon));
-               if (as_icon_get_prefix (app->icon) != NULL)
+                                       as_icon_get_name (icon));
+               if (as_icon_get_prefix (icon) != NULL)
                        gs_app_kv_lpad (str, "icon-prefix",
-                                       as_icon_get_prefix (app->icon));
-               if (as_icon_get_filename (app->icon) != NULL)
+                                       as_icon_get_prefix (icon));
+               if (as_icon_get_filename (icon) != NULL)
                        gs_app_kv_lpad (str, "icon-filename",
-                                       as_icon_get_filename (app->icon));
+                                       as_icon_get_filename (icon));
        }
        if (app->match_value != 0)
                gs_app_kv_printf (str, "match-value", "%05x", app->match_value);
@@ -1004,38 +1007,41 @@ GdkPixbuf *
 gs_app_get_pixbuf (GsApp *app)
 {
        g_return_val_if_fail (GS_IS_APP (app), NULL);
-       if (app->icon == NULL)
-               return NULL;
-       return as_icon_get_pixbuf (app->icon);
+       return app->pixbuf;
 }
 
 /**
- * gs_app_get_icon:
+ * gs_app_get_icons:
  * @app: a #GsApp
  *
- * Gets the icon for the application.
+ * Gets the icons for the application.
  *
- * Returns: a #AsIcon, or %NULL for unset
+ * Returns: (transfer none) (element-type AsIcon): an array of icons
  **/
-AsIcon *
-gs_app_get_icon (GsApp *app)
+GPtrArray *
+gs_app_get_icons (GsApp *app)
 {
        g_return_val_if_fail (GS_IS_APP (app), NULL);
-       return app->icon;
+       return app->icons;
 }
 
 /**
- * gs_app_set_icon:
+ * gs_app_add_icon:
  * @app: a #GsApp
- * @icon: a #AsIcon
+ * @icon: a #AsIcon, or %NULL to remove all icons
  *
- * Sets an icon to use for the application.
+ * Adds an icon to use for the application.
+ * If the first icon added cannot be loaded then the next one is tried.
  **/
 void
-gs_app_set_icon (GsApp *app, AsIcon *icon)
+gs_app_add_icon (GsApp *app, AsIcon *icon)
 {
        g_return_if_fail (GS_IS_APP (app));
-       g_set_object (&app->icon, icon);
+       if (icon == NULL) {
+               g_ptr_array_set_size (app->icons, 0);
+               return;
+       }
+       g_ptr_array_add (app->icons, g_object_ref (icon));
 }
 
 /**
@@ -1109,11 +1115,7 @@ void
 gs_app_set_pixbuf (GsApp *app, GdkPixbuf *pixbuf)
 {
        g_return_if_fail (GS_IS_APP (app));
-       if (app->icon == NULL) {
-               g_warning ("trying to set pixbuf on %s with no icon", app->id);
-               return;
-       }
-       as_icon_set_pixbuf (app->icon, pixbuf);
+       g_set_object (&app->pixbuf, pixbuf);
 }
 
 typedef enum {
@@ -2685,7 +2687,6 @@ gs_app_dispose (GObject *object)
 {
        GsApp *app = GS_APP (object);
 
-       g_clear_object (&app->icon);
        g_clear_object (&app->runtime);
 
        g_clear_pointer (&app->addons, g_ptr_array_unref);
@@ -2693,6 +2694,7 @@ gs_app_dispose (GObject *object)
        g_clear_pointer (&app->related, g_ptr_array_unref);
        g_clear_pointer (&app->screenshots, g_ptr_array_unref);
        g_clear_pointer (&app->reviews, g_ptr_array_unref);
+       g_clear_pointer (&app->icons, g_ptr_array_unref);
 
        G_OBJECT_CLASS (gs_app_parent_class)->dispose (object);
 }
@@ -2736,6 +2738,8 @@ gs_app_finalize (GObject *object)
                g_error_free (app->last_error);
        if (app->local_file != NULL)
                g_object_unref (app->local_file);
+       if (app->pixbuf != NULL)
+               g_object_unref (app->pixbuf);
 
        G_OBJECT_CLASS (gs_app_parent_class)->finalize (object);
 }
@@ -2859,6 +2863,7 @@ gs_app_init (GsApp *app)
        app->history = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
        app->screenshots = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
        app->reviews = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+       app->icons = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
        app->metadata = g_hash_table_new_full (g_str_hash,
                                                g_str_equal,
                                                g_free,
diff --git a/src/gs-app.h b/src/gs-app.h
index dc679fb..a152dda 100644
--- a/src/gs-app.h
+++ b/src/gs-app.h
@@ -185,8 +185,8 @@ void                 gs_app_set_management_plugin   (GsApp          *app,
 GdkPixbuf      *gs_app_get_pixbuf              (GsApp          *app);
 void            gs_app_set_pixbuf              (GsApp          *app,
                                                 GdkPixbuf      *pixbuf);
-AsIcon         *gs_app_get_icon                (GsApp          *app);
-void            gs_app_set_icon                (GsApp          *app,
+GPtrArray      *gs_app_get_icons               (GsApp          *app);
+void            gs_app_add_icon                (GsApp          *app,
                                                 AsIcon         *icon);
 GFile          *gs_app_get_local_file          (GsApp          *app);
 void            gs_app_set_local_file          (GsApp          *app,
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index c757ea4..9ebbb98 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -920,7 +920,7 @@ gs_plugin_loader_add_os_update_item (GsAppList *list)
        ic = as_icon_new ();
        as_icon_set_kind (ic, AS_ICON_KIND_STOCK);
        as_icon_set_name (ic, "software-update-available-symbolic");
-       gs_app_set_icon (app_os, ic);
+       gs_app_add_icon (app_os, ic);
        gs_app_list_add (list, app_os);
 }
 
@@ -3933,14 +3933,14 @@ gs_plugin_loader_file_to_app_thread_cb (GTask *task,
        /* check the apps have an icon set */
        for (j = 0; j < gs_app_list_length (state->list); j++) {
                GsApp *app = gs_app_list_index (state->list, j);
-               if (gs_app_get_icon (app) == NULL) {
+               if (gs_app_get_icons(app)->len == 0) {
                        g_autoptr(AsIcon) ic = as_icon_new ();
                        as_icon_set_kind (ic, AS_ICON_KIND_STOCK);
                        if (gs_app_get_kind (app) == AS_APP_KIND_SOURCE)
                                as_icon_set_name (ic, "x-package-repository");
                        else
                                as_icon_set_name (ic, "application-x-executable");
-                       gs_app_set_icon (app, ic);
+                       gs_app_add_icon (app, ic);
                }
        }
 
diff --git a/src/plugins/gs-appstream.c b/src/plugins/gs-appstream.c
index ee5044d..b0cbbfb 100644
--- a/src/plugins/gs-appstream.c
+++ b/src/plugins/gs-appstream.c
@@ -47,10 +47,10 @@ gs_refine_item_pixbuf (GsPlugin *plugin, GsApp *app, AsApp *item)
                        cachedir = g_path_get_basename (fn);
                        as_icon_set_prefix (icon, cachedir);
                }
-               gs_app_set_icon (app, icon);
+               gs_app_add_icon (app, icon);
                break;
        case AS_ICON_KIND_STOCK:
-               gs_app_set_icon (app, icon);
+               gs_app_add_icon (app, icon);
                break;
        case AS_ICON_KIND_LOCAL:
                /* does not exist, so try to find using the icon theme */
@@ -60,7 +60,7 @@ gs_refine_item_pixbuf (GsPlugin *plugin, GsApp *app, AsApp *item)
                                 as_icon_get_name (icon));
                        as_icon_set_kind (icon, AS_ICON_KIND_STOCK);
                }
-               gs_app_set_icon (app, icon);
+               gs_app_add_icon (app, icon);
                break;
        case AS_ICON_KIND_CACHED:
                if (gs_plugin_get_scale (plugin) == 2)
@@ -72,7 +72,7 @@ gs_refine_item_pixbuf (GsPlugin *plugin, GsApp *app, AsApp *item)
                                   as_app_get_id (item));
                        return;
                }
-               gs_app_set_icon (app, icon);
+               gs_app_add_icon (app, icon);
                break;
        default:
                g_warning ("icon kind unknown for %s", as_app_get_id (item));
diff --git a/src/plugins/gs-plugin-dummy.c b/src/plugins/gs-plugin-dummy.c
index 6fbe61c..f0f087f 100644
--- a/src/plugins/gs-plugin-dummy.c
+++ b/src/plugins/gs-plugin-dummy.c
@@ -154,7 +154,7 @@ gs_plugin_add_search (GsPlugin *plugin,
        app = gs_app_new ("chiron.desktop");
        gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "Chiron");
        gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "A teaching application");
-       gs_app_set_icon (app, ic);
+       gs_app_add_icon (app, ic);
        gs_app_set_size_installed (app, 42 * 1024 * 1024);
        gs_app_set_size_download (app, 50 * 1024 * 1024);
        gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
@@ -197,7 +197,7 @@ gs_plugin_add_updates (GsPlugin *plugin,
        gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "A teaching application");
        gs_app_set_update_details (app, "Do not crash when using libvirt.");
        gs_app_set_update_urgency (app, AS_URGENCY_KIND_HIGH);
-       gs_app_set_icon (app, ic);
+       gs_app_add_icon (app, ic);
        gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
        gs_app_set_state (app, AS_APP_STATE_UPDATABLE_LIVE);
        gs_app_set_management_plugin (app, gs_plugin_get_name (plugin));
@@ -491,7 +491,7 @@ gs_plugin_add_distro_upgrades (GsPlugin *plugin,
        gs_app_set_metadata (app, "GnomeSoftware::UpgradeBanner-css",
                             "background: url('" DATADIR "/gnome-software/upgrade-bg.png');"
                             "background-size: 100% 100%;");
-       gs_app_set_icon (app, ic);
+       gs_app_add_icon (app, ic);
        gs_app_list_add (list, app);
 
        gs_plugin_cache_add (plugin, "release-rawhide", app);
diff --git a/src/plugins/gs-plugin-epiphany.c b/src/plugins/gs-plugin-epiphany.c
index 0e3a473..85028c0 100644
--- a/src/plugins/gs-plugin-epiphany.c
+++ b/src/plugins/gs-plugin-epiphany.c
@@ -75,6 +75,7 @@ gs_plugin_app_install (GsPlugin *plugin, GsApp *app,
                       GCancellable *cancellable, GError **error)
 {
        AsIcon *icon;
+       GPtrArray *icons;
        gboolean ret = TRUE;
        gsize kf_length;
        g_autoptr(GError) error_local = NULL;
@@ -108,7 +109,16 @@ gs_plugin_app_install (GsPlugin *plugin, GsApp *app,
        /* symlink icon */
        epi_icon = g_build_filename (epi_dir, "app-icon.png", NULL);
        symlink_icon = g_file_new_for_path (epi_icon);
-       icon = gs_app_get_icon (app);
+       icons = gs_app_get_icons (app);
+       if (icons->len == 0) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "no icons for %s",
+                            gs_app_get_id (app));
+               return FALSE;
+       }
+       icon = g_ptr_array_index (icons, 0);
        ret = g_file_make_symbolic_link (symlink_icon,
                                         as_icon_get_filename (icon),
                                         NULL,
diff --git a/src/plugins/gs-plugin-fedora-distro-upgrades.c b/src/plugins/gs-plugin-fedora-distro-upgrades.c
index 9af2cfc..262ddf8 100644
--- a/src/plugins/gs-plugin-fedora-distro-upgrades.c
+++ b/src/plugins/gs-plugin-fedora-distro-upgrades.c
@@ -372,7 +372,7 @@ gs_plugin_add_distro_upgrades (GsPlugin *plugin,
                gs_app_add_quirk (app, AS_APP_QUIRK_PROVENANCE);
                gs_app_add_quirk (app, AS_APP_QUIRK_NOT_REVIEWABLE);
                gs_app_set_origin_ui (app, distro_info->name);
-               gs_app_set_icon (app, ic);
+               gs_app_add_icon (app, ic);
                gs_app_set_management_plugin (app, "packagekit");
 
                /* just use the release notes */
diff --git a/src/plugins/gs-plugin-flatpak.c b/src/plugins/gs-plugin-flatpak.c
index b05fc91..1a17893 100644
--- a/src/plugins/gs-plugin-flatpak.c
+++ b/src/plugins/gs-plugin-flatpak.c
@@ -354,7 +354,7 @@ gs_plugin_flatpak_create_installed (GsPlugin *plugin,
                icon = as_icon_new ();
                as_icon_set_kind (icon, AS_ICON_KIND_STOCK);
                as_icon_set_name (icon, "system-run-symbolic");
-               gs_app_set_icon (app, icon);
+               gs_app_add_icon (app, icon);
                break;
        default:
                g_set_error_literal (error,
@@ -1399,7 +1399,7 @@ gs_plugin_file_to_app (GsPlugin *plugin,
                icon = as_icon_new ();
                as_icon_set_kind (icon, AS_ICON_KIND_STOCK);
                as_icon_set_name (icon, "application-x-executable");
-               gs_app_set_icon (app, icon);
+               gs_app_add_icon (app, icon);
        }
 
        /* not quite true: this just means we can update this specific app */
diff --git a/src/plugins/gs-plugin-fwupd.c b/src/plugins/gs-plugin-fwupd.c
index c8305ec..a13c04d 100644
--- a/src/plugins/gs-plugin-fwupd.c
+++ b/src/plugins/gs-plugin-fwupd.c
@@ -214,7 +214,7 @@ gs_plugin_fwupd_new_app_from_results (FwupdResult *res)
        icon = as_icon_new ();
        as_icon_set_kind (icon, AS_ICON_KIND_STOCK);
        as_icon_set_name (icon, "application-x-firmware");
-       gs_app_set_icon (app, icon);
+       gs_app_add_icon (app, icon);
 
        if (fwupd_result_get_update_id (res) != NULL) {
                gs_app_set_id (app, fwupd_result_get_update_id (res));
diff --git a/src/plugins/gs-plugin-icons.c b/src/plugins/gs-plugin-icons.c
index e6f3cae..16d47cb 100644
--- a/src/plugins/gs-plugin-icons.c
+++ b/src/plugins/gs-plugin-icons.c
@@ -221,8 +221,8 @@ gs_plugin_refine_app (GsPlugin *plugin,
                      GCancellable *cancellable,
                      GError **error)
 {
-       AsIcon *icon;
-       g_autoptr(GdkPixbuf) pixbuf = NULL;
+       GPtrArray *icons;
+       guint i;
 
        /* not required */
        if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON) == 0)
@@ -231,34 +231,46 @@ gs_plugin_refine_app (GsPlugin *plugin,
        /* invalid */
        if (gs_app_get_pixbuf (app) != NULL)
                return TRUE;
-       icon = gs_app_get_icon (app);
-       if (icon == NULL)
-               return TRUE;
 
-       /* handle different icon types */
-       switch (as_icon_get_kind (icon)) {
-       case AS_ICON_KIND_LOCAL:
-               pixbuf = gs_plugin_icons_load_local (plugin, icon, error);
-               break;
-       case AS_ICON_KIND_STOCK:
-               pixbuf = gs_plugin_icons_load_stock (plugin, icon, error);
-               break;
-       case AS_ICON_KIND_REMOTE:
-               pixbuf = gs_plugin_icons_load_remote (plugin, icon, error);
-               break;
-       case AS_ICON_KIND_CACHED:
-               pixbuf = gs_plugin_icons_load_cached (plugin, icon, error);
-               break;
-       default:
-               g_set_error (error,
-                            GS_PLUGIN_ERROR,
-                            GS_PLUGIN_ERROR_FAILED,
-                            "icon kind '%s' unknown",
-                            as_icon_kind_to_string (as_icon_get_kind (icon)));
-               break;
+       /* process all icons */
+       icons = gs_app_get_icons (app);
+       for (i = 0; i < icons->len; i++) {
+               AsIcon *icon = g_ptr_array_index (icons, i);
+               g_autoptr(GdkPixbuf) pixbuf = NULL;
+               g_autoptr(GError) error_local = NULL;
+
+               /* handle different icon types */
+               switch (as_icon_get_kind (icon)) {
+               case AS_ICON_KIND_LOCAL:
+                       pixbuf = gs_plugin_icons_load_local (plugin, icon, &error_local);
+                       break;
+               case AS_ICON_KIND_STOCK:
+                       pixbuf = gs_plugin_icons_load_stock (plugin, icon, &error_local);
+                       break;
+               case AS_ICON_KIND_REMOTE:
+                       pixbuf = gs_plugin_icons_load_remote (plugin, icon, &error_local);
+                       break;
+               case AS_ICON_KIND_CACHED:
+                       pixbuf = gs_plugin_icons_load_cached (plugin, icon, &error_local);
+                       break;
+               default:
+                       g_set_error (&error_local,
+                                    GS_PLUGIN_ERROR,
+                                    GS_PLUGIN_ERROR_FAILED,
+                                    "icon kind '%s' unknown",
+                                    as_icon_kind_to_string (as_icon_get_kind (icon)));
+                       break;
+               }
+               if (pixbuf != NULL) {
+                       gs_app_set_pixbuf (app, pixbuf);
+                       break;
+               }
+
+               /* we failed, but keep going */
+               g_debug ("failed to load icon for %s: %s",
+                        gs_app_get_id (app),
+                        error_local->message);
        }
-       if (pixbuf == NULL)
-               return FALSE;
-       gs_app_set_pixbuf (app, pixbuf);
+
        return TRUE;
 }
diff --git a/src/plugins/gs-plugin-packagekit.c b/src/plugins/gs-plugin-packagekit.c
index 331b773..57e4ffc 100644
--- a/src/plugins/gs-plugin-packagekit.c
+++ b/src/plugins/gs-plugin-packagekit.c
@@ -401,7 +401,7 @@ gs_plugin_app_install (GsPlugin *plugin,
 
                /* get the new icon from the package */
                gs_app_set_local_file (app, NULL);
-               gs_app_set_icon (app, NULL);
+               gs_app_add_icon (app, NULL);
                gs_app_set_pixbuf (app, NULL);
                break;
        default:
diff --git a/src/plugins/gs-plugin-shell-extensions.c b/src/plugins/gs-plugin-shell-extensions.c
index a8b219c..daae0fd 100644
--- a/src/plugins/gs-plugin-shell-extensions.c
+++ b/src/plugins/gs-plugin-shell-extensions.c
@@ -201,7 +201,7 @@ gs_plugin_shell_extensions_add_app (GsPlugin *plugin,
        ic = as_icon_new ();
        as_icon_set_kind (ic, AS_ICON_KIND_STOCK);
        as_icon_set_name (ic, "application-x-addon-symbolic");
-       gs_app_set_icon (app, ic);
+       gs_app_add_icon (app, ic);
 
        /* add categories */
        gs_app_add_category (app, "Addons");


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