diff options
-rw-r--r-- | client/as-util.c | 14 | ||||
-rw-r--r-- | libappstream-builder/asb-app.c | 49 | ||||
-rw-r--r-- | libappstream-builder/asb-task.c | 2 | ||||
-rw-r--r-- | libappstream-builder/plugins/asb-plugin-desktop.c | 40 | ||||
-rw-r--r-- | libappstream-builder/plugins/asb-plugin-font.c | 13 | ||||
-rw-r--r-- | libappstream-builder/plugins/asb-plugin-gstreamer.c | 9 | ||||
-rw-r--r-- | libappstream-builder/plugins/asb-plugin-ibus-sql.c | 10 | ||||
-rw-r--r-- | libappstream-builder/plugins/asb-plugin-ibus-xml.c | 9 | ||||
-rw-r--r-- | libappstream-glib/as-app.c | 235 | ||||
-rw-r--r-- | libappstream-glib/as-app.h | 15 | ||||
-rw-r--r-- | libappstream-glib/as-self-test.c | 58 | ||||
-rw-r--r-- | libappstream-glib/as-store.c | 16 |
12 files changed, 291 insertions, 179 deletions
diff --git a/client/as-util.c b/client/as-util.c index cda081d..46716db 100644 --- a/client/as-util.c +++ b/client/as-util.c @@ -647,10 +647,10 @@ as_util_appdata_from_desktop (AsUtilPrivate *priv, gchar **values, GError **erro } /* set things that don't belong in the AppData file */ - as_app_set_icon (app, NULL, -1); g_ptr_array_set_size (as_app_get_keywords (app, NULL), 0); g_ptr_array_set_size (as_app_get_categories (app), 0); g_ptr_array_set_size (as_app_get_mimetypes (app), 0); + g_ptr_array_set_size (as_app_get_icons (app), 0); /* add urls */ as_app_add_url (app, AS_URL_KIND_HOMEPAGE, @@ -2092,11 +2092,13 @@ as_util_validate_strict (AsUtilPrivate *priv, gchar **values, GError **error) static gboolean as_util_check_root_app_icon (AsApp *app, GError **error) { + AsIcon *icon_default; _cleanup_free_ gchar *icon = NULL; _cleanup_object_unref_ GdkPixbuf *pb = NULL; /* nothing found */ - if (as_app_get_icon (app) == NULL) { + icon_default = as_app_get_icon_default (app); + if (icon_default == NULL) { g_set_error (error, AS_ERROR, AS_ERROR_FAILED, @@ -2106,18 +2108,18 @@ as_util_check_root_app_icon (AsApp *app, GError **error) } /* is stock icon */ - if (as_utils_is_stock_icon_name (as_app_get_icon (app))) + if (as_utils_is_stock_icon_name (as_icon_get_name (icon_default))) return TRUE; /* can we find it */ icon = as_utils_find_icon_filename (g_getenv ("DESTDIR"), - as_app_get_icon (app), + as_icon_get_name (icon_default), error); if (icon == NULL) { g_prefix_error (error, "%s missing icon %s: ", as_app_get_id (app), - as_app_get_icon (app)); + as_icon_get_name (icon_default)); return FALSE; } @@ -2127,7 +2129,7 @@ as_util_check_root_app_icon (AsApp *app, GError **error) g_prefix_error (error, "%s invalid icon %s: ", as_app_get_id (app), - as_app_get_icon (app)); + as_icon_get_name (icon_default)); return FALSE; } diff --git a/libappstream-builder/asb-app.c b/libappstream-builder/asb-app.c index c5acbcf..09d4ed6 100644 --- a/libappstream-builder/asb-app.c +++ b/libappstream-builder/asb-app.c @@ -39,7 +39,6 @@ typedef struct _AsbAppPrivate AsbAppPrivate; struct _AsbAppPrivate { GPtrArray *requires_appdata; - GPtrArray *pixbufs; /* of GdkPixbuf */ AsbPackage *pkg; gboolean ignore_requires_appdata; gboolean hidpi_enabled; @@ -59,7 +58,6 @@ asb_app_finalize (GObject *object) AsbAppPrivate *priv = GET_PRIVATE (app); g_ptr_array_unref (priv->requires_appdata); - g_ptr_array_unref (priv->pixbufs); if (priv->pkg != NULL) g_object_unref (priv->pkg); @@ -74,7 +72,6 @@ asb_app_init (AsbApp *app) { AsbAppPrivate *priv = GET_PRIVATE (app); priv->requires_appdata = g_ptr_array_new_with_free_func (g_free); - priv->pixbufs = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); /* all untrusted */ as_app_set_trust_flags (AS_APP (app), @@ -165,22 +162,6 @@ asb_app_set_requires_appdata (AsbApp *app, gboolean requires_appdata) } /** - * asb_app_add_pixbuf: - * @app: A #AsbApp - * @pixbuf: a #GdkPixbuf - * - * Adds an icon for the application. - * - * Since: 0.3.1 - **/ -void -asb_app_add_pixbuf (AsbApp *app, GdkPixbuf *pixbuf) -{ - AsbAppPrivate *priv = GET_PRIVATE (app); - g_ptr_array_add (priv->pixbufs, g_object_ref (pixbuf)); -} - -/** * asb_app_get_requires_appdata: * @app: A #AsbApp * @@ -323,35 +304,51 @@ gboolean asb_app_save_resources (AsbApp *app, GError **error) { AsbAppPrivate *priv = GET_PRIVATE (app); + AsIcon *icon; AsScreenshot *ss; - guint i; GdkPixbuf *pixbuf; + GPtrArray *icons; GPtrArray *screenshots; + guint i; /* any non-stock icon set */ - for (i = 0; i < priv->pixbufs->len; i++) { + icons = as_app_get_icons (AS_APP (app)); + for (i = 0; i < icons->len; i++) { const gchar *tmpdir; _cleanup_free_ gchar *filename = NULL; _cleanup_free_ gchar *size_str = NULL; + /* don't save stock icons */ + icon = g_ptr_array_index (icons, i); + if (as_icon_get_kind (icon) == AS_ICON_KIND_STOCK) + continue; + /* save to disk */ - pixbuf = g_ptr_array_index (priv->pixbufs, i); tmpdir = asb_package_get_config (priv->pkg, "TempDir"); if (priv->hidpi_enabled) { size_str = g_strdup_printf ("%ux%u", - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf)); + as_icon_get_width (icon), + as_icon_get_height (icon)); filename = g_build_filename (tmpdir, "icons", size_str, - as_app_get_icon (AS_APP (app)), + as_icon_get_name (icon), NULL); } else { filename = g_build_filename (tmpdir, "icons", - as_app_get_icon (AS_APP (app)), + as_icon_get_name (icon), NULL); } + pixbuf = as_icon_get_pixbuf (icon); + if (pixbuf == NULL) { + g_set_error (error, + AS_APP_ERROR, + AS_APP_ERROR_FAILED, + "No pixbuf for %s", + as_icon_get_name (icon)); + return FALSE; + } if (!gdk_pixbuf_save (pixbuf, filename, "png", error, NULL)) return FALSE; diff --git a/libappstream-builder/asb-task.c b/libappstream-builder/asb-task.c index 1c55fee..5d5a105 100644 --- a/libappstream-builder/asb-task.c +++ b/libappstream-builder/asb-task.c @@ -388,7 +388,7 @@ asb_task_process (AsbTask *task, GError **error_not_used) /* don't include apps that have no icon */ if (as_app_get_id_kind (AS_APP (app)) != AS_ID_KIND_ADDON) { - if (as_app_get_icon (AS_APP (app)) == NULL) + if (as_app_get_icon_default (AS_APP (app)) == NULL) as_app_add_veto (AS_APP (app), "Has no Icon"); } diff --git a/libappstream-builder/plugins/asb-plugin-desktop.c b/libappstream-builder/plugins/asb-plugin-desktop.c index 362dd2d..54f5163 100644 --- a/libappstream-builder/plugins/asb-plugin-desktop.c +++ b/libappstream-builder/plugins/asb-plugin-desktop.c @@ -201,6 +201,9 @@ asb_plugin_desktop_add_icons (AsbPlugin *plugin, guint min_icon_size; _cleanup_free_ gchar *fn_hidpi = NULL; _cleanup_free_ gchar *fn = NULL; + _cleanup_free_ gchar *name = NULL; + _cleanup_object_unref_ AsIcon *icon_hidpi = NULL; + _cleanup_object_unref_ AsIcon *icon = NULL; _cleanup_object_unref_ GdkPixbuf *pixbuf_hidpi = NULL; _cleanup_object_unref_ GdkPixbuf *pixbuf = NULL; @@ -246,7 +249,13 @@ asb_plugin_desktop_add_icons (AsbPlugin *plugin, } /* save in target directory */ - asb_app_add_pixbuf (app, pixbuf); + name = g_strdup_printf ("%s.png", as_app_get_id_filename (AS_APP (app))); + icon = as_icon_new (); + as_icon_set_pixbuf (icon, pixbuf); + as_icon_set_name (icon, name, -1); + as_icon_set_kind (icon, AS_ICON_KIND_CACHED); + as_icon_set_prefix (icon, as_app_get_icon_path (AS_APP (app))); + as_app_add_icon (AS_APP (app), icon); /* is HiDPI disabled */ if (!asb_context_get_hidpi_enabled (plugin->ctx)) @@ -269,7 +278,14 @@ asb_plugin_desktop_add_icons (AsbPlugin *plugin, gdk_pixbuf_get_height (pixbuf_hidpi) <= gdk_pixbuf_get_height (pixbuf)) return TRUE; as_app_add_kudo_kind (AS_APP (app), AS_KUDO_KIND_HI_DPI_ICON); - asb_app_add_pixbuf (app, pixbuf_hidpi); + + /* save icon */ + icon_hidpi = as_icon_new (); + as_icon_set_pixbuf (icon_hidpi, pixbuf_hidpi); + as_icon_set_name (icon_hidpi, name, -1); + as_icon_set_kind (icon_hidpi, AS_ICON_KIND_CACHED); + as_icon_set_prefix (icon_hidpi, as_app_get_icon_path (AS_APP (app))); + as_app_add_icon (AS_APP (app), icon_hidpi); return TRUE; } @@ -284,7 +300,7 @@ asb_plugin_process_filename (AsbPlugin *plugin, const gchar *tmpdir, GError **error) { - const gchar *key; + AsIcon *icon; gboolean ret; _cleanup_free_ gchar *app_id = NULL; _cleanup_free_ gchar *full_filename = NULL; @@ -314,27 +330,23 @@ asb_plugin_process_filename (AsbPlugin *plugin, asb_app_add_requires_appdata (app, "Category=DesktopSettings"); /* is the icon a stock-icon-name? */ - key = as_app_get_icon (AS_APP (app)); - if (key != NULL) { - if (as_app_get_icon_kind (AS_APP (app)) == AS_ICON_KIND_STOCK) { + icon = as_app_get_icon_default (AS_APP (app)); + if (icon != NULL) { + _cleanup_free_ gchar *key; + key = g_strdup (as_icon_get_name (icon)); + if (as_icon_get_kind (icon) == AS_ICON_KIND_STOCK) { asb_package_log (pkg, ASB_PACKAGE_LOG_LEVEL_DEBUG, "using stock icon %s", key); } else { _cleanup_error_free_ GError *error_local = NULL; + g_ptr_array_set_size (as_app_get_icons (AS_APP (app)), 0); ret = asb_plugin_desktop_add_icons (plugin, app, tmpdir, key, &error_local); - if (ret) { - _cleanup_free_ gchar *fn = NULL; - fn = g_strdup_printf ("%s.png", - as_app_get_id_filename (AS_APP (app))); - as_app_set_icon (AS_APP (app), fn, -1); - as_app_set_icon_kind (AS_APP (app), - AS_ICON_KIND_CACHED); - } else { + if (!ret) { as_app_add_veto (AS_APP (app), "%s", error_local->message); } diff --git a/libappstream-builder/plugins/asb-plugin-font.c b/libappstream-builder/plugins/asb-plugin-font.c index 1684c73..8014c36 100644 --- a/libappstream-builder/plugins/asb-plugin-font.c +++ b/libappstream-builder/plugins/asb-plugin-font.c @@ -614,8 +614,7 @@ asb_plugin_process_filename (AsbPlugin *plugin, /* generate icon */ tmp = as_app_get_metadata_item (AS_APP (app), "FontIconText"); if (tmp != NULL) { - icon_filename = g_strdup_printf ("%s.png", as_app_get_id_filename (AS_APP (app))); - as_app_set_icon (AS_APP (app), icon_filename, -1); + _cleanup_object_unref_ AsIcon *icon = NULL; pixbuf = asb_font_get_pixbuf (ft_face, 64, 64, tmp, error); if (pixbuf == NULL) { ret = FALSE; @@ -632,8 +631,14 @@ asb_plugin_process_filename (AsbPlugin *plugin, 64, 64, tmp); goto out; } - as_app_set_icon_kind (AS_APP (app), AS_ICON_KIND_CACHED); - asb_app_add_pixbuf (app, pixbuf); + + /* add icon */ + icon_filename = g_strdup_printf ("%s.png", as_app_get_id_filename (AS_APP (app))); + icon = as_icon_new (); + as_icon_set_kind (icon, AS_ICON_KIND_CACHED); + as_icon_set_name (icon, icon_filename, -1); + as_icon_set_pixbuf (icon, pixbuf); + as_app_add_icon (AS_APP (app), icon); } /* add */ diff --git a/libappstream-builder/plugins/asb-plugin-gstreamer.c b/libappstream-builder/plugins/asb-plugin-gstreamer.c index 25641fe..b205f3a 100644 --- a/libappstream-builder/plugins/asb-plugin-gstreamer.c +++ b/libappstream-builder/plugins/asb-plugin-gstreamer.c @@ -142,6 +142,7 @@ asb_plugin_process (AsbPlugin *plugin, guint j; _cleanup_free_ gchar *app_id = NULL; _cleanup_object_unref_ AsbApp *app = NULL; + _cleanup_object_unref_ AsIcon *icon = NULL; _cleanup_string_free_ GString *str = NULL; /* use the pkgname suffix as the app-id */ @@ -158,13 +159,17 @@ asb_plugin_process (AsbPlugin *plugin, app = asb_app_new (pkg, app_id); as_app_set_id_kind (AS_APP (app), AS_ID_KIND_CODEC); as_app_set_name (AS_APP (app), "C", "GStreamer Multimedia Codecs", -1); - as_app_set_icon (AS_APP (app), "application-x-executable", -1); asb_app_set_requires_appdata (app, TRUE); asb_app_set_hidpi_enabled (app, asb_context_get_hidpi_enabled (plugin->ctx)); - as_app_set_icon_kind (AS_APP (app), AS_ICON_KIND_STOCK); as_app_add_category (AS_APP (app), "Addons", -1); as_app_add_category (AS_APP (app), "Codecs", -1); + /* add icon */ + icon = as_icon_new (); + as_icon_set_kind (icon, AS_ICON_KIND_STOCK); + as_icon_set_name (icon, "application-x-executable", -1); + as_app_add_icon (AS_APP (app), icon); + for (i = 0; data[i].path != NULL; i++) { if (!asb_utils_is_file_in_tmpdir (tmpdir, data[i].path)) continue; diff --git a/libappstream-builder/plugins/asb-plugin-ibus-sql.c b/libappstream-builder/plugins/asb-plugin-ibus-sql.c index 6f680f9..cffbc9b 100644 --- a/libappstream-builder/plugins/asb-plugin-ibus-sql.c +++ b/libappstream-builder/plugins/asb-plugin-ibus-sql.c @@ -97,6 +97,7 @@ asb_plugin_process_filename (AsbPlugin *plugin, _cleanup_free_ gchar *name = NULL; _cleanup_free_ gchar *symbol = NULL; _cleanup_object_unref_ AsbApp *app = NULL; + _cleanup_object_unref_ AsIcon *icon = NULL; _cleanup_strv_free_ gchar **languages = NULL; /* open IME database */ @@ -189,8 +190,6 @@ asb_plugin_process_filename (AsbPlugin *plugin, as_app_set_id_kind (AS_APP (app), AS_ID_KIND_INPUT_METHOD); as_app_add_category (AS_APP (app), "Addons", -1); as_app_add_category (AS_APP (app), "InputSources", -1); - as_app_set_icon (AS_APP (app), "system-run-symbolic", -1); - as_app_set_icon_kind (AS_APP (app), AS_ICON_KIND_STOCK); as_app_set_name (AS_APP (app), "C", name, -1); as_app_set_comment (AS_APP (app), "C", description, -1); if (symbol != NULL && symbol[0] != '\0') @@ -206,6 +205,13 @@ asb_plugin_process_filename (AsbPlugin *plugin, } asb_app_set_requires_appdata (app, TRUE); asb_app_set_hidpi_enabled (app, asb_context_get_hidpi_enabled (plugin->ctx)); + + /* add icon */ + icon = as_icon_new (); + as_icon_set_kind (icon, AS_ICON_KIND_STOCK); + as_icon_set_name (icon, "system-run-symbolic", -1); + as_app_add_icon (AS_APP (app), icon); + asb_plugin_add_app (apps, AS_APP (app)); out: if (db != NULL) diff --git a/libappstream-builder/plugins/asb-plugin-ibus-xml.c b/libappstream-builder/plugins/asb-plugin-ibus-xml.c index d808d8a..a450cec 100644 --- a/libappstream-builder/plugins/asb-plugin-ibus-xml.c +++ b/libappstream-builder/plugins/asb-plugin-ibus-xml.c @@ -86,6 +86,7 @@ asb_plugin_process_filename (AsbPlugin *plugin, _cleanup_free_ gchar *data = NULL; _cleanup_free_ gchar *filename_tmp; _cleanup_object_unref_ AsbApp *app = NULL; + _cleanup_object_unref_ AsIcon *icon = NULL; _cleanup_strv_free_ gchar **languages = NULL; _cleanup_strv_free_ gchar **lines = NULL; @@ -120,11 +121,15 @@ asb_plugin_process_filename (AsbPlugin *plugin, as_app_set_id_kind (AS_APP (app), AS_ID_KIND_INPUT_METHOD); as_app_add_category (AS_APP (app), "Addons", -1); as_app_add_category (AS_APP (app), "InputSources", -1); - as_app_set_icon (AS_APP (app), "system-run-symbolic", -1); - as_app_set_icon_kind (AS_APP (app), AS_ICON_KIND_STOCK); asb_app_set_requires_appdata (app, TRUE); asb_app_set_hidpi_enabled (app, asb_context_get_hidpi_enabled (plugin->ctx)); + /* add icon */ + icon = as_icon_new (); + as_icon_set_kind (icon, AS_ICON_KIND_STOCK); + as_icon_set_name (icon, "system-run-symbolic", -1); + as_app_add_icon (AS_APP (app), icon); + /* read the component header which all input methods have */ n = as_node_find (root, "component/description"); if (n != NULL) { diff --git a/libappstream-glib/as-app.c b/libappstream-glib/as-app.c index 9341abd..c8a0737 100644 --- a/libappstream-glib/as-app.c +++ b/libappstream-glib/as-app.c @@ -40,6 +40,7 @@ #include "as-app-private.h" #include "as-cleanup.h" #include "as-enums.h" +#include "as-icon-private.h" #include "as-node-private.h" #include "as-provide-private.h" #include "as-release-private.h" @@ -73,11 +74,11 @@ struct _AsAppPrivate GPtrArray *releases; /* of AsRelease */ GPtrArray *provides; /* of AsProvide */ GPtrArray *screenshots; /* of AsScreenshot */ + GPtrArray *icons; /* of AsIcon */ GPtrArray *vetos; /* of string */ AsAppSourceKind source_kind; AsAppState state; AsAppTrustFlags trust_flags; - gchar *icon; gchar *icon_path; gchar *id_filename; gchar *id; @@ -243,7 +244,6 @@ as_app_finalize (GObject *object) AsApp *app = AS_APP (object); AsAppPrivate *priv = GET_PRIVATE (app); - g_free (priv->icon); g_free (priv->icon_path); g_free (priv->id_filename); g_free (priv->id); @@ -272,6 +272,7 @@ as_app_finalize (GObject *object) g_ptr_array_unref (priv->releases); g_ptr_array_unref (priv->provides); g_ptr_array_unref (priv->screenshots); + g_ptr_array_unref (priv->icons); g_ptr_array_unref (priv->token_cache); g_ptr_array_unref (priv->vetos); @@ -309,6 +310,7 @@ as_app_init (AsApp *app) priv->releases = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); priv->provides = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); priv->screenshots = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + priv->icons = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); priv->token_cache = g_ptr_array_new_with_free_func ((GDestroyNotify) as_app_token_item_free); priv->vetos = g_ptr_array_new_with_free_func (g_free); @@ -586,6 +588,23 @@ as_app_get_screenshots (AsApp *app) } /** + * as_app_get_icons: + * @app: a #AsApp instance. + * + * Gets any icons the application has defined. + * + * Returns: (element-type AsIcon) (transfer none): an array + * + * Since: 0.3.1 + **/ +GPtrArray * +as_app_get_icons (AsApp *app) +{ + AsAppPrivate *priv = GET_PRIVATE (app); + return priv->icons; +} + +/** * as_app_get_names: * @app: a #AsApp instance. * @@ -893,41 +912,6 @@ as_app_get_problems (AsApp *app) } /** - * as_app_get_icon_kind: - * @app: a #AsApp instance. - * - * Gets the icon kind. - * - * Returns: enumerated value - * - * Since: 0.1.0 - **/ -AsIconKind -as_app_get_icon_kind (AsApp *app) -{ - AsAppPrivate *priv = GET_PRIVATE (app); - return priv->icon_kind; -} - -/** - * as_app_get_icon: - * @app: a #AsApp instance. - * - * Gets the application icon. Use as_app_get_icon_path() if you need the create - * a full filename. - * - * Returns: string, or %NULL if unset - * - * Since: 0.1.0 - **/ -const gchar * -as_app_get_icon (AsApp *app) -{ - AsAppPrivate *priv = GET_PRIVATE (app); - return priv->icon; -} - -/** * as_app_get_pkgname_default: * @app: a #AsApp instance. * @@ -1569,32 +1553,6 @@ as_app_set_update_contact (AsApp *app, } /** - * as_app_set_icon: - * @app: a #AsApp instance. - * @icon: the icon filename or URL. - * @icon_len: the size of @icon, or -1 if %NULL-terminated. - * - * Set the application icon. - * - * Since: 0.1.0 - **/ -void -as_app_set_icon (AsApp *app, const gchar *icon, gssize icon_len) -{ - AsAppPrivate *priv = GET_PRIVATE (app); - - /* handle untrusted */ - if ((priv->trust_flags & AS_APP_TRUST_FLAG_CHECK_VALID_UTF8) > 0 && - !as_app_validate_utf8 (icon, icon_len)) { - priv->problems |= AS_APP_PROBLEM_NOT_VALID_UTF8; - return; - } - - g_free (priv->icon); - priv->icon = as_strndup (icon, icon_len); -} - -/** * as_app_set_icon_path: * @app: a #AsApp instance. * @icon_path: the local path. @@ -1621,22 +1579,6 @@ as_app_set_icon_path (AsApp *app, const gchar *icon_path, gssize icon_path_len) } /** - * as_app_set_icon_kind: - * @app: a #AsApp instance. - * @icon_kind: the #AsIconKind. - * - * Sets the icon kind. - * - * Since: 0.1.0 - **/ -void -as_app_set_icon_kind (AsApp *app, AsIconKind icon_kind) -{ - AsAppPrivate *priv = GET_PRIVATE (app); - priv->icon_kind = icon_kind; -} - -/** * as_app_parse_locale: **/ static gchar * @@ -2084,6 +2026,36 @@ as_app_add_screenshot (AsApp *app, AsScreenshot *screenshot) } /** + * as_app_add_icon: + * @app: a #AsApp instance. + * @icon: a #AsIcon instance. + * + * Adds a icon to an application. + * + * Since: 0.3.1 + **/ +void +as_app_add_icon (AsApp *app, AsIcon *icon) +{ + AsAppPrivate *priv = GET_PRIVATE (app); + + /* handle untrusted */ + if ((priv->trust_flags & AS_APP_TRUST_FLAG_CHECK_DUPLICATES) > 0) { + AsIcon *ic_tmp; + guint i; + for (i = 0; i < priv->icons->len; i++) { + ic_tmp = g_ptr_array_index (priv->icons, i); + if (as_icon_get_pixbuf (ic_tmp) != NULL) + continue; + if (g_strcmp0 (as_icon_get_name (ic_tmp), + as_icon_get_name (icon)) == 0) + return; + } + } + g_ptr_array_add (priv->icons, g_object_ref (icon)); +} + +/** * as_app_add_pkgname: * @app: a #AsApp instance. * @pkgname: the package name. @@ -2428,6 +2400,12 @@ as_app_subsume_private (AsApp *app, AsApp *donor, AsAppSubsumeFlags flags) as_app_add_screenshot (app, ss); } + /* icons */ + for (i = 0; i < priv->icons->len; i++) { + AsIcon *ic = g_ptr_array_index (priv->icons, i); + as_app_add_icon (app, ic); + } + /* mimetypes */ for (i = 0; i < priv->mimetypes->len; i++) { tmp = g_ptr_array_index (priv->mimetypes, i); @@ -2460,12 +2438,6 @@ as_app_subsume_private (AsApp *app, AsApp *donor, AsAppSubsumeFlags flags) as_app_subsume_dict (papp->urls, priv->urls, overwrite); as_app_subsume_keywords (app, donor, overwrite); - /* icon */ - if (priv->icon != NULL) - as_app_set_icon (app, priv->icon, -1); - if (priv->icon_kind != AS_ICON_KIND_UNKNOWN) - as_app_set_icon_kind (app, priv->icon_kind); - /* source */ if (priv->source_file != NULL) as_app_set_source_file (app, priv->source_file); @@ -2788,10 +2760,9 @@ as_app_node_insert (AsApp *app, GNode *parent, gdouble api_version) } /* <icon> */ - if (priv->icon != NULL) { - as_node_insert (node_app, "icon", priv->icon, 0, - "type", as_icon_kind_to_string (priv->icon_kind), - NULL); + for (i = 0; i < priv->icons->len; i++) { + AsIcon *ic = g_ptr_array_index (priv->icons, i); + as_icon_node_insert (ic, node_app, api_version); } /* <categories> */ @@ -3071,11 +3042,15 @@ as_app_node_parse_child (AsApp *app, GNode *n, AsAppParseFlags flags, GError **e /* <icon> */ case AS_TAG_ICON: - tmp = as_node_get_attribute (n, "type"); - as_app_set_icon_kind (app, as_icon_kind_from_string (tmp)); - g_free (priv->icon); - priv->icon = as_node_take_data (n); + { + _cleanup_object_unref_ AsIcon *ic = NULL; + ic = as_icon_new (); + as_icon_set_prefix (ic, priv->icon_path); + if (!as_icon_node_parse (ic, n, error)) + return FALSE; + as_app_add_icon (app, ic); break; + } /* <categories> */ case AS_TAG_CATEGORIES: @@ -3345,6 +3320,7 @@ as_app_node_parse_full (AsApp *app, GNode *node, AsAppParseFlags flags, GError * g_ptr_array_set_size (priv->pkgnames, 0); g_ptr_array_set_size (priv->architectures, 0); g_ptr_array_set_size (priv->extends, 0); + g_ptr_array_set_size (priv->icons, 0); g_hash_table_remove_all (priv->keywords); } for (n = node->children; n != NULL; n = n->next) { @@ -3453,11 +3429,11 @@ as_app_node_parse_dep11 (AsApp *app, GNode *node, GError **error) } if (g_strcmp0 (tmp, "Icon") == 0) { for (c = n->children; c != NULL; c = c->next) { - if (g_strcmp0 (as_yaml_node_get_key (c), "cached") == 0) { - as_app_set_icon (app, as_yaml_node_get_value (c), -1); - as_app_set_icon_kind (app, AS_ICON_KIND_CACHED); - continue; - } + _cleanup_object_unref_ AsIcon *ic = NULL; + ic = as_icon_new (); + if (!as_icon_node_parse_dep11 (ic, c, error)) + return FALSE; + as_app_add_icon (app, ic); } continue; } @@ -3813,14 +3789,20 @@ as_app_parse_file_key (AsApp *app, key, NULL); if (tmp != NULL && tmp[0] != '\0') { - as_app_set_icon (app, tmp, -1); + AsIcon *icon; + dot = g_strstr_len (tmp, -1, "."); + if (dot != NULL) + *dot = '\0'; + icon = as_icon_new (); + as_icon_set_name (icon, tmp, -1); dot = g_strstr_len (tmp, -1, "."); if (dot != NULL) *dot = '\0'; if (as_utils_is_stock_icon_name (tmp)) { - as_app_set_icon (app, tmp, -1); - as_app_set_icon_kind (app, AS_ICON_KIND_STOCK); + as_icon_set_name (icon, tmp, -1); + as_icon_set_kind (icon, AS_ICON_KIND_STOCK); } + as_app_add_icon (app, icon); } /* Categories */ @@ -4036,7 +4018,7 @@ as_app_parse_desktop_file (AsApp *app, } /* all applications require icons */ - if (as_app_get_icon (app) == NULL) + if (as_app_get_icons(app)->len == 0) as_app_add_veto (app, "%s has no icon", app_id); return TRUE; @@ -4318,6 +4300,55 @@ as_app_get_vetos (AsApp *app) } /** + * as_app_get_icon_default: + * @app: A #AsApp + * + * Finds the default icon. + * + * Returns: (transfer none): a #AsIcon, or %NULL + * + * Since: 0.3.1 + **/ +AsIcon * +as_app_get_icon_default (AsApp *app) +{ + AsAppPrivate *priv = GET_PRIVATE (app); + AsIcon *icon; + + if (priv->icons->len == 0) + return NULL; + icon = g_ptr_array_index (priv->icons, 0); + return icon; +} + +/** + * as_app_get_icon_for_size: + * @app: A #AsApp + * @width: Size in pixels + * @height: Size in pixels + * + * Finds an icon of a specific size. + * + * Returns: (transfer none): a #AsIcon, or %NULL + * + * Since: 0.3.1 + **/ +AsIcon * +as_app_get_icon_for_size (AsApp *app, guint width, guint height) +{ + AsAppPrivate *priv = GET_PRIVATE (app); + guint i; + + for (i = 0; i < priv->icons->len; i++) { + AsIcon *ic = g_ptr_array_index (priv->icons, i); + if (as_icon_get_width (ic) == width && + as_icon_get_height (ic) == height) + return ic; + } + return NULL; +} + +/** * as_app_add_veto: * @app: A #AsApp * @fmt: format string diff --git a/libappstream-glib/as-app.h b/libappstream-glib/as-app.h index f6c562d..57fdb61 100644 --- a/libappstream-glib/as-app.h +++ b/libappstream-glib/as-app.h @@ -29,6 +29,7 @@ #include <glib-object.h> #include "as-enums.h" +#include "as-icon.h" #include "as-provide.h" #include "as-release.h" #include "as-screenshot.h" @@ -213,7 +214,6 @@ const gchar *as_app_source_kind_to_string (AsAppSourceKind source_kind); const gchar *as_app_state_to_string (AsAppState state); /* getters */ -AsIconKind as_app_get_icon_kind (AsApp *app); AsIdKind as_app_get_id_kind (AsApp *app); AsAppSourceKind as_app_get_source_kind (AsApp *app); AsAppState as_app_get_state (AsApp *app); @@ -232,6 +232,7 @@ GPtrArray *as_app_get_architectures (AsApp *app); GPtrArray *as_app_get_releases (AsApp *app); GPtrArray *as_app_get_provides (AsApp *app); GPtrArray *as_app_get_screenshots (AsApp *app); +GPtrArray *as_app_get_icons (AsApp *app); GHashTable *as_app_get_names (AsApp *app); GHashTable *as_app_get_comments (AsApp *app); GHashTable *as_app_get_developer_names (AsApp *app); @@ -239,7 +240,6 @@ GHashTable *as_app_get_metadata (AsApp *app); GHashTable *as_app_get_descriptions (AsApp *app); GHashTable *as_app_get_urls (AsApp *app); GPtrArray *as_app_get_vetos (AsApp *app); -const gchar *as_app_get_icon (AsApp *app); const gchar *as_app_get_icon_path (AsApp *app); const gchar *as_app_get_id_filename (AsApp *app); const gchar *as_app_get_id (AsApp *app); @@ -299,14 +299,9 @@ void as_app_set_source_pkgname (AsApp *app, void as_app_set_update_contact (AsApp *app, const gchar *update_contact, gssize update_contact_len); -void as_app_set_icon (AsApp *app, - const gchar *icon, - gssize icon_len); void as_app_set_icon_path (AsApp *app, const gchar *icon_path, gssize icon_path_len); -void as_app_set_icon_kind (AsApp *app, - AsIconKind icon_kind); void as_app_set_name (AsApp *app, const gchar *locale, const gchar *name, @@ -354,6 +349,8 @@ void as_app_add_provide (AsApp *app, AsProvide *provide); void as_app_add_screenshot (AsApp *app, AsScreenshot *screenshot); +void as_app_add_icon (AsApp *app, + AsIcon *icon); void as_app_add_language (AsApp *app, gint percentage, const gchar *locale, @@ -402,6 +399,10 @@ gboolean as_app_to_file (AsApp *app, GFile *file, GCancellable *cancellable, GError **error); +AsIcon *as_app_get_icon_default (AsApp *app); +AsIcon *as_app_get_icon_for_size (AsApp *app, + guint width, + guint height); G_END_DECLS diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c index 2ccc5e5..f9d3dbb 100644 --- a/libappstream-glib/as-self-test.c +++ b/libappstream-glib/as-self-test.c @@ -665,9 +665,11 @@ as_test_screenshot_func (void) static void as_test_app_func (void) { + AsIcon *ic; GError *error = NULL; GNode *n; GNode *root; + GPtrArray *icons; GString *xml; gboolean ret; const gchar *src = @@ -748,9 +750,7 @@ as_test_app_func (void) g_assert_cmpstr (as_app_get_name (app, "pl"), ==, "Oprogramowanie"); g_assert_cmpstr (as_app_get_comment (app, NULL), ==, "Application manager"); g_assert_cmpstr (as_app_get_developer_name (app, NULL), ==, "GNOME Foundation"); - g_assert_cmpstr (as_app_get_icon (app), ==, "org.gnome.Software.png"); g_assert_cmpstr (as_app_get_source_pkgname (app), ==, "gnome-software-src"); - g_assert_cmpint (as_app_get_icon_kind (app), ==, AS_ICON_KIND_CACHED); g_assert_cmpint (as_app_get_source_kind (app), ==, AS_APP_SOURCE_KIND_UNKNOWN); g_assert_cmpstr (as_app_get_project_group (app), ==, "GNOME"); g_assert_cmpstr (as_app_get_project_license (app), ==, "GPLv2+"); @@ -770,6 +770,19 @@ as_test_app_func (void) g_assert (!as_app_has_kudo_kind (app, AS_KUDO_KIND_USER_DOCS)); as_node_unref (root); + /* check icons */ + icons = as_app_get_icons (app); + g_assert (icons != NULL); + g_assert_cmpint (icons->len, ==, 1); + + /* check we can get a specific icon */ + ic = as_app_get_icon_for_size (app, 999, 999); + g_assert (ic == NULL); + ic = as_app_get_icon_for_size (app, 64, 64); + g_assert (ic != NULL); + g_assert_cmpstr (as_icon_get_name (ic), ==, "org.gnome.Software.png"); + g_assert_cmpint (as_icon_get_kind (ic), ==, AS_ICON_KIND_CACHED); + /* back to node */ root = as_node_new (); n = as_app_node_insert (app, root, 0.8); @@ -1088,6 +1101,7 @@ static void as_test_store_local_app_install_func (void) { AsApp *app; + AsIcon *ic; GError *error = NULL; gboolean ret; _cleanup_free_ gchar *filename = NULL; @@ -1108,10 +1122,17 @@ as_test_store_local_app_install_func (void) g_assert (app != NULL); g_assert_cmpstr (as_app_get_name (app, "C"), ==, "Test"); g_assert_cmpstr (as_app_get_comment (app, "C"), ==, "A test program"); - g_assert_cmpstr (as_app_get_icon (app), ==, "test"); - g_assert_cmpint (as_app_get_icon_kind (app), ==, AS_ICON_KIND_CACHED); g_assert_cmpint (as_app_get_source_kind (app), ==, AS_APP_SOURCE_KIND_APPSTREAM); + /* check icons */ + g_assert_cmpint (as_app_get_icons(app)->len, ==, 1); + ic = as_app_get_icon_default (app); + g_assert (ic != NULL); + g_assert_cmpstr (as_icon_get_name (ic), ==, "test"); + g_assert_cmpint (as_icon_get_kind (ic), ==, AS_ICON_KIND_CACHED); + g_assert_cmpint (as_icon_get_width (ic), ==, 0); + g_assert_cmpint (as_icon_get_height (ic), ==, 0); + /* ensure we reference the correct file */ source_file = g_build_filename (filename, "/usr", "share", "app-install", "desktop", "test.desktop", NULL); @@ -1240,6 +1261,7 @@ as_test_app_validate_style_func (void) static void as_test_app_parse_file_func (void) { + AsIcon *ic; GError *error = NULL; gboolean ret; _cleanup_free_ gchar *filename = NULL; @@ -1262,8 +1284,6 @@ as_test_app_parse_file_func (void) "Inspect and compare installed color profiles"); g_assert_cmpstr (as_app_get_comment (app, "pl"), ==, "Badanie i porównywanie zainstalowanych profilów kolorów"); - g_assert_cmpstr (as_app_get_icon (app), ==, "audio-input-microphone"); - g_assert_cmpint (as_app_get_icon_kind (app), ==, AS_ICON_KIND_STOCK); g_assert_cmpint (as_app_get_vetos(app)->len, ==, 1); g_assert_cmpstr (as_app_get_project_group (app), ==, NULL); g_assert_cmpstr (as_app_get_source_file (app), ==, filename); @@ -1273,6 +1293,15 @@ as_test_app_parse_file_func (void) g_assert (as_app_has_category (app, "System")); g_assert (!as_app_has_category (app, "NotGoingToExist")); + /* check icons */ + g_assert_cmpint (as_app_get_icons(app)->len, ==, 1); + ic = as_app_get_icon_default (app); + g_assert (ic != NULL); + g_assert_cmpstr (as_icon_get_name (ic), ==, "audio-input-microphone"); + g_assert_cmpint (as_icon_get_kind (ic), ==, AS_ICON_KIND_STOCK); + g_assert_cmpint (as_icon_get_width (ic), ==, 0); + g_assert_cmpint (as_icon_get_height (ic), ==, 0); + /* reparse with heuristics */ ret = as_app_parse_file (app, filename, @@ -1737,14 +1766,18 @@ as_test_node_localized_wrap2_func (void) static void as_test_app_subsume_func (void) { + AsIcon *ic; GList *list; _cleanup_object_unref_ AsApp *app = NULL; _cleanup_object_unref_ AsApp *donor = NULL; + _cleanup_object_unref_ AsIcon *icon = NULL; _cleanup_object_unref_ AsScreenshot *ss = NULL; donor = as_app_new (); + icon = as_icon_new (); + as_icon_set_name (icon, "gtk-find", -1); + as_app_add_icon (donor, icon); as_app_set_state (donor, AS_APP_STATE_INSTALLED); - as_app_set_icon (donor, "gtk-find", -1); as_app_add_pkgname (donor, "hal", -1); as_app_add_language (donor, -1, "en_GB", -1); as_app_add_metadata (donor, "donor", "true", -1); @@ -1761,7 +1794,6 @@ as_test_app_subsume_func (void) as_app_subsume_full (app, donor, AS_APP_SUBSUME_FLAG_NO_OVERWRITE); as_app_add_screenshot (app, ss); - g_assert_cmpstr (as_app_get_icon (app), ==, "gtk-find"); g_assert_cmpstr (as_app_get_metadata_item (app, "donor"), ==, "true"); g_assert_cmpstr (as_app_get_metadata_item (app, "overwrite"), ==, "2222"); g_assert_cmpstr (as_app_get_metadata_item (donor, "recipient"), ==, NULL); @@ -1773,6 +1805,15 @@ as_test_app_subsume_func (void) g_assert_cmpint (g_list_length (list), ==, 1); g_list_free (list); + /* check icon */ + g_assert_cmpint (as_app_get_icons(app)->len, ==, 1); + ic = as_app_get_icon_default (app); + g_assert (ic != NULL); + g_assert_cmpstr (as_icon_get_name (ic), ==, "gtk-find"); + g_assert_cmpint (as_icon_get_kind (ic), ==, AS_ICON_KIND_UNKNOWN); + g_assert_cmpint (as_icon_get_width (ic), ==, 0); + g_assert_cmpint (as_icon_get_height (ic), ==, 0); + /* test both ways */ as_app_subsume_full (app, donor, AS_APP_SUBSUME_FLAG_BOTH_WAYS); g_assert_cmpstr (as_app_get_metadata_item (app, "donor"), ==, "true"); @@ -2963,4 +3004,3 @@ main (int argc, char **argv) return g_test_run (); } - diff --git a/libappstream-glib/as-store.c b/libappstream-glib/as-store.c index 75872a4..1a39651 100644 --- a/libappstream-glib/as-store.c +++ b/libappstream-glib/as-store.c @@ -1298,10 +1298,14 @@ as_store_load_app_install_file (AsStore *store, const gchar *path_icons, GError **error) { + AsIcon *icon; + GPtrArray *icons; + guint i; _cleanup_error_free_ GError *error_local = NULL; _cleanup_object_unref_ AsApp *app; app = as_app_new (); + as_app_set_icon_path (app, path_icons, -1); if (!as_app_parse_file (app, filename, AS_APP_PARSE_FLAG_USE_HEURISTICS, @@ -1320,9 +1324,14 @@ as_store_load_app_install_file (AsStore *store, error_local->message); return FALSE; } - if (as_app_get_icon_kind (app) == AS_ICON_KIND_UNKNOWN) - as_app_set_icon_kind (app, AS_ICON_KIND_CACHED); - as_app_set_icon_path (app, path_icons, -1); + + /* convert all the icons */ + icons = as_app_get_icons (app); + for (i = 0; i < icons->len; i++) { + icon = g_ptr_array_index (icons, i); + if (as_icon_get_kind (icon) == AS_ICON_KIND_UNKNOWN) + as_icon_set_kind (icon, AS_ICON_KIND_CACHED); + } as_store_add_app_install_screenshot (app); as_store_add_app (store, app); @@ -1439,7 +1448,6 @@ as_store_load_installed (AsStore *store, /* set lower priority than AppStream entries */ as_app_set_priority (app, -1); - as_app_set_icon_kind (app, AS_ICON_KIND_STOCK); as_app_set_state (app, AS_APP_STATE_INSTALLED); as_store_add_app (store, app); } |