diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2010-09-19 03:57:27 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2010-09-19 04:40:19 +0800 |
commit | a98c07a569292fa66f91d3fa4bd32f32adff1880 (patch) | |
tree | 98caa43594f61662289fd696b409978946e92255 /e-util/e-activity.c | |
parent | b145c0a2522c5c9942c0827bf03baefea68f5d99 (diff) | |
download | gsoc2013-evolution-a98c07a569292fa66f91d3fa4bd32f32adff1880.tar.gz gsoc2013-evolution-a98c07a569292fa66f91d3fa4bd32f32adff1880.tar.zst gsoc2013-evolution-a98c07a569292fa66f91d3fa4bd32f32adff1880.zip |
Add a GCancellable to EActivity.
EActivity now uses a GCancellable to manage cancellations, instead of
having its own redundant cancellation API. API changes are as follows:
+ e_activity_get_cancellable()
+ e_activity_set_cancellable()
- e_activity_cancel()
- e_activity_is_cancelled()
- e_activity_get_allow_cancel()
- e_activity_set_allow_cancel()
EActivity's "cancelled" signal remains, but only as a repeater for
GCancellable::cancelled signals. It should not be emitted directly.
The presence of a GCancellable implies that cancellation is allowed.
EActivity does not create its own default GCancellable, it has to be
given one.
If a CamelOperation (cast as a GCancellable) is given, EActivity will
configure itself to listen for status updates from the CamelOperation
and propagate the information to its own "primary-text" and "percent"
properties.
These changes allowed me to start cleaning up some of the incredibly
convoluted logic in mail-mt.c -- in particular, mail_operation_status()
is completely gone now. mail-mt.c is still in a transitional state --
much more significant changes coming soon.
Diffstat (limited to 'e-util/e-activity.c')
-rw-r--r-- | e-util/e-activity.c | 170 |
1 files changed, 105 insertions, 65 deletions
diff --git a/e-util/e-activity.c b/e-util/e-activity.c index 631915db89..f90361d7f2 100644 --- a/e-util/e-activity.c +++ b/e-util/e-activity.c @@ -23,6 +23,7 @@ #include <stdarg.h> #include <glib/gi18n.h> +#include <camel/camel.h> #include "e-util/e-util.h" @@ -31,20 +32,20 @@ ((obj), E_TYPE_ACTIVITY, EActivityPrivate)) struct _EActivityPrivate { + GCancellable *cancellable; + gchar *icon_name; gchar *primary_text; gchar *secondary_text; gdouble percent; - guint allow_cancel : 1; - guint cancelled : 1; guint clickable : 1; guint completed : 1; }; enum { PROP_0, - PROP_ALLOW_CANCEL, + PROP_CANCELLABLE, PROP_CLICKABLE, PROP_ICON_NAME, PROP_PERCENT, @@ -67,6 +68,19 @@ G_DEFINE_TYPE ( e_activity, G_TYPE_OBJECT) +static void +activity_camel_status_cb (EActivity *activity, + const gchar *description, + gint percent) +{ + /* CamelOperation::status signals are always emitted from idle + * callbacks, so we don't have to screw around with locking. */ + + g_object_set ( + activity, "percent", (gdouble) percent, + "primary-text", description, NULL); +} + static gboolean activity_describe_accumulator (GSignalInvocationHint *ihint, GValue *return_accu, @@ -82,16 +96,24 @@ activity_describe_accumulator (GSignalInvocationHint *ihint, } static void +activity_emit_cancelled (EActivity *activity) +{ + /* This signal should only be emitted via our GCancellable, + * which is why we don't expose this function publicly. */ + g_signal_emit (activity, signals[CANCELLED], 0); +} + +static void activity_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { - case PROP_ALLOW_CANCEL: - e_activity_set_allow_cancel ( + case PROP_CANCELLABLE: + e_activity_set_cancellable ( E_ACTIVITY (object), - g_value_get_boolean (value)); + g_value_get_object (value)); return; case PROP_CLICKABLE: @@ -135,9 +157,9 @@ activity_get_property (GObject *object, GParamSpec *pspec) { switch (property_id) { - case PROP_ALLOW_CANCEL: - g_value_set_boolean ( - value, e_activity_get_allow_cancel ( + case PROP_CANCELLABLE: + g_value_set_object ( + value, e_activity_get_cancellable ( E_ACTIVITY (object))); return; @@ -176,6 +198,26 @@ activity_get_property (GObject *object, } static void +activity_dispose (GObject *object) +{ + EActivityPrivate *priv; + + priv = E_ACTIVITY_GET_PRIVATE (object); + + if (priv->cancellable != NULL) { + g_signal_handlers_disconnect_matched ( + priv->cancellable, + G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->cancellable); + priv->cancellable = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_activity_parent_class)->dispose (object); +} + +static void activity_finalize (GObject *object) { EActivityPrivate *priv; @@ -191,12 +233,6 @@ activity_finalize (GObject *object) } static void -activity_cancelled (EActivity *activity) -{ - activity->priv->cancelled = TRUE; -} - -static void activity_completed (EActivity *activity) { activity->priv->completed = TRUE; @@ -212,21 +248,22 @@ static gchar * activity_describe (EActivity *activity) { GString *string; + GCancellable *cancellable; const gchar *text; - gboolean cancelled; - gboolean completed; gdouble percent; string = g_string_sized_new (256); + cancellable = e_activity_get_cancellable (activity); text = e_activity_get_primary_text (activity); - cancelled = e_activity_is_cancelled (activity); - completed = e_activity_is_completed (activity); percent = e_activity_get_percent (activity); - if (cancelled) { + if (text == NULL) + return NULL; + + if (g_cancellable_is_cancelled (cancellable)) { /* Translators: This is a cancelled activity. */ g_string_printf (string, _("%s (cancelled)"), text); - } else if (completed) { + } else if (e_activity_is_completed (activity)) { /* Translators: This is a completed activity. */ g_string_printf (string, _("%s (completed)"), text); } else if (percent < 0.0) { @@ -254,21 +291,21 @@ e_activity_class_init (EActivityClass *class) object_class = G_OBJECT_CLASS (class); object_class->set_property = activity_set_property; object_class->get_property = activity_get_property; + object_class->dispose = activity_dispose; object_class->finalize = activity_finalize; - class->cancelled = activity_cancelled; class->completed = activity_completed; class->clicked = activity_clicked; class->describe = activity_describe; g_object_class_install_property ( object_class, - PROP_ALLOW_CANCEL, - g_param_spec_boolean ( - "allow-cancel", + PROP_CANCELLABLE, + g_param_spec_object ( + "cancellable", NULL, NULL, - FALSE, + G_TYPE_CANCELLABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); @@ -373,11 +410,9 @@ e_activity_init (EActivity *activity) } EActivity * -e_activity_new (const gchar *primary_text) +e_activity_new (void) { - return g_object_new ( - E_TYPE_ACTIVITY, - "primary-text", primary_text, NULL); + return g_object_new (E_TYPE_ACTIVITY, NULL); } EActivity * @@ -387,9 +422,11 @@ e_activity_newv (const gchar *format, ...) gchar *primary_text; va_list args; + activity = e_activity_new (); + va_start (args, format); primary_text = g_strdup_vprintf (format, args); - activity = e_activity_new (primary_text); + e_activity_set_primary_text (activity, primary_text); g_free (primary_text); va_end (args); @@ -397,28 +434,15 @@ e_activity_newv (const gchar *format, ...) } void -e_activity_cancel (EActivity *activity) -{ - g_return_if_fail (E_IS_ACTIVITY (activity)); - - if (!activity->priv->allow_cancel) - return; - - if (activity->priv->cancelled) - return; - - if (activity->priv->completed) - return; - - g_signal_emit (activity, signals[CANCELLED], 0); -} - -void e_activity_complete (EActivity *activity) { + GCancellable *cancellable; + g_return_if_fail (E_IS_ACTIVITY (activity)); - if (activity->priv->cancelled) + cancellable = e_activity_get_cancellable (activity); + + if (g_cancellable_is_cancelled (cancellable)) return; if (activity->priv->completed) @@ -449,14 +473,6 @@ e_activity_describe (EActivity *activity) } gboolean -e_activity_is_cancelled (EActivity *activity) -{ - g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE); - - return activity->priv->cancelled; -} - -gboolean e_activity_is_completed (EActivity *activity) { g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE); @@ -464,23 +480,47 @@ e_activity_is_completed (EActivity *activity) return activity->priv->completed; } -gboolean -e_activity_get_allow_cancel (EActivity *activity) +GCancellable * +e_activity_get_cancellable (EActivity *activity) { - g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE); + g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL); - return activity->priv->allow_cancel; + return activity->priv->cancellable; } void -e_activity_set_allow_cancel (EActivity *activity, - gboolean allow_cancel) +e_activity_set_cancellable (EActivity *activity, + GCancellable *cancellable) { g_return_if_fail (E_IS_ACTIVITY (activity)); - activity->priv->allow_cancel = allow_cancel; + if (cancellable != NULL) { + g_return_if_fail (G_IS_CANCELLABLE (cancellable)); + g_object_ref (cancellable); + } + + if (activity->priv->cancellable != NULL) { + g_signal_handlers_disconnect_matched ( + activity->priv->cancellable, + G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, activity); + g_object_unref (activity->priv->cancellable); + } + + activity->priv->cancellable = cancellable; + + if (G_IS_CANCELLABLE (cancellable)) + g_signal_connect_swapped ( + cancellable, "cancelled", + G_CALLBACK (activity_emit_cancelled), activity); + + /* If this is a CamelOperation, listen for status updates + * from it and propagate them to our own status properties. */ + if (CAMEL_IS_OPERATION (cancellable)) + g_signal_connect_swapped ( + cancellable, "status", + G_CALLBACK (activity_camel_status_cb), activity); - g_object_notify (G_OBJECT (activity), "allow-cancel"); + g_object_notify (G_OBJECT (activity), "cancellable"); } gboolean |