[gnome-software/wip/hughsie/banner-editor-ids: 1/4] Add a plugin function to get the list of recent releases
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/wip/hughsie/banner-editor-ids: 1/4] Add a plugin function to get the list of recent releases
- Date: Mon, 15 May 2017 18:58:55 +0000 (UTC)
commit 5ff41d7eaf7895104040ef321b3585eb3743b9a0
Author: Richard Hughes <richard hughsie com>
Date: Mon May 15 15:16:10 2017 +0100
Add a plugin function to get the list of recent releases
lib/gs-cmd.c | 17 +++++-
lib/gs-plugin-loader-sync.c | 48 ++++++++++++++-
lib/gs-plugin-loader-sync.h | 8 ++-
lib/gs-plugin-loader.c | 120 +++++++++++++++++++++++++++++++++++-
lib/gs-plugin-loader.h | 12 +++-
lib/gs-plugin-types.h | 4 +-
lib/gs-plugin-vfuncs.h | 21 ++++++-
lib/gs-plugin.c | 2 +
plugins/core/gs-appstream.c | 50 +++++++++++++++-
plugins/core/gs-appstream.h | 8 ++-
plugins/core/gs-plugin-appstream.c | 12 ++++
plugins/dummy/gs-plugin-dummy.c | 20 ++++++
12 files changed, 313 insertions(+), 9 deletions(-)
---
diff --git a/lib/gs-cmd.c b/lib/gs-cmd.c
index 3477ade..421c259 100644
--- a/lib/gs-cmd.c
+++ b/lib/gs-cmd.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2013-2016 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2013-2017 Richard Hughes <richard hughsie com>
*
* Licensed under the GNU General Public License Version 2
*
@@ -449,6 +449,21 @@ main (int argc, char **argv)
break;
}
}
+ } else if (argc == 2 && g_strcmp0 (argv[1], "recent") == 0) {
+ for (i = 0; i < repeat; i++) {
+ if (list != NULL)
+ g_object_unref (list);
+ list = gs_plugin_loader_get_recent (plugin_loader,
+ 60 * 60 * 24 * 30,
+ refine_flags,
+ GS_PLUGIN_FAILURE_FLAGS_FATAL_ANY,
+ NULL,
+ &error);
+ if (list == NULL) {
+ ret = FALSE;
+ break;
+ }
+ }
} else if (argc == 2 && g_strcmp0 (argv[1], "get-categories") == 0) {
for (i = 0; i < repeat; i++) {
if (categories != NULL)
diff --git a/lib/gs-plugin-loader-sync.c b/lib/gs-plugin-loader-sync.c
index 5b178d0..d7f4e6e 100644
--- a/lib/gs-plugin-loader-sync.c
+++ b/lib/gs-plugin-loader-sync.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2012-2015 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2012-2017 Richard Hughes <richard hughsie com>
*
* Licensed under the GNU General Public License Version 2
*
@@ -441,6 +441,52 @@ gs_plugin_loader_get_category_apps (GsPluginLoader *plugin_loader,
}
static void
+_get_recent_finish_sync (GsPluginLoader *plugin_loader,
+ GAsyncResult *res,
+ GsPluginLoaderHelper *helper)
+{
+ helper->list = gs_plugin_loader_get_recent_finish (plugin_loader,
+ res,
+ helper->error);
+ g_main_loop_quit (helper->loop);
+}
+
+GsAppList *
+gs_plugin_loader_get_recent (GsPluginLoader *plugin_loader,
+ guint64 age,
+ GsPluginRefineFlags refine_flags,
+ GsPluginFailureFlags failure_flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GsPluginLoaderHelper helper;
+
+ /* create temp object */
+ helper.context = g_main_context_new ();
+ helper.loop = g_main_loop_new (helper.context, FALSE);
+ helper.error = error;
+
+ g_main_context_push_thread_default (helper.context);
+
+ /* run async method */
+ gs_plugin_loader_get_recent_async (plugin_loader,
+ age,
+ refine_flags,
+ failure_flags,
+ cancellable,
+ (GAsyncReadyCallback) _get_recent_finish_sync,
+ &helper);
+ g_main_loop_run (helper.loop);
+
+ g_main_context_pop_thread_default (helper.context);
+
+ g_main_loop_unref (helper.loop);
+ g_main_context_unref (helper.context);
+
+ return helper.list;
+}
+
+static void
gs_plugin_loader_app_refine_finish_sync (GsPluginLoader *plugin_loader,
GAsyncResult *res,
GsPluginLoaderHelper *helper)
diff --git a/lib/gs-plugin-loader-sync.h b/lib/gs-plugin-loader-sync.h
index 61ad653..b52f42c 100644
--- a/lib/gs-plugin-loader-sync.h
+++ b/lib/gs-plugin-loader-sync.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2007-2015 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2007-2017 Richard Hughes <richard hughsie com>
*
* Licensed under the GNU General Public License Version 2
*
@@ -78,6 +78,12 @@ GsAppList *gs_plugin_loader_get_category_apps (GsPluginLoader *plugin_loader,
GsPluginFailureFlags failure_flags,
GCancellable *cancellable,
GError **error);
+GsAppList *gs_plugin_loader_get_recent (GsPluginLoader *plugin_loader,
+ guint64 age,
+ GsPluginRefineFlags refine_flags,
+ GsPluginFailureFlags failure_flags,
+ GCancellable *cancellable,
+ GError **error);
gboolean gs_plugin_loader_app_refine (GsPluginLoader *plugin_loader,
GsApp *app,
GsPluginRefineFlags refine_flags,
diff --git a/lib/gs-plugin-loader.c b/lib/gs-plugin-loader.c
index 625e0e7..137591d 100644
--- a/lib/gs-plugin-loader.c
+++ b/lib/gs-plugin-loader.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2007-2016 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2007-2017 Richard Hughes <richard hughsie com>
*
* Licensed under the GNU General Public License Version 2
*
@@ -113,6 +113,11 @@ typedef gboolean (*GsPluginCategoryFunc) (GsPlugin *plugin,
GsAppList *list,
GCancellable *cancellable,
GError **error);
+typedef gboolean (*GsPluginGetRecentFunc) (GsPlugin *plugin,
+ GsAppList *list,
+ guint64 age,
+ GCancellable *cancellable,
+ GError **error);
typedef gboolean (*GsPluginResultsFunc) (GsPlugin *plugin,
GsAppList *list,
GCancellable *cancellable,
@@ -193,6 +198,7 @@ typedef struct {
GsPluginAction action;
gboolean anything_ran;
guint max_results;
+ guint64 age;
GsAppListSortFunc sort_func;
gpointer sort_func_data;
} GsPluginLoaderJob;
@@ -659,6 +665,13 @@ gs_plugin_loader_call_vfunc (GsPluginLoaderJob *job,
cancellable, &error_local);
}
break;
+ case GS_PLUGIN_ACTION_GET_RECENT:
+ {
+ GsPluginGetRecentFunc plugin_func = func;
+ ret = plugin_func (plugin, list, job->age,
+ cancellable, &error_local);
+ }
+ break;
case GS_PLUGIN_ACTION_GET_UPDATES:
case GS_PLUGIN_ACTION_GET_DISTRO_UPDATES:
case GS_PLUGIN_ACTION_GET_UNVOTED_REVIEWS:
@@ -2650,6 +2663,111 @@ gs_plugin_loader_get_category_apps_finish (GsPluginLoader *plugin_loader,
/******************************************************************************/
static void
+gs_plugin_loader_get_recent_thread_cb (GTask *task,
+ gpointer object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (object);
+ GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (plugin_loader);
+ GError *error = NULL;
+ GsPluginLoaderJob *job = (GsPluginLoaderJob *) task_data;
+
+ /* run each plugin */
+ for (guint i = 0; i < priv->plugins->len; i++) {
+ GsPlugin *plugin = g_ptr_array_index (priv->plugins, i);
+ if (g_task_return_error_if_cancelled (task))
+ return;
+ if (!gs_plugin_loader_call_vfunc (job, plugin, NULL, NULL,
+ cancellable, &error)) {
+ g_task_return_error (task, error);
+ return;
+ }
+ }
+
+ /* run refine() on each one */
+ if (!gs_plugin_loader_run_refine (job, job->list, cancellable, &error)) {
+ g_task_return_error (task, error);
+ return;
+ }
+
+ /* filter package list */
+ gs_app_list_filter (job->list, gs_plugin_loader_app_is_non_compulsory, NULL);
+ gs_app_list_filter (job->list, gs_plugin_loader_app_is_valid, job);
+ gs_app_list_filter (job->list, gs_plugin_loader_filter_qt_for_gtk, NULL);
+ gs_app_list_filter (job->list, gs_plugin_loader_get_app_is_compatible, plugin_loader);
+
+ /* filter duplicates with priority */
+ gs_app_list_filter (job->list, gs_plugin_loader_app_set_prio, plugin_loader);
+ gs_app_list_filter_duplicates (job->list, GS_APP_LIST_FILTER_FLAG_KEY_ID);
+
+ /* sort, just in case the UI doesn't do this */
+ gs_app_list_sort (job->list, gs_plugin_loader_app_sort_name_cb, NULL);
+
+ /* success */
+ g_task_return_pointer (task, g_object_ref (job->list), (GDestroyNotify) g_object_unref);
+}
+
+/**
+ * gs_plugin_loader_get_recent_async:
+ *
+ * This method calls all plugins that implement the gs_plugin_add_recent()
+ * function. The plugins return applications that have has upstream releases
+ * within the duration of @age;
+ **/
+void
+gs_plugin_loader_get_recent_async (GsPluginLoader *plugin_loader,
+ guint64 age,
+ GsPluginRefineFlags refine_flags,
+ GsPluginFailureFlags failure_flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GsPluginLoaderJob *job;
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (GS_IS_PLUGIN_LOADER (plugin_loader));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ /* save job */
+ job = gs_plugin_loader_job_new (plugin_loader);
+ job->refine_flags = refine_flags;
+ job->failure_flags = failure_flags;
+ job->list = gs_app_list_new ();
+ job->age = age;
+ job->action = GS_PLUGIN_ACTION_GET_RECENT;
+ job->function_name = "gs_plugin_add_recent";
+ gs_plugin_loader_job_debug (job);
+
+ /* run in a thread */
+ task = g_task_new (plugin_loader, cancellable, callback, user_data);
+ g_task_set_task_data (task, job, (GDestroyNotify) gs_plugin_loader_job_free);
+ g_task_run_in_thread (task, gs_plugin_loader_get_recent_thread_cb);
+}
+
+/**
+ * gs_plugin_loader_get_recent_finish:
+ *
+ * Return value: (element-type GsApp) (transfer full): A list of applications
+ **/
+GsAppList *
+gs_plugin_loader_get_recent_finish (GsPluginLoader *plugin_loader,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_LOADER (plugin_loader), NULL);
+ g_return_val_if_fail (G_IS_TASK (res), NULL);
+ g_return_val_if_fail (g_task_is_valid (res, plugin_loader), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ gs_utils_error_convert_gio (error);
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+/******************************************************************************/
+
+static void
gs_plugin_loader_app_refine_thread_cb (GTask *task,
gpointer object,
gpointer task_data,
diff --git a/lib/gs-plugin-loader.h b/lib/gs-plugin-loader.h
index 745df87..c3820f2 100644
--- a/lib/gs-plugin-loader.h
+++ b/lib/gs-plugin-loader.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2007-2015 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2007-2017 Richard Hughes <richard hughsie com>
*
* Licensed under the GNU General Public License Version 2
*
@@ -134,6 +134,16 @@ void gs_plugin_loader_get_category_apps_async (GsPluginLoader
*plugin_loader,
GsAppList *gs_plugin_loader_get_category_apps_finish (GsPluginLoader *plugin_loader,
GAsyncResult *res,
GError **error);
+void gs_plugin_loader_get_recent_async (GsPluginLoader *plugin_loader,
+ guint64 age,
+ GsPluginRefineFlags refine_flags,
+ GsPluginFailureFlags failure_flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GsAppList *gs_plugin_loader_get_recent_finish (GsPluginLoader *plugin_loader,
+ GAsyncResult *res,
+ GError **error);
void gs_plugin_loader_search_async (GsPluginLoader *plugin_loader,
const gchar *value,
guint max_results,
diff --git a/lib/gs-plugin-types.h b/lib/gs-plugin-types.h
index e0519f3..077a38e 100644
--- a/lib/gs-plugin-types.h
+++ b/lib/gs-plugin-types.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2012-2016 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2012-2017 Richard Hughes <richard hughsie com>
*
* Licensed under the GNU General Public License Version 2
*
@@ -262,6 +262,7 @@ typedef enum {
* @GS_PLUGIN_ACTION_AUTH_REGISTER: Authentication register action
* @GS_PLUGIN_ACTION_AUTH_LOST_PASSWORD: Authentication lost password action
* @GS_PLUGIN_ACTION_URL_TO_APP: Convert the file to an application
+ * @GS_PLUGIN_ACTION_GET_RECENT: Get the apps recently released
*
* The plugin action.
**/
@@ -304,6 +305,7 @@ typedef enum {
GS_PLUGIN_ACTION_AUTH_REGISTER,
GS_PLUGIN_ACTION_AUTH_LOST_PASSWORD,
GS_PLUGIN_ACTION_URL_TO_APP,
+ GS_PLUGIN_ACTION_GET_RECENT,
/*< private >*/
GS_PLUGIN_ACTION_LAST
} GsPluginAction;
diff --git a/lib/gs-plugin-vfuncs.h b/lib/gs-plugin-vfuncs.h
index ae6a29b..4de2449 100644
--- a/lib/gs-plugin-vfuncs.h
+++ b/lib/gs-plugin-vfuncs.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2012-2016 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2012-2017 Richard Hughes <richard hughsie com>
*
* Licensed under the GNU General Public License Version 2
*
@@ -324,6 +324,25 @@ gboolean gs_plugin_add_category_apps (GsPlugin *plugin,
GError **error);
/**
+ * gs_plugin_add_recent:
+ * @plugin: a #GsPlugin
+ * @age: a number of seconds
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: a #GError, or %NULL
+ *
+ * Return all the applications that have had upstream releases recently.
+ *
+ * Plugins are expected to add new apps using gs_app_list_add().
+ *
+ * Returns: %TRUE for success or if not relevant
+ **/
+gboolean gs_plugin_add_recent (GsPlugin *plugin,
+ GsAppList *list,
+ guint64 age,
+ GCancellable *cancellable,
+ GError **error);
+
+/**
* gs_plugin_add_popular:
* @plugin: a #GsPlugin
* @list: a #GsAppList
diff --git a/lib/gs-plugin.c b/lib/gs-plugin.c
index 0f636a1..55e999b 100644
--- a/lib/gs-plugin.c
+++ b/lib/gs-plugin.c
@@ -1750,6 +1750,8 @@ gs_plugin_action_to_string (GsPluginAction action)
return "auth-register";
if (action == GS_PLUGIN_ACTION_AUTH_LOST_PASSWORD)
return "auth-lost-password";
+ if (action == GS_PLUGIN_ACTION_GET_RECENT)
+ return "get-recent";
return NULL;
}
diff --git a/plugins/core/gs-appstream.c b/plugins/core/gs-appstream.c
index 33df85b..033df31 100644
--- a/plugins/core/gs-appstream.c
+++ b/plugins/core/gs-appstream.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2015-2016 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2015-2017 Richard Hughes <richard hughsie com>
*
* Licensed under the GNU General Public License Version 2
*
@@ -1092,6 +1092,54 @@ gs_appstream_add_popular (GsPlugin *plugin,
return TRUE;
}
+static gboolean
+_as_app_is_recent (AsApp *app, guint64 age)
+{
+ AsRelease *rel;
+ guint64 ts;
+ guint64 now;
+
+ rel = as_app_get_release_default (app);
+ if (rel == NULL)
+ return FALSE;
+ ts = as_release_get_timestamp (rel);
+ if (ts == 0)
+ return FALSE;
+ now = (guint64) g_get_real_time () / G_USEC_PER_SEC;
+ return (now - ts) < age;
+}
+
+gboolean
+gs_appstream_add_recent (GsPlugin *plugin,
+ AsStore *store,
+ GsAppList *list,
+ guint64 age,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GPtrArray *array;
+ g_autoptr(AsProfileTask) ptask = NULL;
+
+ /* find out how many packages are in each category */
+ ptask = as_profile_start_literal (gs_plugin_get_profile (plugin),
+ "appstream::add-recent");
+ g_assert (ptask != NULL);
+ array = as_store_get_apps (store);
+ for (guint i = 0; i < array->len; i++) {
+ g_autoptr(GsApp) app = NULL;
+ AsApp *item = g_ptr_array_index (array, i);
+ if (as_app_get_id (item) == NULL)
+ continue;
+ if (!_as_app_is_recent (item, age))
+ continue;
+ app = gs_appstream_create_app (plugin, item, error);
+ if (app == NULL)
+ return FALSE;
+ gs_app_list_add (list, app);
+ }
+ return TRUE;
+}
+
gboolean
gs_appstream_add_featured (GsPlugin *plugin,
AsStore *store,
diff --git a/plugins/core/gs-appstream.h b/plugins/core/gs-appstream.h
index c4c6d98..dab26d5 100644
--- a/plugins/core/gs-appstream.h
+++ b/plugins/core/gs-appstream.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
- * Copyright (C) 2015-2016 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2015-2017 Richard Hughes <richard hughsie com>
*
* Licensed under the GNU General Public License Version 2
*
@@ -63,6 +63,12 @@ gboolean gs_appstream_add_featured (GsPlugin *plugin,
GsAppList *list,
GCancellable *cancellable,
GError **error);
+gboolean gs_appstream_add_recent (GsPlugin *plugin,
+ AsStore *store,
+ GsAppList *list,
+ guint64 age,
+ GCancellable *cancellable,
+ GError **error);
void gs_appstream_add_extra_info (GsPlugin *plugin,
AsApp *app);
diff --git a/plugins/core/gs-plugin-appstream.c b/plugins/core/gs-plugin-appstream.c
index 14f2865..9ce8069 100644
--- a/plugins/core/gs-plugin-appstream.c
+++ b/plugins/core/gs-plugin-appstream.c
@@ -646,6 +646,18 @@ gs_plugin_add_featured (GsPlugin *plugin,
error);
}
+gboolean
+gs_plugin_add_recent (GsPlugin *plugin,
+ GsAppList *list,
+ guint64 age,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GsPluginData *priv = gs_plugin_get_data (plugin);
+ return gs_appstream_add_recent (plugin, priv->store, list, age,
+ cancellable, error);
+}
+
static gboolean
gs_plugin_appstream_refresh_url (GsPlugin *plugin,
const gchar *url,
diff --git a/plugins/dummy/gs-plugin-dummy.c b/plugins/dummy/gs-plugin-dummy.c
index d2190c3..f1e3e52 100644
--- a/plugins/dummy/gs-plugin-dummy.c
+++ b/plugins/dummy/gs-plugin-dummy.c
@@ -676,6 +676,26 @@ gs_plugin_add_category_apps (GsPlugin *plugin,
}
gboolean
+gs_plugin_add_recent (GsPlugin *plugin,
+ GsAppList *list,
+ guint64 age,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(GsApp) 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, "View and use virtual machines");
+ gs_app_set_url (app, AS_URL_KIND_HOMEPAGE, "http://www.box.org");
+ gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
+ gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
+ gs_app_set_pixbuf (app, gdk_pixbuf_new_from_file
("/usr/share/icons/hicolor/48x48/apps/chiron.desktop.png", NULL));
+ gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
+ gs_app_set_management_plugin (app, gs_plugin_get_name (plugin));
+ gs_app_list_add (list, app);
+ return TRUE;
+}
+
+gboolean
gs_plugin_add_distro_upgrades (GsPlugin *plugin,
GsAppList *list,
GCancellable *cancellable,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]