[gnome-software/wip/jrocha/limit-parallel-ops: 2/4] Add a pending-action to GsApp



commit 2b938c87294366966cd72b460616e04032e06958
Author: Joaquim Rocha <jrocha endlessm com>
Date:   Thu Jan 18 16:56:00 2018 +0100

    Add a pending-action to GsApp
    
    Sometimes we cannot apply an action to a GsApp right away (e.g. because
    of not having an available worker thread for the action), so we should
    be able to set up an internal state in GsApp objects in order to reflect
    this.
    
    For that purpose, this patch introduces a gs_app_get/set_pending_action
    private method that can be used to track and eventually inform the user
    about this condition.

 lib/gs-app-private.h |  4 ++++
 lib/gs-app.c         | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 lib/gs-self-test.c   |  9 ++++++++
 3 files changed, 72 insertions(+), 1 deletion(-)
---
diff --git a/lib/gs-app-private.h b/lib/gs-app-private.h
index 7c98d56f..6e7c6e00 100644
--- a/lib/gs-app-private.h
+++ b/lib/gs-app-private.h
@@ -23,6 +23,7 @@
 #define __GS_APP_PRIVATE_H
 
 #include "gs-app.h"
+#include "gs-plugin-types.h"
 
 G_BEGIN_DECLS
 
@@ -34,6 +35,9 @@ void           gs_app_set_unique_id           (GsApp          *app,
 void            gs_app_remove_addon            (GsApp          *app,
                                                 GsApp          *addon);
 GCancellable   *gs_app_get_cancellable         (GsApp          *app);
+GsPluginAction  gs_app_get_pending_action      (GsApp          *app);
+void            gs_app_set_pending_action      (GsApp          *app,
+                                                GsPluginAction  action);
 
 G_END_DECLS
 
diff --git a/lib/gs-app.c b/lib/gs-app.c
index 3c7fbd17..dc6de9b7 100644
--- a/lib/gs-app.c
+++ b/lib/gs-app.c
@@ -126,6 +126,7 @@ typedef struct
        GdkPixbuf               *pixbuf;
        GsPrice                 *price;
        GCancellable            *cancellable;
+       GsPluginAction           pending_action;
 } GsAppPrivate;
 
 enum {
@@ -142,6 +143,7 @@ enum {
        PROP_CAN_CANCEL_INSTALLATION,
        PROP_INSTALL_DATE,
        PROP_QUIRK,
+       PROP_PENDING_ACTION,
        PROP_LAST
 };
 
@@ -1071,6 +1073,18 @@ gs_app_set_allow_cancel (GsApp *app, gboolean allow_cancel)
        gs_app_queue_notify (app, "allow-cancel");
 }
 
+static void
+gs_app_set_pending_action_internal (GsApp *app,
+                                   GsPluginAction action)
+{
+       GsAppPrivate *priv = gs_app_get_instance_private (app);
+       if (priv->pending_action == action)
+               return;
+
+       priv->pending_action = action;
+       gs_app_queue_notify (app, "pending-action");
+}
+
 /**
  * gs_app_set_state:
  * @app: a #GsApp
@@ -1104,8 +1118,12 @@ gs_app_set_state (GsApp *app, AsAppState state)
 
        locker = g_mutex_locker_new (&priv->mutex);
 
-       if (gs_app_set_state_internal (app, state))
+       if (gs_app_set_state_internal (app, state)) {
+               /* since the state changed, and the pending-action refers to
+                * actions that usually change the state, we reset it here */
+               gs_app_set_pending_action_internal (app, GS_PLUGIN_ACTION_UNKNOWN);
                gs_app_queue_notify (app, "state");
+       }
 }
 
 /**
@@ -3958,6 +3976,38 @@ gs_app_get_cancellable (GsApp *app)
        return priv->cancellable;
 }
 
+/**
+ * gs_app_get_pending_action:
+ * @app: a #GsApp
+ *
+ * Get the pending action for this #GsApp, or %NULL if no action is pending.
+ *
+ * Returns: the #GsAppAction of the @app.
+ **/
+GsPluginAction
+gs_app_get_pending_action (GsApp *app)
+{
+       GsAppPrivate *priv = gs_app_get_instance_private (app);
+       g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
+       return priv->pending_action;
+}
+
+/**
+ * gs_app_set_pending_action:
+ * @app: a #GsApp
+ * @action: a #GsPluginAction
+ *
+ * Set an action that is pending on this #GsApp.
+ **/
+void
+gs_app_set_pending_action (GsApp *app,
+                          GsPluginAction action)
+{
+       GsAppPrivate *priv = gs_app_get_instance_private (app);
+       g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->mutex);
+       gs_app_set_pending_action_internal (app, action);
+}
+
 static void
 gs_app_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
@@ -4240,6 +4290,14 @@ gs_app_class_init (GsAppClass *klass)
                                     0, G_MAXUINT64, 0,
                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
        g_object_class_install_property (object_class, PROP_QUIRK, pspec);
+
+       /**
+        * GsApp:pending-action:
+        */
+       pspec = g_param_spec_uint64 ("pending-action", NULL, NULL,
+                                    0, G_MAXUINT64, 0,
+                                    G_PARAM_READABLE | G_PARAM_PRIVATE);
+       g_object_class_install_property (object_class, PROP_PENDING_ACTION, pspec);
 }
 
 static void
diff --git a/lib/gs-self-test.c b/lib/gs-self-test.c
index 1ac0c474..4e7ae1da 100644
--- a/lib/gs-self-test.c
+++ b/lib/gs-self-test.c
@@ -587,6 +587,15 @@ gs_app_func (void)
        g_assert_cmpuint (gs_app_get_progress (app), ==, 42);
        gs_app_set_progress (app, 142);
        g_assert_cmpuint (gs_app_get_progress (app), ==, 100);
+
+       /* check pending action */
+       g_assert_cmpuint (gs_app_get_pending_action (app), ==, GS_PLUGIN_ACTION_UNKNOWN);
+       gs_app_set_state (app, AS_APP_STATE_UPDATABLE_LIVE);
+       gs_app_set_pending_action (app, GS_PLUGIN_ACTION_UPDATE);
+       g_assert_cmpuint (gs_app_get_pending_action (app), ==, GS_PLUGIN_ACTION_UPDATE);
+       gs_app_set_state (app, AS_APP_STATE_INSTALLING);
+       g_assert_cmpuint (gs_app_get_pending_action (app), ==, GS_PLUGIN_ACTION_UNKNOWN);
+       gs_app_set_state_recover (app);
 }
 
 static void


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