[gnome-software] Use a standard GAsyncReadyCallback when installing and removing packages



commit d0f3c738b97ce8280c63f88b1fa3fb8a45eeac20
Author: Richard Hughes <richard hughsie com>
Date:   Thu Oct 10 16:23:31 2013 +0100

    Use a standard GAsyncReadyCallback when installing and removing packages
    
    Additionally, this gives us both sync and async versions of all the action
    methods, which we'll need for future functionality.

 src/gs-plugin-loader-sync.c |   50 +++++
 src/gs-plugin-loader-sync.h |    5 +
 src/gs-plugin-loader.c      |  496 +++++++++++++++++++++++--------------------
 src/gs-plugin-loader.h      |   25 +--
 src/gs-self-test.c          |   10 +-
 src/gs-shell-details.c      |   70 +++++--
 src/gs-shell-installed.c    |   38 +++-
 src/gs-shell-search.c       |   73 +++++--
 8 files changed, 472 insertions(+), 295 deletions(-)
---
diff --git a/src/gs-plugin-loader-sync.c b/src/gs-plugin-loader-sync.c
index 9ed84ea..5270f12 100644
--- a/src/gs-plugin-loader-sync.c
+++ b/src/gs-plugin-loader-sync.c
@@ -309,4 +309,54 @@ gs_plugin_loader_app_refine (GsPluginLoader *plugin_loader,
        return helper.ret;
 }
 
+/**
+ * gs_plugin_loader_app_action_finish_sync:
+ **/
+static void
+gs_plugin_loader_app_action_finish_sync (GsPluginLoader *plugin_loader,
+                                        GAsyncResult *res,
+                                        GsPluginLoaderHelper *helper)
+{
+       helper->ret = gs_plugin_loader_app_action_finish (plugin_loader,
+                                                         res,
+                                                         helper->error);
+       g_main_loop_quit (helper->loop);
+}
+
+/**
+ * gs_plugin_loader_app_action:
+ **/
+gboolean
+gs_plugin_loader_app_action (GsPluginLoader *plugin_loader,
+                            GsApp *app,
+                            GsPluginLoaderAction action,
+                            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_app_action_async (plugin_loader,
+                                          app,
+                                          action,
+                                          cancellable,
+                                          (GAsyncReadyCallback) gs_plugin_loader_app_action_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.ret;
+}
+
 /* vim: set noexpandtab: */
diff --git a/src/gs-plugin-loader-sync.h b/src/gs-plugin-loader-sync.h
index d88d113..6cbc480 100644
--- a/src/gs-plugin-loader-sync.h
+++ b/src/gs-plugin-loader-sync.h
@@ -54,6 +54,11 @@ gboolean      gs_plugin_loader_app_refine            (GsPluginLoader *plugin_loader,
                                                         GsPluginRefineFlags flags,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
+gboolean        gs_plugin_loader_app_action            (GsPluginLoader *plugin_loader,
+                                                        GsApp          *app,
+                                                        GsPluginLoaderAction action,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
 
 G_END_DECLS
 
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index d0ac7b7..fc90d03 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -406,10 +406,115 @@ gs_plugin_loader_get_app_is_compatible (GsApp *app, gpointer user_data)
        return FALSE;
 }
 
+
+/**
+ * gs_plugin_loader_run_action:
+ **/
+static gboolean
+gs_plugin_loader_run_action (GsPluginLoader *plugin_loader,
+                            GsApp *app,
+                            const gchar *function_name,
+                            GCancellable *cancellable,
+                            GError **error)
+{
+       gboolean exists;
+       gboolean ret = FALSE;
+       gboolean anything_ran = FALSE;
+       gchar *profile_id;
+       GError *error_local = NULL;
+       GsPluginActionFunc plugin_func = NULL;
+       GsPlugin *plugin;
+       guint i;
+
+       /* run each plugin */
+       for (i = 0; i < plugin_loader->priv->plugins->len; i++) {
+               plugin = g_ptr_array_index (plugin_loader->priv->plugins, i);
+               if (!plugin->enabled)
+                       continue;
+               ret = g_cancellable_set_error_if_cancelled (cancellable, error);
+               if (ret) {
+                       ret = FALSE;
+                       goto out;
+               }
+               exists = g_module_symbol (plugin->module,
+                                         function_name,
+                                         (gpointer *) &plugin_func);
+               if (!exists)
+                       continue;
+               profile_id = g_strdup_printf ("GsPlugin::%s(%s)",
+                                             plugin->name, function_name);
+               gs_profile_start (plugin_loader->priv->profile, profile_id);
+               ret = plugin_func (plugin, app, cancellable, &error_local);
+               if (!ret) {
+                       if (g_error_matches (error_local,
+                                            GS_PLUGIN_ERROR,
+                                            GS_PLUGIN_ERROR_NOT_SUPPORTED)) {
+                               g_debug ("not supported for plugin %s: %s",
+                                        plugin->name,
+                                        error_local->message);
+                               g_clear_error (&error_local);
+                       } else {
+                               g_propagate_error (error, error_local);
+                               goto out;
+                       }
+               }
+               gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
+               gs_profile_stop (plugin_loader->priv->profile, profile_id);
+               g_free (profile_id);
+               anything_ran = TRUE;
+       }
+
+       /* nothing ran */
+       if (!anything_ran) {
+               ret = FALSE;
+               g_set_error (error,
+                            GS_PLUGIN_LOADER_ERROR,
+                            GS_PLUGIN_LOADER_ERROR_FAILED,
+                            "no plugin could handle %s",
+                            function_name);
+               goto out;
+       }
+
+       /* success */
+       ret = TRUE;
+out:
+       return ret;
+}
+
+typedef struct {
+       GsApp *app;
+       GsAppState state;
+} AppStateData;
+
+static gboolean
+set_state_idle_cb (gpointer data)
+{
+       AppStateData *app_data = data;
+
+       gs_app_set_state (app_data->app, app_data->state);
+       g_object_unref (app_data->app);
+       g_free (app_data);
+
+       return G_SOURCE_REMOVE;
+}
+
+static void
+gs_app_set_state_in_idle (GsApp *app, GsAppState state)
+{
+       AppStateData *app_data;
+
+       app_data = g_new (AppStateData, 1);
+       app_data->app = g_object_ref (app);
+       app_data->state = state;
+
+       g_idle_add (set_state_idle_cb, app_data);
+}
+
 /******************************************************************************/
 
 /* async state */
 typedef struct {
+       const gchar                     *function_name;
        gboolean                         ret;
        GCancellable                    *cancellable;
        GList                           *list;
@@ -419,6 +524,9 @@ typedef struct {
        gchar                           *value;
        GsCategory                      *category;
        GsApp                           *app;
+       GsAppState                       state_progress;
+       GsAppState                       state_success;
+       GsAppState                       state_failure;
 } GsPluginLoaderAsyncState;
 
 /******************************************************************************/
@@ -1627,122 +1735,29 @@ gs_plugin_loader_app_refine_finish (GsPluginLoader *plugin_loader,
 /******************************************************************************/
 
 /**
- * gs_plugin_loader_run_action:
+ * gs_plugin_loader_app_action_state_finish:
  **/
-static gboolean
-gs_plugin_loader_run_action (GsPluginLoader *plugin_loader,
-                            GsApp *app,
-                            const gchar *function_name,
-                            GCancellable *cancellable,
-                            GError **error)
+static void
+gs_plugin_loader_app_action_state_finish (GsPluginLoaderAsyncState *state,
+                                         const GError *error)
 {
-       gboolean exists;
-       gboolean ret = FALSE;
-       gboolean anything_ran = FALSE;
-       gchar *profile_id;
-       GError *error_local = NULL;
-       GsPluginActionFunc plugin_func = NULL;
-       GsPlugin *plugin;
-       guint i;
-
-       /* run each plugin */
-       for (i = 0; i < plugin_loader->priv->plugins->len; i++) {
-               plugin = g_ptr_array_index (plugin_loader->priv->plugins, i);
-               if (!plugin->enabled)
-                       continue;
-               ret = g_cancellable_set_error_if_cancelled (cancellable, error);
-               if (ret) {
-                       ret = FALSE;
-                       goto out;
-               }
-               exists = g_module_symbol (plugin->module,
-                                         function_name,
-                                         (gpointer *) &plugin_func);
-               if (!exists)
-                       continue;
-               profile_id = g_strdup_printf ("GsPlugin::%s(%s)",
-                                             plugin->name, function_name);
-               gs_profile_start (plugin_loader->priv->profile, profile_id);
-               ret = plugin_func (plugin, app, cancellable, &error_local);
-               if (!ret) {
-                       if (g_error_matches (error_local,
-                                            GS_PLUGIN_ERROR,
-                                            GS_PLUGIN_ERROR_NOT_SUPPORTED)) {
-                               g_debug ("not supported for plugin %s: %s",
-                                        plugin->name,
-                                        error_local->message);
-                               g_clear_error (&error_local);
-                       } else {
-                               g_propagate_error (error, error_local);
-                               goto out;
-                       }
-               }
-               gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
-               gs_profile_stop (plugin_loader->priv->profile, profile_id);
-               g_free (profile_id);
-               anything_ran = TRUE;
-       }
-
-       /* nothing ran */
-       if (!anything_ran) {
-               ret = FALSE;
-               g_set_error (error,
-                            GS_PLUGIN_LOADER_ERROR,
-                            GS_PLUGIN_LOADER_ERROR_FAILED,
-                            "no plugin could handle %s",
-                            function_name);
-               goto out;
+       if (state->ret) {
+               g_simple_async_result_set_op_res_gboolean (state->res, TRUE);
+       } else {
+               g_simple_async_result_set_from_error (state->res, error);
        }
 
-       /* success */
-       ret = TRUE;
-out:
-       return ret;
-}
-
-/**
- * gs_plugin_loader_get_state_for_app:
- **/
-GsAppState
-gs_plugin_loader_get_state_for_app (GsPluginLoader *plugin_loader, GsApp *app)
-{
-       GsAppState state = GS_APP_STATE_UNKNOWN;
-       GsApp *tmp;
-       GsPluginLoaderPrivate *priv = plugin_loader->priv;
-       guint i;
-
-       for (i = 0; i < priv->pending_apps->len; i++) {
-               tmp = g_ptr_array_index (priv->pending_apps, i);
-               if (g_strcmp0 (gs_app_get_id (tmp), gs_app_get_id (app)) == 0) {
-                       state = gs_app_get_state (tmp);
-                       break;
-               }
-       }
-       return state;
-}
+       /* deallocate */
+       if (state->cancellable != NULL)
+               g_object_unref (state->cancellable);
 
-/**
- * gs_plugin_loader_get_pending:
- **/
-GPtrArray *
-gs_plugin_loader_get_pending (GsPluginLoader *plugin_loader)
-{
-       return g_ptr_array_ref (plugin_loader->priv->pending_apps);
+       g_free (state->value);
+       g_object_unref (state->app);
+       g_object_unref (state->res);
+       g_object_unref (state->plugin_loader);
+       g_slice_free (GsPluginLoaderAsyncState, state);
 }
 
-typedef struct {
-       GsPluginLoader  *plugin_loader;
-       GsApp           *app;
-       GCancellable    *cancellable;
-       GThread         *thread;
-       const gchar     *function_name;
-       GsAppState       state_progress;
-       GsAppState       state_success;
-       GsAppState       state_failure;
-       GsPluginLoaderFinishedFunc func;
-       gpointer         func_user_data;
-} GsPluginLoaderThreadHelper;
-
 static gboolean
 emit_pending_apps_idle (gpointer loader)
 {
@@ -1752,158 +1767,173 @@ emit_pending_apps_idle (gpointer loader)
        return G_SOURCE_REMOVE;
 }
 
-typedef struct {
-       GsApp *app;
-       GsAppState state;
-} AppStateData;
-
-static gboolean
-set_state_idle_cb (gpointer data)
-{
-       AppStateData *app_data = data;
-
-       gs_app_set_state (app_data->app, app_data->state);
-       g_object_unref (app_data->app);
-       g_free (app_data);
-
-       return G_SOURCE_REMOVE;
-}
-
-static void
-gs_app_set_state_in_idle (GsApp *app, GsAppState state)
-{
-       AppStateData *app_data;
-
-       app_data = g_new (AppStateData, 1);
-       app_data->app = g_object_ref (app);
-       app_data->state = state;
-
-       g_idle_add (set_state_idle_cb, app_data);
-}
-
 /**
- * gs_plugin_loader_thread_func:
+ * gs_plugin_loader_app_action_thread_cb:
  **/
-static gpointer
-gs_plugin_loader_thread_func (gpointer user_data)
+static void
+gs_plugin_loader_app_action_thread_cb (GSimpleAsyncResult *res,
+                                      GObject *object,
+                                      GCancellable *cancellable)
 {
-       GsPluginLoaderThreadHelper *helper = (GsPluginLoaderThreadHelper *) user_data;
-       gboolean ret;
        GError *error = NULL;
+       GsPluginLoaderAsyncState *state = (GsPluginLoaderAsyncState *) g_object_get_data (G_OBJECT 
(cancellable), "state");
+       GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (object);
 
        /* add to list */
-       gs_app_set_state_in_idle (helper->app, helper->state_progress);
-       g_mutex_lock (&helper->plugin_loader->priv->pending_apps_mutex);
-       g_ptr_array_add (helper->plugin_loader->priv->pending_apps, g_object_ref (helper->app));
-       g_mutex_unlock (&helper->plugin_loader->priv->pending_apps_mutex);
-       g_idle_add (emit_pending_apps_idle, g_object_ref (helper->plugin_loader));
-
-       /* run action */
-       ret = gs_plugin_loader_run_action (helper->plugin_loader,
-                                          helper->app,
-                                          helper->function_name,
-                                          helper->cancellable,
-                                          &error);
-       if (!ret) {
-               gs_app_set_state_in_idle (helper->app, helper->state_failure);
-               g_warning ("failed to complete %s: %s", helper->function_name, error->message);
+       if (state->state_progress != GS_APP_STATE_UNKNOWN)
+               gs_app_set_state_in_idle (state->app, state->state_progress);
+       g_mutex_lock (&state->plugin_loader->priv->pending_apps_mutex);
+       g_ptr_array_add (state->plugin_loader->priv->pending_apps, g_object_ref (state->app));
+       g_mutex_unlock (&state->plugin_loader->priv->pending_apps_mutex);
+       g_idle_add (emit_pending_apps_idle, g_object_ref (state->plugin_loader));
+
+       /* perform action */
+       state->ret = gs_plugin_loader_run_action (plugin_loader,
+                                                 state->app,
+                                                 state->function_name,
+                                                 state->cancellable,
+                                                 &error);
+       if (!state->ret) {
+               gs_app_set_state_in_idle (state->app, state->state_failure);
+               gs_plugin_loader_app_action_state_finish (state, error);
                g_error_free (error);
-       } else {
-               gs_app_set_state_in_idle (helper->app, helper->state_success);
+               return;
        }
 
        /* remove from list */
-       g_mutex_lock (&helper->plugin_loader->priv->pending_apps_mutex);
-       g_ptr_array_remove (helper->plugin_loader->priv->pending_apps, helper->app);
-       g_mutex_unlock (&helper->plugin_loader->priv->pending_apps_mutex);
-       g_idle_add (emit_pending_apps_idle, g_object_ref (helper->plugin_loader));
-
-       /* fire finished func */
-       if (helper->func != NULL) {
-               helper->func (helper->plugin_loader,
-                             ret ? helper->app : NULL,
-                             helper->func_user_data);
-       }
+       g_mutex_lock (&state->plugin_loader->priv->pending_apps_mutex);
+       g_ptr_array_remove (state->plugin_loader->priv->pending_apps, state->app);
+       g_mutex_unlock (&state->plugin_loader->priv->pending_apps_mutex);
+       g_idle_add (emit_pending_apps_idle, g_object_ref (state->plugin_loader));
 
-       g_object_unref (helper->plugin_loader);
-       g_object_unref (helper->app);
-       if (helper->cancellable != NULL)
-               g_object_unref (helper->cancellable);
-       g_free (helper);
-       return NULL;
+       /* success */
+       if (state->state_success != GS_APP_STATE_UNKNOWN)
+               gs_app_set_state_in_idle (state->app, state->state_success);
+       gs_plugin_loader_app_action_state_finish (state, NULL);
 }
 
 /**
- * gs_plugin_loader_app_install:
+ * gs_plugin_loader_app_action_async:
+ *
+ * This method calls all plugins that implement the gs_plugin_action()
+ * function.
  **/
 void
-gs_plugin_loader_app_install (GsPluginLoader *plugin_loader,
-                             GsApp *app,
-                             GsPluginRefineFlags flags,
-                             GCancellable *cancellable,
-                             GsPluginLoaderFinishedFunc func,
-                             gpointer user_data)
+gs_plugin_loader_app_action_async (GsPluginLoader *plugin_loader,
+                                  GsApp *app,
+                                  GsPluginLoaderAction action,
+                                  GCancellable *cancellable,
+                                  GAsyncReadyCallback callback,
+                                  gpointer user_data)
 {
-       GsPluginLoaderThreadHelper *helper;
-       helper = g_new0 (GsPluginLoaderThreadHelper, 1);
-       helper->plugin_loader = g_object_ref (plugin_loader);
-       helper->app = g_object_ref (app);
-       helper->func = func;
-       helper->func_user_data = user_data;
+       GCancellable *tmp;
+       GsPluginLoaderAsyncState *state;
+
+       g_return_if_fail (GS_IS_PLUGIN_LOADER (plugin_loader));
+       g_return_if_fail (GS_IS_APP (app));
+       g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+       /* save state */
+       state = g_slice_new0 (GsPluginLoaderAsyncState);
+       state->res = g_simple_async_result_new (G_OBJECT (plugin_loader),
+                                               callback,
+                                               user_data,
+                                               gs_plugin_loader_app_action_async);
+       state->plugin_loader = g_object_ref (plugin_loader);
+       state->app = g_object_ref (app);
        if (cancellable != NULL)
-               helper->cancellable = g_object_ref (cancellable);
-       helper->function_name = "gs_plugin_app_install";
-       helper->state_progress = GS_APP_STATE_INSTALLING;
-       helper->state_success = GS_APP_STATE_INSTALLED;
-       helper->state_failure = GS_APP_STATE_AVAILABLE;
-       helper->thread = g_thread_new ("GsPluginLoader::install",
-                                      gs_plugin_loader_thread_func,
-                                      helper);
+               state->cancellable = g_object_ref (cancellable);
+
+       switch (action) {
+       case GS_PLUGIN_LOADER_ACTION_INSTALL:
+               state->function_name = "gs_plugin_app_install";
+               state->state_progress = GS_APP_STATE_INSTALLING;
+               state->state_success = GS_APP_STATE_INSTALLED;
+               state->state_failure = GS_APP_STATE_AVAILABLE;
+               break;
+       case GS_PLUGIN_LOADER_ACTION_REMOVE:
+               state->function_name = "gs_plugin_app_remove";
+               state->state_progress = GS_APP_STATE_REMOVING;
+               state->state_success = GS_APP_STATE_AVAILABLE;
+               state->state_failure = GS_APP_STATE_INSTALLED;
+               break;
+       case GS_PLUGIN_LOADER_ACTION_SET_RATING:
+               state->function_name = "gs_plugin_app_set_rating";
+               state->state_progress = GS_APP_STATE_UNKNOWN;
+               state->state_success = GS_APP_STATE_UNKNOWN;
+               state->state_failure = GS_APP_STATE_UNKNOWN;
+               break;
+       default:
+               g_assert_not_reached ();
+               break;
+       }
+
+       /* run in a thread */
+       tmp = g_cancellable_new ();
+       g_object_set_data (G_OBJECT (tmp), "state", state);
+       g_simple_async_result_run_in_thread (G_SIMPLE_ASYNC_RESULT (state->res),
+                                            gs_plugin_loader_app_action_thread_cb,
+                                            0,
+                                            (GCancellable *) tmp);
+       g_object_unref (tmp);
 }
 
 /**
- * gs_plugin_loader_app_remove:
+ * gs_plugin_loader_app_action_finish:
+ *
+ * Return value: success
  **/
-void
-gs_plugin_loader_app_remove (GsPluginLoader *plugin_loader,
-                            GsApp *app,
-                            GsPluginRefineFlags flags,
-                            GCancellable *cancellable,
-                            GsPluginLoaderFinishedFunc func,
-                            gpointer user_data)
+gboolean
+gs_plugin_loader_app_action_finish (GsPluginLoader *plugin_loader,
+                                   GAsyncResult *res,
+                                   GError **error)
 {
-       GsPluginLoaderThreadHelper *helper;
-       helper = g_new0 (GsPluginLoaderThreadHelper, 1);
-       helper->plugin_loader = g_object_ref (plugin_loader);
-       helper->app = g_object_ref (app);
-       helper->func = func;
-       helper->func_user_data = user_data;
-       if (cancellable != NULL)
-               helper->cancellable = g_object_ref (cancellable);
-       helper->function_name = "gs_plugin_app_remove";
-       helper->state_progress = GS_APP_STATE_REMOVING;
-       helper->state_success = GS_APP_STATE_AVAILABLE;
-       helper->state_failure = GS_APP_STATE_INSTALLED;
-       helper->thread = g_thread_new ("GsPluginLoader::remove",
-                                      gs_plugin_loader_thread_func,
-                                      helper);
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (GS_IS_PLUGIN_LOADER (plugin_loader), FALSE);
+       g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (res), FALSE);
+       g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+       /* failed */
+       simple = G_SIMPLE_ASYNC_RESULT (res);
+       if (g_simple_async_result_propagate_error (simple, error))
+               return FALSE;
+
+       /* grab detail */
+       return g_simple_async_result_get_op_res_gboolean (simple);
 }
 
+/******************************************************************************/
+
+
 /**
- * gs_plugin_loader_app_set_rating:
+ * gs_plugin_loader_get_state_for_app:
  **/
-gboolean
-gs_plugin_loader_app_set_rating (GsPluginLoader *plugin_loader,
-                                GsApp *app,
-                                GsPluginRefineFlags flags,
-                                GCancellable *cancellable,
-                                GError **error)
+GsAppState
+gs_plugin_loader_get_state_for_app (GsPluginLoader *plugin_loader, GsApp *app)
+{
+       GsAppState state = GS_APP_STATE_UNKNOWN;
+       GsApp *tmp;
+       GsPluginLoaderPrivate *priv = plugin_loader->priv;
+       guint i;
+
+       for (i = 0; i < priv->pending_apps->len; i++) {
+               tmp = g_ptr_array_index (priv->pending_apps, i);
+               if (g_strcmp0 (gs_app_get_id (tmp), gs_app_get_id (app)) == 0) {
+                       state = gs_app_get_state (tmp);
+                       break;
+               }
+       }
+       return state;
+}
+
+/**
+ * gs_plugin_loader_get_pending:
+ **/
+GPtrArray *
+gs_plugin_loader_get_pending (GsPluginLoader *plugin_loader)
 {
-       return gs_plugin_loader_run_action (plugin_loader,
-                                           app,
-                                           "gs_plugin_app_set_rating",
-                                           cancellable,
-                                           error);
+       return g_ptr_array_ref (plugin_loader->priv->pending_apps);
 }
 
 /**
diff --git a/src/gs-plugin-loader.h b/src/gs-plugin-loader.h
index fa72f61..fd26ce8 100644
--- a/src/gs-plugin-loader.h
+++ b/src/gs-plugin-loader.h
@@ -61,6 +61,13 @@ typedef enum
        GS_PLUGIN_LOADER_ERROR_LAST
 } GsPluginLoaderError;
 
+typedef enum {
+       GS_PLUGIN_LOADER_ACTION_INSTALL,
+       GS_PLUGIN_LOADER_ACTION_REMOVE,
+       GS_PLUGIN_LOADER_ACTION_SET_RATING,
+       GS_PLUGIN_LOADER_ACTION_LAST
+} GsPluginLoaderAction;
+
 typedef void    (*GsPluginLoaderFinishedFunc)          (GsPluginLoader *plugin_loader,
                                                         GsApp          *app,
                                                         gpointer        user_data);
@@ -144,22 +151,14 @@ void               gs_plugin_loader_app_refine_async      (GsPluginLoader 
*plugin_loader,
 gboolean        gs_plugin_loader_app_refine_finish     (GsPluginLoader *plugin_loader,
                                                         GAsyncResult   *res,
                                                         GError         **error);
-void            gs_plugin_loader_app_install           (GsPluginLoader *plugin_loader,
-                                                        GsApp          *app,
-                                                        GsPluginRefineFlags flags,
-                                                        GCancellable   *cancellable,
-                                                        GsPluginLoaderFinishedFunc func,
-                                                        gpointer        user_data);
-void            gs_plugin_loader_app_remove            (GsPluginLoader *plugin_loader,
+void            gs_plugin_loader_app_action_async      (GsPluginLoader *plugin_loader,
                                                         GsApp          *app,
-                                                        GsPluginRefineFlags flags,
+                                                        GsPluginLoaderAction a,
                                                         GCancellable   *cancellable,
-                                                        GsPluginLoaderFinishedFunc func,
+                                                        GAsyncReadyCallback callback,
                                                         gpointer        user_data);
-gboolean        gs_plugin_loader_app_set_rating        (GsPluginLoader *plugin_loader,
-                                                        GsApp          *app,
-                                                        GsPluginRefineFlags flags,
-                                                        GCancellable   *cancellable,
+gboolean        gs_plugin_loader_app_action_finish     (GsPluginLoader *plugin_loader,
+                                                        GAsyncResult   *res,
                                                         GError         **error);
 GsAppState      gs_plugin_loader_get_state_for_app     (GsPluginLoader *plugin_loader,
                                                         GsApp          *app);
diff --git a/src/gs-self-test.c b/src/gs-self-test.c
index e982e8d..00bfbdf 100644
--- a/src/gs-self-test.c
+++ b/src/gs-self-test.c
@@ -269,11 +269,11 @@ gs_plugin_loader_func (void)
        /* create a dummy value */
        app = gs_app_new ("self-test");
        gs_app_set_rating (app, 35);
-       ret = gs_plugin_loader_app_set_rating (loader,
-                                              app,
-                                              GS_PLUGIN_REFINE_FLAGS_DEFAULT,
-                                              NULL,
-                                              &error);
+       ret = gs_plugin_loader_app_action (loader,
+                                          app,
+                                          GS_PLUGIN_LOADER_ACTION_SET_RATING,
+                                          NULL,
+                                          &error);
        g_assert_no_error (error);
        g_assert (ret);
 
diff --git a/src/gs-shell-details.c b/src/gs-shell-details.c
index 44712f7..6e94ab2 100644
--- a/src/gs-shell-details.c
+++ b/src/gs-shell-details.c
@@ -556,21 +556,57 @@ gs_shell_details_get_app (GsShellDetails *shell_details)
        return shell_details->priv->app;
 }
 
+/**
+ * gs_shell_details_app_installed_cb:
+ **/
 static void
-gs_shell_details_installed_func (GsPluginLoader *plugin_loader, GsApp *app, gpointer user_data)
+gs_shell_details_app_installed_cb (GObject *source,
+                                  GAsyncResult *res,
+                                  gpointer user_data)
 {
+       GError *error = NULL;
+       GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source);
        GsShellDetails *shell_details = GS_SHELL_DETAILS (user_data);
-       gs_shell_details_refresh (shell_details);
+       GsShellDetailsPrivate *priv = shell_details->priv;
+       gboolean ret;
 
-       if (app) {
-               gs_app_notify_installed (app);
+       ret = gs_plugin_loader_app_action_finish (plugin_loader,
+                                                 res,
+                                                 &error);
+       if (!ret) {
+               g_warning ("failed to install %s: %s",
+                          gs_app_get_id (priv->app),
+                          error->message);
+               g_error_free (error);
+               return;
        }
+       gs_app_notify_installed (priv->app);
 }
 
+/**
+ * gs_shell_details_app_removed_cb:
+ **/
 static void
-gs_shell_details_removed_func (GsPluginLoader *plugin_loader, GsApp *app, gpointer user_data)
+gs_shell_details_app_removed_cb (GObject *source,
+                                GAsyncResult *res,
+                                gpointer user_data)
 {
+       GError *error = NULL;
+       GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source);
        GsShellDetails *shell_details = GS_SHELL_DETAILS (user_data);
+       GsShellDetailsPrivate *priv = shell_details->priv;
+       gboolean ret;
+
+       ret = gs_plugin_loader_app_action_finish (plugin_loader,
+                                                 res,
+                                                 &error);
+       if (!ret) {
+               g_warning ("failed to remove %s: %s",
+                          gs_app_get_id (priv->app),
+                          error->message);
+               g_error_free (error);
+               return;
+       }
        gs_shell_details_refresh (shell_details);
 }
 
@@ -610,12 +646,12 @@ gs_shell_details_app_remove_button_cb (GtkWidget *widget, GsShellDetails *shell_
        response = gtk_dialog_run (GTK_DIALOG (dialog));
        if (response == GTK_RESPONSE_OK) {
                g_debug ("remove %s", gs_app_get_id (priv->app));
-               gs_plugin_loader_app_remove (priv->plugin_loader,
-                                            priv->app,
-                                            GS_PLUGIN_REFINE_FLAGS_DEFAULT,
-                                            priv->cancellable,
-                                            gs_shell_details_removed_func,
-                                            shell_details);
+               gs_plugin_loader_app_action_async (priv->plugin_loader,
+                                                  priv->app,
+                                                  GS_PLUGIN_LOADER_ACTION_REMOVE,
+                                                  priv->cancellable,
+                                                  gs_shell_details_app_removed_cb,
+                                                  shell_details);
        }
        g_string_free (markup, TRUE);
        gtk_widget_destroy (dialog);
@@ -628,12 +664,12 @@ static void
 gs_shell_details_app_install_button_cb (GtkWidget *widget, GsShellDetails *shell_details)
 {
        GsShellDetailsPrivate *priv = shell_details->priv;
-       gs_plugin_loader_app_install (priv->plugin_loader,
-                                     priv->app,
-                                     GS_PLUGIN_REFINE_FLAGS_DEFAULT,
-                                     priv->cancellable,
-                                     gs_shell_details_installed_func,
-                                     shell_details);
+       gs_plugin_loader_app_action_async (priv->plugin_loader,
+                                          priv->app,
+                                          GS_PLUGIN_LOADER_ACTION_INSTALL,
+                                          priv->cancellable,
+                                          gs_shell_details_app_installed_cb,
+                                          shell_details);
 }
 
 /**
diff --git a/src/gs-shell-installed.c b/src/gs-shell-installed.c
index 6ca1df2..a6aa573 100644
--- a/src/gs-shell-installed.c
+++ b/src/gs-shell-installed.c
@@ -108,19 +108,35 @@ gs_shell_installed_remove_row (GtkListBox *list_box, GtkWidget *child)
 }
 
 /**
- * gs_shell_installed_finished_func:
+ * gs_shell_installed_app_removed_cb:
  **/
 static void
-gs_shell_installed_finished_func (GsPluginLoader *plugin_loader, GsApp *app, gpointer user_data)
+gs_shell_installed_app_removed_cb (GObject *source,
+                                  GAsyncResult *res,
+                                  gpointer user_data)
 {
+       GError *error = NULL;
+       GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source);
        GsShellInstalledHelper *helper = (GsShellInstalledHelper *) user_data;
        GsShellInstalledPrivate *priv = helper->shell_installed->priv;
-
-       /* remove from the list */
-       if (app != NULL) {
+       GsApp *app;
+       gboolean ret;
+
+       ret = gs_plugin_loader_app_action_finish (plugin_loader,
+                                                 res,
+                                                 &error);
+       if (!ret) {
+               app = gs_app_widget_get_app (helper->app_widget);
+               g_warning ("failed to remove %s: %s",
+                          gs_app_get_id (app),
+                          error->message);
+               g_error_free (error);
+       } else {
+               /* remove from the list */
                gs_shell_installed_remove_row (GTK_LIST_BOX (priv->list_box_installed),
                                               GTK_WIDGET (helper->app_widget));
        }
+
        g_object_unref (helper->app_widget);
        g_object_unref (helper->shell_installed);
        g_free (helper);
@@ -169,12 +185,12 @@ gs_shell_installed_app_remove_cb (GsAppWidget *app_widget,
                helper = g_new0 (GsShellInstalledHelper, 1);
                helper->shell_installed = g_object_ref (shell_installed);
                helper->app_widget = g_object_ref (app_widget);
-               gs_plugin_loader_app_remove (priv->plugin_loader,
-                                            app,
-                                            GS_PLUGIN_REFINE_FLAGS_DEFAULT,
-                                            priv->cancellable,
-                                            gs_shell_installed_finished_func,
-                                            helper);
+               gs_plugin_loader_app_action_async (priv->plugin_loader,
+                                                  app,
+                                                  GS_PLUGIN_LOADER_ACTION_REMOVE,
+                                                  priv->cancellable,
+                                                  gs_shell_installed_app_removed_cb,
+                                                  helper);
        }
        g_string_free (markup, TRUE);
        gtk_widget_destroy (dialog);
diff --git a/src/gs-shell-search.c b/src/gs-shell-search.c
index 66d0daa..50c10f7 100644
--- a/src/gs-shell-search.c
+++ b/src/gs-shell-search.c
@@ -62,20 +62,57 @@ gs_shell_search_app_widget_activated_cb (GtkListBox *list_box,
        gs_shell_show_app (shell_search->priv->shell, app);
 }
 
+typedef struct {
+       GsApp                   *app;
+       GsShellSearch           *shell_search;
+} GsShellSearchHelper;
+
 static void
-gs_shell_search_installed_func (GsPluginLoader *plugin_loader, GsApp *app, gpointer user_data)
+gs_shell_search_app_installed_cb (GObject *source,
+                                 GAsyncResult *res,
+                                 gpointer user_data)
 {
-       if (app) {
-               gs_app_notify_installed (app);
+       GError *error = NULL;
+       GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source);
+       GsShellSearchHelper *helper = (GsShellSearchHelper *) user_data;
+       gboolean ret;
+
+       ret = gs_plugin_loader_app_action_finish (plugin_loader,
+                                                 res,
+                                                 &error);
+       if (!ret) {
+               g_warning ("failed to install %s: %s",
+                          gs_app_get_id (helper->app),
+                          error->message);
+               g_error_free (error);
+       } else {
+               gs_app_notify_installed (helper->app);
        }
+       g_object_unref (helper->app);
+       g_object_unref (helper->shell_search);
+       g_free (helper);
 }
 
 /**
  * gs_shell_search_finished_func:
  **/
 static void
-gs_shell_search_removed_func (GsPluginLoader *plugin_loader, GsApp *app, gpointer user_data)
+gs_shell_search_app_removed_cb (GObject *source,
+                               GAsyncResult *res,
+                               gpointer user_data)
 {
+       GError *error = NULL;
+       GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source);
+       gboolean ret;
+
+       ret = gs_plugin_loader_app_action_finish (plugin_loader,
+                                                 res,
+                                                 &error);
+       if (!ret) {
+               g_warning ("failed to remove: %s",
+                          error->message);
+               g_error_free (error);
+       }
 }
 
 /**
@@ -114,12 +151,12 @@ gs_shell_search_app_remove (GsShellSearch *shell_search, GsApp *app)
        response = gtk_dialog_run (GTK_DIALOG (dialog));
        if (response == GTK_RESPONSE_OK) {
                g_debug ("remove %s", gs_app_get_id (app));
-               gs_plugin_loader_app_remove (priv->plugin_loader,
-                                            app,
-                                            GS_PLUGIN_REFINE_FLAGS_DEFAULT,
-                                            priv->cancellable,
-                                            gs_shell_search_removed_func,
-                                            shell_search);
+               gs_plugin_loader_app_action_async (priv->plugin_loader,
+                                                  app,
+                                                  GS_PLUGIN_LOADER_ACTION_REMOVE,
+                                                  priv->cancellable,
+                                                  gs_shell_search_app_removed_cb,
+                                                  shell_search);
        }
        g_string_free (markup, TRUE);
        gtk_widget_destroy (dialog);
@@ -132,12 +169,16 @@ static void
 gs_shell_search_app_install (GsShellSearch *shell_search, GsApp *app)
 {
        GsShellSearchPrivate *priv = shell_search->priv;
-       gs_plugin_loader_app_install (priv->plugin_loader,
-                                     app,
-                                     GS_PLUGIN_REFINE_FLAGS_DEFAULT,
-                                     priv->cancellable,
-                                     gs_shell_search_installed_func,
-                                     shell_search);
+       GsShellSearchHelper *helper;
+       helper = g_new0 (GsShellSearchHelper, 1);
+       helper->app = g_object_ref (app);
+       helper->shell_search = g_object_ref (shell_search);
+       gs_plugin_loader_app_action_async (priv->plugin_loader,
+                                          app,
+                                          GS_PLUGIN_LOADER_ACTION_INSTALL,
+                                          priv->cancellable,
+                                          gs_shell_search_app_installed_cb,
+                                          helper);
 }
 
 /**


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