[gnome-software] Allow plugins to emit status changed events
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] Allow plugins to emit status changed events
- Date: Fri, 8 Mar 2013 09:06:38 +0000 (UTC)
commit 7685ba52a8a18902470b5bdc0325252c0309379d
Author: Richard Hughes <richard hughsie com>
Date: Thu Mar 7 22:01:33 2013 +0000
Allow plugins to emit status changed events
src/gs-main.c | 47 +++++++++++++++++++++++++++
src/gs-plugin-loader.c | 61 ++++++++++++++++++++++++++++++++++++
src/gs-plugin-loader.h | 4 ++
src/gs-plugin.h | 22 +++++++++++--
src/gs-self-test.c | 15 +++++++++
src/plugins/gs-plugin-dummy.c | 6 +++
src/plugins/gs-plugin-packagekit.c | 6 +++
7 files changed, 158 insertions(+), 3 deletions(-)
---
diff --git a/src/gs-main.c b/src/gs-main.c
index 573acf2..22550b3 100644
--- a/src/gs-main.c
+++ b/src/gs-main.c
@@ -233,6 +233,49 @@ gs_main_progress_cb (PkProgress *progress,
}
}
+/**
+ * gs_main_progress_cb:
+ **/
+static void
+gs_main_plugin_loader_status_changed_cb (GsPluginLoader *plugin_loader,
+ GsApp *app,
+ GsPluginStatus status,
+ GsMainPrivate *priv)
+{
+ GtkWidget *widget;
+ const gchar *status_text = NULL;
+
+ /* translate */
+ if (status == GS_PLUGIN_STATUS_WAITING) {
+ /* TRANSLATORS: we're waiting for something to happen */
+ status_text = _("Waiting...");
+ }
+
+ /* update the label */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "label_waiting"));
+ if (status_text != NULL) {
+ gtk_label_set_markup (GTK_LABEL (widget), status_text);
+ gtk_widget_show (widget);
+ } else {
+ gtk_widget_hide (widget);
+ }
+
+ /* show the waiting panel if the delay is significant */
+ if (status == GS_PLUGIN_STATUS_FINISHED) {
+ gs_main_set_overview_mode_ui (priv, priv->mode);
+ if (priv->waiting_tab_id > 0) {
+ g_source_remove (priv->waiting_tab_id);
+ priv->waiting_tab_id = 0;
+ }
+ } else {
+ if (priv->waiting_tab_id == 0) {
+ priv->waiting_tab_id = g_timeout_add (50,
+ gs_main_show_waiting_tab_cb,
+ priv);
+ }
+ }
+}
+
typedef struct {
GsAppWidget *app_widget;
GsMainPrivate *priv;
@@ -1292,6 +1335,10 @@ gs_main_startup_cb (GApplication *application, GsMainPrivate *priv)
g_signal_connect (GTK_EDITABLE (widget), "changed",
G_CALLBACK (gs_main_filter_text_changed_cb), priv);
+ /* show the status on a different page */
+ g_signal_connect (priv->plugin_loader, "status-changed",
+ G_CALLBACK (gs_main_plugin_loader_status_changed_cb), priv);
+
/* show main UI */
gtk_widget_show (main_window);
gs_main_set_overview_mode (priv, GS_MAIN_MODE_INSTALLED);
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index 46b1d52..de0ba40 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -32,10 +32,18 @@ struct GsPluginLoaderPrivate
{
GPtrArray *plugins;
gchar *location;
+ GsPluginStatus status_last;
};
G_DEFINE_TYPE (GsPluginLoader, gs_plugin_loader, G_TYPE_OBJECT)
+enum {
+ SIGNAL_STATUS_CHANGED,
+ SIGNAL_LAST
+};
+
+static guint signals [SIGNAL_LAST] = { 0 };
+
/**
* gs_plugin_loader_error_quark:
* Return value: Our personal error quark.
@@ -79,6 +87,7 @@ gs_plugin_loader_run_refine (GsPluginLoader *plugin_loader,
ret = plugin_func (plugin, list, error);
if (!ret)
goto out;
+ gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
g_debug ("%s(%s) took %.0fms",
plugin->name,
function_name,
@@ -118,6 +127,7 @@ gs_plugin_loader_run_results (GsPluginLoader *plugin_loader,
ret = plugin_func (plugin, &list, error);
if (!ret)
goto out;
+ gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
g_debug ("%s(%s) took %.0fms",
plugin->name,
function_name,
@@ -316,6 +326,7 @@ gs_plugin_loader_search (GsPluginLoader *plugin_loader, const gchar *value, GErr
ret = plugin_func (plugin, value, &list, error);
if (!ret)
goto out;
+ gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
g_debug ("%s(%s) took %.0fms",
plugin->name,
function_name,
@@ -383,6 +394,7 @@ gs_plugin_loader_run_action (GsPluginLoader *plugin_loader,
goto out;
}
}
+ gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
g_debug ("%s(%s) took %.0fms",
plugin->name,
function_name,
@@ -456,6 +468,7 @@ gs_plugin_loader_run (GsPluginLoader *plugin_loader, const gchar *function_name)
(gpointer *) &plugin_func);
if (!ret)
continue;
+ gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
g_debug ("run %s on %s", function_name,
g_module_name (plugin->module));
plugin_func (plugin);
@@ -486,6 +499,44 @@ gs_plugin_loader_set_enabled (GsPluginLoader *plugin_loader,
}
/**
+ * gs_plugin_loader_status_to_string:
+ */
+static const gchar *
+gs_plugin_loader_status_to_string (GsPluginStatus status)
+{
+ if (status == GS_PLUGIN_STATUS_WAITING)
+ return "waiting";
+ if (status == GS_PLUGIN_STATUS_FINISHED)
+ return "finished";
+ return "unknown";
+}
+
+/**
+ * gs_plugin_loader_status_update_cb:
+ */
+static void
+gs_plugin_loader_status_update_cb (GsPlugin *plugin,
+ GsApp *app,
+ GsPluginStatus status,
+ gpointer user_data)
+{
+ GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (user_data);
+
+ /* same as last time */
+ if (app == NULL && status == plugin_loader->priv->status_last)
+ return;
+
+ /* new, or an app, so emit */
+ g_debug ("emitting %s(%s)",
+ gs_plugin_loader_status_to_string (status),
+ app != NULL ? gs_app_get_id (app) : "<general>");
+ plugin_loader->priv->status_last = status;
+ g_signal_emit (plugin_loader,
+ signals[SIGNAL_STATUS_CHANGED],
+ 0, app, status);
+}
+
+/**
* gs_plugin_loader_open_plugin:
*/
static GsPlugin *
@@ -533,6 +584,8 @@ gs_plugin_loader_open_plugin (GsPluginLoader *plugin_loader,
plugin->priority = plugin_prio (plugin);
plugin->name = g_strdup (plugin_name ());
plugin->timer = g_timer_new ();
+ plugin->status_update_fn = gs_plugin_loader_status_update_cb;
+ plugin->status_update_user_data = plugin_loader;
g_debug ("opened plugin %s: %s", filename, plugin->name);
/* add to array */
@@ -652,6 +705,13 @@ gs_plugin_loader_class_init (GsPluginLoaderClass *klass)
object_class->finalize = gs_plugin_loader_finalize;
+ signals [SIGNAL_STATUS_CHANGED] =
+ g_signal_new ("status-changed",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsPluginLoaderClass, status_changed),
+ NULL, NULL, g_cclosure_marshal_generic,
+ G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT);
+
g_type_class_add_private (klass, sizeof (GsPluginLoaderPrivate));
}
@@ -663,6 +723,7 @@ gs_plugin_loader_init (GsPluginLoader *plugin_loader)
{
plugin_loader->priv = GS_PLUGIN_LOADER_GET_PRIVATE (plugin_loader);
plugin_loader->priv->plugins = g_ptr_array_new_with_free_func ((GDestroyNotify)
gs_plugin_loader_plugin_free);
+ plugin_loader->priv->status_last = GS_PLUGIN_STATUS_LAST;
}
/**
diff --git a/src/gs-plugin-loader.h b/src/gs-plugin-loader.h
index 0e52bf2..c0d7d74 100644
--- a/src/gs-plugin-loader.h
+++ b/src/gs-plugin-loader.h
@@ -25,6 +25,7 @@
#include <glib-object.h>
#include "gs-app.h"
+#include "gs-plugin.h"
G_BEGIN_DECLS
@@ -47,6 +48,9 @@ typedef struct
typedef struct
{
GObjectClass parent_class;
+ void (*status_changed) (GsPluginLoader *plugin_loader,
+ GsApp *app,
+ GsPluginStatus status);
} GsPluginLoaderClass;
typedef enum
diff --git a/src/gs-plugin.h b/src/gs-plugin.h
index d2d1e5a..edbcc6e 100644
--- a/src/gs-plugin.h
+++ b/src/gs-plugin.h
@@ -31,9 +31,22 @@
G_BEGIN_DECLS
-typedef struct GsPluginPrivate GsPluginPrivate;
+typedef struct GsPluginPrivate GsPluginPrivate;
+typedef struct GsPlugin GsPlugin;
-typedef struct {
+typedef enum {
+ GS_PLUGIN_STATUS_UNKNOWN,
+ GS_PLUGIN_STATUS_WAITING,
+ GS_PLUGIN_STATUS_FINISHED,
+ GS_PLUGIN_STATUS_LAST
+} GsPluginStatus;
+
+typedef void (*GsPluginStatusUpdate) (GsPlugin *plugin,
+ GsApp *app,
+ GsPluginStatus status,
+ gpointer user_data);
+
+struct GsPlugin {
GModule *module;
gdouble priority; /* largest number gets run first */
gboolean enabled;
@@ -42,7 +55,9 @@ typedef struct {
GCancellable *cancellable;
guint pixbuf_size;
GTimer *timer;
-} GsPlugin;
+ GsPluginStatusUpdate status_update_fn;
+ gpointer status_update_user_data;
+};
typedef enum {
GS_PLUGIN_ERROR_FAILED,
@@ -52,6 +67,7 @@ typedef enum {
/* helpers */
#define gs_plugin_add_app(l,a) (*l=g_list_prepend(*l,a))
+#define gs_plugin_status_update(p,a,s)
(p->status_update_fn(p,a,s,p->status_update_user_data))
#define GS_PLUGIN_ERROR 1
#define GS_PLUGIN_GET_PRIVATE(x) g_new0 (x,1)
diff --git a/src/gs-self-test.c b/src/gs-self-test.c
index 5c68215..96958b0 100644
--- a/src/gs-self-test.c
+++ b/src/gs-self-test.c
@@ -41,6 +41,17 @@ gs_app_func (void)
g_object_unref (app);
}
+static guint _status_changed_cnt = 0;
+
+static void
+gs_plugin_loader_status_changed_cb (GsPluginLoader *plugin_loader,
+ GsApp *app,
+ GsPluginStatus status,
+ gpointer user_data)
+{
+ _status_changed_cnt++;
+}
+
static void
gs_plugin_loader_func (void)
{
@@ -53,6 +64,8 @@ gs_plugin_loader_func (void)
loader = gs_plugin_loader_new ();
g_assert (GS_IS_PLUGIN_LOADER (loader));
+ g_signal_connect (loader, "status-changed",
+ G_CALLBACK (gs_plugin_loader_status_changed_cb), NULL);
/* load the plugins */
gs_plugin_loader_set_location (loader, "./plugins/.libs");
@@ -91,9 +104,11 @@ gs_plugin_loader_func (void)
g_list_free_full (list, (GDestroyNotify) g_object_unref);
/* get updates */
+ g_assert_cmpint (_status_changed_cnt, ==, 0);
list = gs_plugin_loader_get_updates (loader, &error);
g_assert_no_error (error);
g_assert (list != NULL);
+ g_assert_cmpint (_status_changed_cnt, ==, 1);
g_assert_cmpint (g_list_length (list), ==, 2);
app = g_list_nth_data (list, 0);
g_assert_cmpstr (gs_app_get_id (app), ==,
"os-update:gnome-boxes-libs;0.0.1;i386;updates-testing,libvirt-glib-devel;0.0.1;noarch;fedora");
diff --git a/src/plugins/gs-plugin-dummy.c b/src/plugins/gs-plugin-dummy.c
index 2f3436a..fea821b 100644
--- a/src/plugins/gs-plugin-dummy.c
+++ b/src/plugins/gs-plugin-dummy.c
@@ -82,6 +82,12 @@ gs_plugin_add_updates (GsPlugin *plugin, GList **list, GError **error)
{
GsApp *app;
+ /* update UI as this might take some time */
+ gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_WAITING);
+
+ /* spin */
+ g_usleep (2 * G_USEC_PER_SEC);
+
/* add a normal application */
app = gs_app_new ("gnome-boxes");
gs_app_set_name (app, "Boxes");
diff --git a/src/plugins/gs-plugin-packagekit.c b/src/plugins/gs-plugin-packagekit.c
index b5f8068..70369a0 100644
--- a/src/plugins/gs-plugin-packagekit.c
+++ b/src/plugins/gs-plugin-packagekit.c
@@ -141,6 +141,9 @@ gs_plugin_add_installed (GsPlugin *plugin, GList **list, GError **error)
PkBitfield filter;
PkResults *results;
+ /* update UI as this might take some time */
+ gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_WAITING);
+
/* do sync call */
filter = pk_bitfield_from_enums (PK_FILTER_ENUM_INSTALLED,
PK_FILTER_ENUM_NEWEST,
@@ -175,6 +178,9 @@ gs_plugin_add_updates (GsPlugin *plugin, GList **list, GError **error)
PkBitfield filter;
PkResults *results;
+ /* update UI as this might take some time */
+ gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_WAITING);
+
/* do sync call */
filter = pk_bitfield_from_enums (PK_FILTER_ENUM_ARCH, -1);
results = pk_client_get_updates (PK_CLIENT(plugin->priv->task),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]