Commit 476c4571 authored by Richard Hughes's avatar Richard Hughes

Add a plugin function to get the list of recent releases

parent 7a0e4034
/* -*- 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 * 60,
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)
......
/* -*- 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
*
......@@ -440,6 +440,52 @@ gs_plugin_loader_get_category_apps (GsPluginLoader *plugin_loader,
return helper.list;
}
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,
......
/* -*- 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,
......
/* -*- 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:
......@@ -2649,6 +2662,120 @@ 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;
const guint max_results = 20;
/* 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;
}
}
/* limit: TODO, use sort func */
if (gs_app_list_length (job->list) > max_results) {
gs_app_list_randomize (job->list);
g_debug ("truncating results to %u from %u",
max_results, gs_app_list_length (job->list));
gs_app_list_truncate (job->list, max_results);
}
/* 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,
......
/* -*- 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,
......
/* -*- 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;
......
/* -*- 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
*
......@@ -323,6 +323,25 @@ gboolean gs_plugin_add_category_apps (GsPlugin *plugin,
GCancellable *cancellable,
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
......
......@@ -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;
}
......
/* -*- 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,
......
/* -*- 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);
......
......@@ -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,
......
......@@ -675,6 +675,26 @@ gs_plugin_add_category_apps (GsPlugin *plugin,
return TRUE;
}
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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment