[gnome-software] Split out the shared Appstream functionality into a new file
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] Split out the shared Appstream functionality into a new file
- Date: Tue, 22 Dec 2015 07:20:00 +0000 (UTC)
commit 518cc935fbd51ecc89976c3088f34f4723d779a3
Author: Richard Hughes <richard hughsie com>
Date: Tue Dec 22 07:11:55 2015 +0000
Split out the shared Appstream functionality into a new file
src/plugins/Makefile.am | 2 +
src/plugins/appstream-common.c | 478 +++++++++++++++++++++++++++++++++++++
src/plugins/appstream-common.h | 38 +++
src/plugins/gs-plugin-appstream.c | 444 +----------------------------------
4 files changed, 520 insertions(+), 442 deletions(-)
---
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 756e194..0b7db2b 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -90,6 +90,8 @@ libgs_plugin_self_test_la_LDFLAGS = -module -avoid-version
libgs_plugin_self_test_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
libgs_plugin_appstream_la_SOURCES = \
+ appstream-common.c \
+ appstream-common.h \
gs-plugin-appstream.c
libgs_plugin_appstream_la_LIBADD = $(GS_PLUGIN_LIBS) $(APPSTREAM_LIBS)
libgs_plugin_appstream_la_LDFLAGS = -module -avoid-version
diff --git a/src/plugins/appstream-common.c b/src/plugins/appstream-common.c
new file mode 100644
index 0000000..216ee33
--- /dev/null
+++ b/src/plugins/appstream-common.c
@@ -0,0 +1,478 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2015 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <gs-plugin.h>
+
+#include "appstream-common.h"
+
+#define GS_PLUGIN_APPSTREAM_MAX_SCREENSHOTS 5
+
+/**
+ * _as_app_has_compulsory_for_desktop:
+ */
+static gboolean
+_as_app_has_compulsory_for_desktop (AsApp *app, const gchar *compulsory_for_desktop)
+{
+ GPtrArray *compulsory_for_desktops;
+ const gchar *tmp;
+ guint i;
+
+ compulsory_for_desktops = as_app_get_compulsory_for_desktops (app);
+ for (i = 0; i < compulsory_for_desktops->len; i++) {
+ tmp = g_ptr_array_index (compulsory_for_desktops, i);
+ if (g_strcmp0 (tmp, compulsory_for_desktop) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * gs_appstream_refine_app_pixbuf:
+ */
+static void
+gs_appstream_refine_app_pixbuf (GsPlugin *plugin, GsApp *app, AsApp *item)
+{
+ AsIcon *icon;
+ gboolean ret;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *fn = NULL;
+ g_autofree gchar *path = NULL;
+
+ icon = as_app_get_icon_default (item);
+ switch (as_icon_get_kind (icon)) {
+ case AS_ICON_KIND_REMOTE:
+ gs_app_set_icon (app, icon);
+ if (as_icon_get_filename (icon) == NULL) {
+ path = g_build_filename (g_get_user_data_dir (),
+ "gnome-software",
+ "icons",
+ NULL);
+ fn = g_build_filename (path, as_icon_get_name (icon), NULL);
+ as_icon_set_filename (icon, fn);
+ as_icon_set_prefix (icon, path);
+ }
+ if (g_file_test (fn, G_FILE_TEST_EXISTS)) {
+ as_icon_set_kind (icon, AS_ICON_KIND_LOCAL);
+ ret = gs_app_load_icon (app, plugin->scale, &error);
+ if (!ret) {
+ g_warning ("failed to load icon %s: %s",
+ as_icon_get_name (icon),
+ error->message);
+ return;
+ }
+ }
+ break;
+ case AS_ICON_KIND_STOCK:
+ case AS_ICON_KIND_LOCAL:
+ gs_app_set_icon (app, icon);
+
+ /* does not exist, so try to find using the icon theme */
+ if (as_icon_get_kind (icon) == AS_ICON_KIND_LOCAL &&
+ as_icon_get_filename (icon) == NULL)
+ as_icon_set_kind (icon, AS_ICON_KIND_STOCK);
+
+ /* load */
+ ret = gs_app_load_icon (app, plugin->scale, &error);
+ if (!ret) {
+ g_warning ("failed to load %s icon %s: %s",
+ as_icon_kind_to_string (as_icon_get_kind (icon)),
+ as_icon_get_name (icon),
+ error->message);
+ return;
+ }
+ break;
+ case AS_ICON_KIND_CACHED:
+ if (plugin->scale == 2)
+ icon = as_app_get_icon_for_size (item, 128, 128);
+ if (icon == NULL)
+ icon = as_app_get_icon_for_size (item, 64, 64);
+ if (icon == NULL) {
+ g_warning ("failed to find cached icon %s",
+ as_icon_get_name (icon));
+ return;
+ }
+ if (!as_icon_load (icon, AS_ICON_LOAD_FLAG_SEARCH_SIZE, &error)) {
+ g_warning ("failed to load cached icon %s: %s",
+ as_icon_get_name (icon), error->message);
+ return;
+ }
+ gs_app_set_pixbuf (app, as_icon_get_pixbuf (icon));
+ break;
+ default:
+ g_warning ("icon kind unknown for %s", as_app_get_id (item));
+ break;
+ }
+}
+
+/**
+ * gs_appstream_refine_add_addons:
+ */
+static void
+gs_appstream_refine_add_addons (GsPlugin *plugin, GsApp *app, AsApp *item)
+{
+ GPtrArray *addons;
+ guint i;
+
+ addons = as_app_get_addons (item);
+ if (addons == NULL)
+ return;
+
+ for (i = 0; i < addons->len; i++) {
+ AsApp *as_addon = g_ptr_array_index (addons, i);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GsApp) addon = NULL;
+
+ addon = gs_app_new (as_app_get_id (as_addon));
+
+ /* add all the data we can */
+ if (!gs_appstream_refine_app (plugin, addon, as_addon, &error)) {
+ g_warning ("failed to refine addon: %s", error->message);
+ continue;
+ }
+ gs_app_add_addon (app, addon);
+ }
+}
+/**
+ * gs_appstream_refine_add_screenshots:
+ */
+static void
+gs_appstream_refine_add_screenshots (GsApp *app, AsApp *item)
+{
+ AsScreenshot *ss;
+ GPtrArray *images_as;
+ GPtrArray *screenshots_as;
+ guint i;
+
+ /* do we have any to add */
+ screenshots_as = as_app_get_screenshots (item);
+ if (screenshots_as->len == 0)
+ return;
+
+ /* does the app already have some */
+ gs_app_add_kudo (app, GS_APP_KUDO_HAS_SCREENSHOTS);
+ if (gs_app_get_screenshots(app)->len > 0)
+ return;
+
+ /* add any we know */
+ for (i = 0; i < screenshots_as->len &&
+ i < GS_PLUGIN_APPSTREAM_MAX_SCREENSHOTS; i++) {
+ ss = g_ptr_array_index (screenshots_as, i);
+ images_as = as_screenshot_get_images (ss);
+ if (images_as->len == 0)
+ continue;
+ if (as_screenshot_get_kind (ss) == AS_SCREENSHOT_KIND_UNKNOWN)
+ continue;
+ gs_app_add_screenshot (app, ss);
+ }
+}
+
+/**
+ * gs_appstream_is_recent_release:
+ */
+static gboolean
+gs_appstream_is_recent_release (AsApp *app)
+{
+ AsRelease *release;
+ GPtrArray *releases;
+ guint secs;
+
+ /* get newest release */
+ releases = as_app_get_releases (app);
+ if (releases->len == 0)
+ return FALSE;
+ release = g_ptr_array_index (releases, 0);
+
+ /* is last build less than one year ago? */
+ secs = (g_get_real_time () / G_USEC_PER_SEC) -
+ as_release_get_timestamp (release);
+ return secs / (60 * 60 * 24) < 365;
+}
+
+/**
+ * gs_appstream_are_screenshots_perfect:
+ */
+static gboolean
+gs_appstream_are_screenshots_perfect (AsApp *app)
+{
+ AsImage *image;
+ AsScreenshot *screenshot;
+ GPtrArray *screenshots;
+ guint height;
+ guint i;
+ guint width;
+
+ screenshots = as_app_get_screenshots (app);
+ if (screenshots->len == 0)
+ return FALSE;
+ for (i = 0; i < screenshots->len; i++) {
+
+ /* get the source image as the thumbs will be resized & padded */
+ screenshot = g_ptr_array_index (screenshots, i);
+ image = as_screenshot_get_source (screenshot);
+ if (image == NULL)
+ return FALSE;
+
+ width = as_image_get_width (image);
+ height = as_image_get_height (image);
+
+ /* too small */
+ if (width < AS_IMAGE_LARGE_WIDTH || height < AS_IMAGE_LARGE_HEIGHT)
+ return FALSE;
+
+ /* too large */
+ if (width > AS_IMAGE_LARGE_WIDTH * 2 || height > AS_IMAGE_LARGE_HEIGHT * 2)
+ return FALSE;
+
+ /* not 16:9 */
+ if ((width / 16) * 9 != height)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * gs_appstream_copy_metadata:
+ */
+static void
+gs_appstream_copy_metadata (GsApp *app, AsApp *item)
+{
+ GHashTable *hash;
+ GList *l;
+ g_autoptr(GList) keys = NULL;
+
+ hash = as_app_get_metadata (item);
+ keys = g_hash_table_get_keys (hash);
+ for (l = keys; l != NULL; l = l->next) {
+ const gchar *key = l->data;
+ const gchar *value = g_hash_table_lookup (hash, key);
+ gs_app_set_metadata (app, key, value);
+ }
+}
+
+/**
+ * gs_appstream_refine_app:
+ */
+gboolean
+gs_appstream_refine_app (GsPlugin *plugin, GsApp *app, AsApp *item, GError **error)
+{
+
+ GHashTable *urls;
+ GPtrArray *pkgnames;
+ GPtrArray *kudos;
+ const gchar *tmp;
+ guint i;
+
+ /* is an app */
+ if (gs_app_get_kind (app) == GS_APP_KIND_UNKNOWN ||
+ gs_app_get_kind (app) == GS_APP_KIND_PACKAGE) {
+ if (as_app_get_id_kind (item) == AS_ID_KIND_SOURCE) {
+ gs_app_set_kind (app, GS_APP_KIND_SOURCE);
+ } else {
+ gs_app_set_kind (app, GS_APP_KIND_NORMAL);
+ }
+ }
+
+ /* is installed already */
+ if (gs_app_get_state (app) == AS_APP_STATE_UNKNOWN) {
+ switch (as_app_get_source_kind (item)) {
+ case AS_APP_SOURCE_KIND_APPDATA:
+ case AS_APP_SOURCE_KIND_DESKTOP:
+ gs_app_set_kind (app, GS_APP_KIND_NORMAL);
+ gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+ break;
+ case AS_APP_SOURCE_KIND_METAINFO:
+ gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+ break;
+ case AS_APP_SOURCE_KIND_APPSTREAM:
+ gs_app_set_state (app, as_app_get_state (item));
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* allow the PackageKit plugin to match up installed local files
+ * with packages when the component isn't in the AppStream XML */
+ switch (as_app_get_source_kind (item)) {
+ case AS_APP_SOURCE_KIND_DESKTOP:
+ case AS_APP_SOURCE_KIND_APPDATA:
+ case AS_APP_SOURCE_KIND_METAINFO:
+ if (as_app_get_source_file (item) != NULL &&
+ gs_app_get_metadata_item (app, "DataDir::desktop-filename") == NULL) {
+ gs_app_set_metadata (app, "DataDir::desktop-filename",
+ as_app_get_source_file (item));
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* set id */
+ if (as_app_get_id (item) != NULL && gs_app_get_id (app) == NULL)
+ gs_app_set_id (app, as_app_get_id (item));
+
+ /* set name */
+ tmp = as_app_get_name (item, NULL);
+ if (tmp != NULL) {
+ gs_app_set_name (app,
+ GS_APP_QUALITY_HIGHEST,
+ as_app_get_name (item, NULL));
+ }
+
+ /* set summary */
+ tmp = as_app_get_comment (item, NULL);
+ if (tmp != NULL) {
+ gs_app_set_summary (app,
+ GS_APP_QUALITY_HIGHEST,
+ as_app_get_comment (item, NULL));
+ }
+
+ /* add urls */
+ urls = as_app_get_urls (item);
+ if (g_hash_table_size (urls) > 0 &&
+ gs_app_get_url (app, AS_URL_KIND_HOMEPAGE) == NULL) {
+ GList *l;
+ g_autoptr(GList) keys = NULL;
+ keys = g_hash_table_get_keys (urls);
+ for (l = keys; l != NULL; l = l->next) {
+ gs_app_set_url (app,
+ as_url_kind_from_string (l->data),
+ g_hash_table_lookup (urls, l->data));
+ }
+ }
+
+ /* set licence */
+ if (as_app_get_project_license (item) != NULL && gs_app_get_licence (app) == NULL)
+ gs_app_set_licence (app,
+ as_app_get_project_license (item),
+ GS_APP_QUALITY_HIGHEST);
+
+ /* set keywords */
+ if (as_app_get_keywords (item, NULL) != NULL &&
+ gs_app_get_keywords (app) == NULL) {
+ gs_app_set_keywords (app, as_app_get_keywords (item, NULL));
+ gs_app_add_kudo (app, GS_APP_KUDO_HAS_KEYWORDS);
+ }
+
+ /* set description */
+ tmp = as_app_get_description (item, NULL);
+ if (tmp != NULL) {
+ g_autofree gchar *from_xml = NULL;
+ from_xml = as_markup_convert_simple (tmp, error);
+ if (from_xml == NULL) {
+ g_prefix_error (error, "trying to parse '%s': ", tmp);
+ return FALSE;
+ }
+ gs_app_set_description (app,
+ GS_APP_QUALITY_HIGHEST,
+ from_xml);
+ }
+
+ /* set icon */
+ if (as_app_get_icon_default (item) != NULL && gs_app_get_pixbuf (app) == NULL)
+ gs_appstream_refine_app_pixbuf (plugin, app, item);
+
+ /* set categories */
+ if (as_app_get_categories (item) != NULL &&
+ gs_app_get_categories (app)->len == 0)
+ gs_app_set_categories (app, as_app_get_categories (item));
+
+ /* set project group */
+ if (as_app_get_project_group (item) != NULL &&
+ gs_app_get_project_group (app) == NULL)
+ gs_app_set_project_group (app, as_app_get_project_group (item));
+
+ /* set default bundle (if any) */
+ if (as_app_get_bundle_default (item) != NULL &&
+ gs_app_get_bundle (app) == NULL)
+ gs_app_set_bundle (app, as_app_get_bundle_default (item));
+
+ /* this is a core application for the desktop and cannot be removed */
+ if (_as_app_has_compulsory_for_desktop (item, "GNOME") &&
+ gs_app_get_kind (app) == GS_APP_KIND_NORMAL)
+ gs_app_set_kind (app, GS_APP_KIND_SYSTEM);
+
+ /* set id kind */
+ if (gs_app_get_id_kind (app) == AS_ID_KIND_UNKNOWN)
+ gs_app_set_id_kind (app, as_app_get_id_kind (item));
+
+ /* copy all the metadata */
+ gs_appstream_copy_metadata (app, item);
+
+ /* set package names */
+ pkgnames = as_app_get_pkgnames (item);
+ if (pkgnames->len > 0 && gs_app_get_sources(app)->len == 0)
+ gs_app_set_sources (app, pkgnames);
+
+ /* set addons */
+ gs_appstream_refine_add_addons (plugin, app, item);
+
+ /* set screenshots */
+ gs_appstream_refine_add_screenshots (app, item);
+
+ /* are the screenshots perfect */
+ if (gs_appstream_are_screenshots_perfect (item))
+ gs_app_add_kudo (app, GS_APP_KUDO_PERFECT_SCREENSHOTS);
+
+ /* was this application released recently */
+ if (gs_appstream_is_recent_release (item))
+ gs_app_add_kudo (app, GS_APP_KUDO_RECENT_RELEASE);
+
+ /* add kudos */
+ if (as_app_get_language (item, plugin->locale) > 50)
+ gs_app_add_kudo (app, GS_APP_KUDO_MY_LANGUAGE);
+
+ /* add new-style kudos */
+ kudos = as_app_get_kudos (item);
+ for (i = 0; i < kudos->len; i++) {
+ tmp = g_ptr_array_index (kudos, i);
+ switch (as_kudo_kind_from_string (tmp)) {
+ case AS_KUDO_KIND_SEARCH_PROVIDER:
+ gs_app_add_kudo (app, GS_APP_KUDO_SEARCH_PROVIDER);
+ break;
+ case AS_KUDO_KIND_USER_DOCS:
+ gs_app_add_kudo (app, GS_APP_KUDO_INSTALLS_USER_DOCS);
+ break;
+ case AS_KUDO_KIND_APP_MENU:
+ gs_app_add_kudo (app, GS_APP_KUDO_USES_APP_MENU);
+ break;
+ case AS_KUDO_KIND_MODERN_TOOLKIT:
+ gs_app_add_kudo (app, GS_APP_KUDO_MODERN_TOOLKIT);
+ break;
+ case AS_KUDO_KIND_NOTIFICATIONS:
+ gs_app_add_kudo (app, GS_APP_KUDO_USES_NOTIFICATIONS);
+ break;
+ case AS_KUDO_KIND_HIGH_CONTRAST:
+ gs_app_add_kudo (app, GS_APP_KUDO_HIGH_CONTRAST);
+ break;
+ case AS_KUDO_KIND_HI_DPI_ICON:
+ gs_app_add_kudo (app, GS_APP_KUDO_HI_DPI_ICON);
+ break;
+ default:
+ g_debug ("no idea how to handle kudo '%s'", tmp);
+ break;
+ }
+ }
+
+ return TRUE;
+}
diff --git a/src/plugins/appstream-common.h b/src/plugins/appstream-common.h
new file mode 100644
index 0000000..b6b5b34
--- /dev/null
+++ b/src/plugins/appstream-common.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2015 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __APPSTREAM_COMMON_H
+#define __APPSTREAM_COMMON_H
+
+#include <glib.h>
+#include <gs-plugin.h>
+#include <appstream-glib.h>
+
+G_BEGIN_DECLS
+
+gboolean gs_appstream_refine_app (GsPlugin *plugin,
+ GsApp *app,
+ AsApp *item,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __APPSTREAM_COMMON_H */
diff --git a/src/plugins/gs-plugin-appstream.c b/src/plugins/gs-plugin-appstream.c
index 9a1be27..b09b637 100644
--- a/src/plugins/gs-plugin-appstream.c
+++ b/src/plugins/gs-plugin-appstream.c
@@ -26,7 +26,7 @@
#include <gs-plugin.h>
#include <gs-plugin-loader.h>
-#define GS_PLUGIN_APPSTREAM_MAX_SCREENSHOTS 5
+#include "appstream-common.h"
struct GsPluginPrivate {
AsStore *store;
@@ -46,25 +46,6 @@ gs_plugin_get_name (void)
}
/**
- * as_app_has_compulsory_for_desktop:
- */
-static gboolean
-as_app_has_compulsory_for_desktop (AsApp *app, const gchar *compulsory_for_desktop)
-{
- GPtrArray *compulsory_for_desktops;
- const gchar *tmp;
- guint i;
-
- compulsory_for_desktops = as_app_get_compulsory_for_desktops (app);
- for (i = 0; i < compulsory_for_desktops->len; i++) {
- tmp = g_ptr_array_index (compulsory_for_desktops, i);
- if (g_strcmp0 (tmp, compulsory_for_desktop) == 0)
- return TRUE;
- }
- return FALSE;
-}
-
-/**
* gs_plugin_appstream_store_changed_cb:
*/
static void
@@ -239,229 +220,6 @@ out:
}
/**
- * gs_plugin_refine_item_pixbuf:
- */
-static void
-gs_plugin_refine_item_pixbuf (GsPlugin *plugin, GsApp *app, AsApp *item)
-{
- AsIcon *icon;
- gboolean ret;
- g_autoptr(GError) error = NULL;
- g_autofree gchar *fn = NULL;
- g_autofree gchar *path = NULL;
-
- icon = as_app_get_icon_default (item);
- switch (as_icon_get_kind (icon)) {
- case AS_ICON_KIND_REMOTE:
- gs_app_set_icon (app, icon);
- if (as_icon_get_filename (icon) == NULL) {
- path = g_build_filename (g_get_user_data_dir (),
- "gnome-software",
- "icons",
- NULL);
- fn = g_build_filename (path, as_icon_get_name (icon), NULL);
- as_icon_set_filename (icon, fn);
- as_icon_set_prefix (icon, path);
- }
- if (g_file_test (fn, G_FILE_TEST_EXISTS)) {
- as_icon_set_kind (icon, AS_ICON_KIND_LOCAL);
- ret = gs_app_load_icon (app, plugin->scale, &error);
- if (!ret) {
- g_warning ("failed to load icon %s: %s",
- as_icon_get_name (icon),
- error->message);
- return;
- }
- }
- break;
- case AS_ICON_KIND_STOCK:
- case AS_ICON_KIND_LOCAL:
- gs_app_set_icon (app, icon);
-
- /* does not exist, so try to find using the icon theme */
- if (as_icon_get_kind (icon) == AS_ICON_KIND_LOCAL &&
- as_icon_get_filename (icon) == NULL)
- as_icon_set_kind (icon, AS_ICON_KIND_STOCK);
-
- /* load */
- ret = gs_app_load_icon (app, plugin->scale, &error);
- if (!ret) {
- g_warning ("failed to load %s icon %s: %s",
- as_icon_kind_to_string (as_icon_get_kind (icon)),
- as_icon_get_name (icon),
- error->message);
- return;
- }
- break;
- case AS_ICON_KIND_CACHED:
- if (plugin->scale == 2)
- icon = as_app_get_icon_for_size (item, 128, 128);
- if (icon == NULL)
- icon = as_app_get_icon_for_size (item, 64, 64);
- if (icon == NULL) {
- g_warning ("failed to find cached icon %s",
- as_icon_get_name (icon));
- return;
- }
- if (!as_icon_load (icon, AS_ICON_LOAD_FLAG_SEARCH_SIZE, &error)) {
- g_warning ("failed to load cached icon %s: %s",
- as_icon_get_name (icon), error->message);
- return;
- }
- gs_app_set_pixbuf (app, as_icon_get_pixbuf (icon));
- break;
- default:
- g_warning ("icon kind unknown for %s", as_app_get_id (item));
- break;
- }
-}
-
-/**
- * gs_plugin_refine_add_addons:
- */
-static void
-gs_plugin_refine_add_addons (GsPlugin *plugin, GsApp *app, AsApp *item)
-{
- GPtrArray *addons;
- guint i;
-
- addons = as_app_get_addons (item);
- if (addons == NULL)
- return;
-
- for (i = 0; i < addons->len; i++) {
- AsApp *as_addon = g_ptr_array_index (addons, i);
- g_autoptr(GError) error = NULL;
- g_autoptr(GsApp) addon = NULL;
-
- addon = gs_app_new (as_app_get_id (as_addon));
-
- /* add all the data we can */
- if (!gs_plugin_refine_item (plugin, addon, as_addon, &error)) {
- g_warning ("failed to refine addon: %s", error->message);
- continue;
- }
- gs_app_add_addon (app, addon);
- }
-}
-/**
- * gs_plugin_refine_add_screenshots:
- */
-static void
-gs_plugin_refine_add_screenshots (GsApp *app, AsApp *item)
-{
- AsScreenshot *ss;
- GPtrArray *images_as;
- GPtrArray *screenshots_as;
- guint i;
-
- /* do we have any to add */
- screenshots_as = as_app_get_screenshots (item);
- if (screenshots_as->len == 0)
- return;
-
- /* does the app already have some */
- gs_app_add_kudo (app, GS_APP_KUDO_HAS_SCREENSHOTS);
- if (gs_app_get_screenshots(app)->len > 0)
- return;
-
- /* add any we know */
- for (i = 0; i < screenshots_as->len &&
- i < GS_PLUGIN_APPSTREAM_MAX_SCREENSHOTS; i++) {
- ss = g_ptr_array_index (screenshots_as, i);
- images_as = as_screenshot_get_images (ss);
- if (images_as->len == 0)
- continue;
- if (as_screenshot_get_kind (ss) == AS_SCREENSHOT_KIND_UNKNOWN)
- continue;
- gs_app_add_screenshot (app, ss);
- }
-}
-
-/**
- * gs_plugin_appstream_is_recent_release:
- */
-static gboolean
-gs_plugin_appstream_is_recent_release (AsApp *app)
-{
- AsRelease *release;
- GPtrArray *releases;
- guint secs;
-
- /* get newest release */
- releases = as_app_get_releases (app);
- if (releases->len == 0)
- return FALSE;
- release = g_ptr_array_index (releases, 0);
-
- /* is last build less than one year ago? */
- secs = (g_get_real_time () / G_USEC_PER_SEC) -
- as_release_get_timestamp (release);
- return secs / (60 * 60 * 24) < 365;
-}
-
-/**
- * gs_plugin_appstream_are_screenshots_perfect:
- */
-static gboolean
-gs_plugin_appstream_are_screenshots_perfect (AsApp *app)
-{
- AsImage *image;
- AsScreenshot *screenshot;
- GPtrArray *screenshots;
- guint height;
- guint i;
- guint width;
-
- screenshots = as_app_get_screenshots (app);
- if (screenshots->len == 0)
- return FALSE;
- for (i = 0; i < screenshots->len; i++) {
-
- /* get the source image as the thumbs will be resized & padded */
- screenshot = g_ptr_array_index (screenshots, i);
- image = as_screenshot_get_source (screenshot);
- if (image == NULL)
- return FALSE;
-
- width = as_image_get_width (image);
- height = as_image_get_height (image);
-
- /* too small */
- if (width < AS_IMAGE_LARGE_WIDTH || height < AS_IMAGE_LARGE_HEIGHT)
- return FALSE;
-
- /* too large */
- if (width > AS_IMAGE_LARGE_WIDTH * 2 || height > AS_IMAGE_LARGE_HEIGHT * 2)
- return FALSE;
-
- /* not 16:9 */
- if ((width / 16) * 9 != height)
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * gs_plugin_appstream_copy_metadata:
- */
-static void
-gs_plugin_appstream_copy_metadata (GsApp *app, AsApp *item)
-{
- GHashTable *hash;
- GList *l;
- g_autoptr(GList) keys = NULL;
-
- hash = as_app_get_metadata (item);
- keys = g_hash_table_get_keys (hash);
- for (l = keys; l != NULL; l = l->next) {
- const gchar *key = l->data;
- const gchar *value = g_hash_table_lookup (hash, key);
- gs_app_set_metadata (app, key, value);
- }
-}
-
-/**
* gs_plugin_refine_item:
*/
static gboolean
@@ -470,205 +228,7 @@ gs_plugin_refine_item (GsPlugin *plugin,
AsApp *item,
GError **error)
{
- GHashTable *urls;
- GPtrArray *pkgnames;
- GPtrArray *kudos;
- const gchar *tmp;
- guint i;
-
- /* is an app */
- if (gs_app_get_kind (app) == GS_APP_KIND_UNKNOWN ||
- gs_app_get_kind (app) == GS_APP_KIND_PACKAGE) {
- if (as_app_get_id_kind (item) == AS_ID_KIND_SOURCE) {
- gs_app_set_kind (app, GS_APP_KIND_SOURCE);
- } else {
- gs_app_set_kind (app, GS_APP_KIND_NORMAL);
- }
- }
-
- /* is installed already */
- if (gs_app_get_state (app) == AS_APP_STATE_UNKNOWN) {
- switch (as_app_get_source_kind (item)) {
- case AS_APP_SOURCE_KIND_APPDATA:
- case AS_APP_SOURCE_KIND_DESKTOP:
- gs_app_set_kind (app, GS_APP_KIND_NORMAL);
- gs_app_set_state (app, AS_APP_STATE_INSTALLED);
- break;
- case AS_APP_SOURCE_KIND_METAINFO:
- gs_app_set_state (app, AS_APP_STATE_INSTALLED);
- break;
- case AS_APP_SOURCE_KIND_APPSTREAM:
- gs_app_set_state (app, as_app_get_state (item));
- break;
- default:
- break;
- }
- }
-
- /* allow the PackageKit plugin to match up installed local files
- * with packages when the component isn't in the AppStream XML */
- switch (as_app_get_source_kind (item)) {
- case AS_APP_SOURCE_KIND_DESKTOP:
- case AS_APP_SOURCE_KIND_APPDATA:
- case AS_APP_SOURCE_KIND_METAINFO:
- if (as_app_get_source_file (item) != NULL &&
- gs_app_get_metadata_item (app, "DataDir::desktop-filename") == NULL) {
- gs_app_set_metadata (app, "DataDir::desktop-filename",
- as_app_get_source_file (item));
- }
- break;
- default:
- break;
- }
-
- /* set id */
- if (as_app_get_id (item) != NULL && gs_app_get_id (app) == NULL)
- gs_app_set_id (app, as_app_get_id (item));
-
- /* set name */
- tmp = as_app_get_name (item, NULL);
- if (tmp != NULL) {
- gs_app_set_name (app,
- GS_APP_QUALITY_HIGHEST,
- as_app_get_name (item, NULL));
- }
-
- /* set summary */
- tmp = as_app_get_comment (item, NULL);
- if (tmp != NULL) {
- gs_app_set_summary (app,
- GS_APP_QUALITY_HIGHEST,
- as_app_get_comment (item, NULL));
- }
-
- /* add urls */
- urls = as_app_get_urls (item);
- if (g_hash_table_size (urls) > 0 &&
- gs_app_get_url (app, AS_URL_KIND_HOMEPAGE) == NULL) {
- GList *l;
- g_autoptr(GList) keys = NULL;
- keys = g_hash_table_get_keys (urls);
- for (l = keys; l != NULL; l = l->next) {
- gs_app_set_url (app,
- as_url_kind_from_string (l->data),
- g_hash_table_lookup (urls, l->data));
- }
- }
-
- /* set licence */
- if (as_app_get_project_license (item) != NULL && gs_app_get_licence (app) == NULL)
- gs_app_set_licence (app,
- as_app_get_project_license (item),
- GS_APP_QUALITY_HIGHEST);
-
- /* set keywords */
- if (as_app_get_keywords (item, NULL) != NULL &&
- gs_app_get_keywords (app) == NULL) {
- gs_app_set_keywords (app, as_app_get_keywords (item, NULL));
- gs_app_add_kudo (app, GS_APP_KUDO_HAS_KEYWORDS);
- }
-
- /* set description */
- tmp = as_app_get_description (item, NULL);
- if (tmp != NULL) {
- g_autofree gchar *from_xml = NULL;
- from_xml = as_markup_convert_simple (tmp, error);
- if (from_xml == NULL) {
- g_prefix_error (error, "trying to parse '%s': ", tmp);
- return FALSE;
- }
- gs_app_set_description (app,
- GS_APP_QUALITY_HIGHEST,
- from_xml);
- }
-
- /* set icon */
- if (as_app_get_icon_default (item) != NULL && gs_app_get_pixbuf (app) == NULL)
- gs_plugin_refine_item_pixbuf (plugin, app, item);
-
- /* set categories */
- if (as_app_get_categories (item) != NULL &&
- gs_app_get_categories (app)->len == 0)
- gs_app_set_categories (app, as_app_get_categories (item));
-
- /* set project group */
- if (as_app_get_project_group (item) != NULL &&
- gs_app_get_project_group (app) == NULL)
- gs_app_set_project_group (app, as_app_get_project_group (item));
-
- /* set default bundle (if any) */
- if (as_app_get_bundle_default (item) != NULL &&
- gs_app_get_bundle (app) == NULL)
- gs_app_set_bundle (app, as_app_get_bundle_default (item));
-
- /* this is a core application for the desktop and cannot be removed */
- if (as_app_has_compulsory_for_desktop (item, "GNOME") &&
- gs_app_get_kind (app) == GS_APP_KIND_NORMAL)
- gs_app_set_kind (app, GS_APP_KIND_SYSTEM);
-
- /* set id kind */
- if (gs_app_get_id_kind (app) == AS_ID_KIND_UNKNOWN)
- gs_app_set_id_kind (app, as_app_get_id_kind (item));
-
- /* copy all the metadata */
- gs_plugin_appstream_copy_metadata (app, item);
-
- /* set package names */
- pkgnames = as_app_get_pkgnames (item);
- if (pkgnames->len > 0 && gs_app_get_sources(app)->len == 0)
- gs_app_set_sources (app, pkgnames);
-
- /* set addons */
- gs_plugin_refine_add_addons (plugin, app, item);
-
- /* set screenshots */
- gs_plugin_refine_add_screenshots (app, item);
-
- /* are the screenshots perfect */
- if (gs_plugin_appstream_are_screenshots_perfect (item))
- gs_app_add_kudo (app, GS_APP_KUDO_PERFECT_SCREENSHOTS);
-
- /* was this application released recently */
- if (gs_plugin_appstream_is_recent_release (item))
- gs_app_add_kudo (app, GS_APP_KUDO_RECENT_RELEASE);
-
- /* add kudos */
- if (as_app_get_language (item, plugin->locale) > 50)
- gs_app_add_kudo (app, GS_APP_KUDO_MY_LANGUAGE);
-
- /* add new-style kudos */
- kudos = as_app_get_kudos (item);
- for (i = 0; i < kudos->len; i++) {
- tmp = g_ptr_array_index (kudos, i);
- switch (as_kudo_kind_from_string (tmp)) {
- case AS_KUDO_KIND_SEARCH_PROVIDER:
- gs_app_add_kudo (app, GS_APP_KUDO_SEARCH_PROVIDER);
- break;
- case AS_KUDO_KIND_USER_DOCS:
- gs_app_add_kudo (app, GS_APP_KUDO_INSTALLS_USER_DOCS);
- break;
- case AS_KUDO_KIND_APP_MENU:
- gs_app_add_kudo (app, GS_APP_KUDO_USES_APP_MENU);
- break;
- case AS_KUDO_KIND_MODERN_TOOLKIT:
- gs_app_add_kudo (app, GS_APP_KUDO_MODERN_TOOLKIT);
- break;
- case AS_KUDO_KIND_NOTIFICATIONS:
- gs_app_add_kudo (app, GS_APP_KUDO_USES_NOTIFICATIONS);
- break;
- case AS_KUDO_KIND_HIGH_CONTRAST:
- gs_app_add_kudo (app, GS_APP_KUDO_HIGH_CONTRAST);
- break;
- case AS_KUDO_KIND_HI_DPI_ICON:
- gs_app_add_kudo (app, GS_APP_KUDO_HI_DPI_ICON);
- break;
- default:
- g_debug ("no idea how to handle kudo '%s'", tmp);
- break;
- }
- }
-
- return TRUE;
+ return gs_appstream_refine_app (plugin, app, item, error);
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]