aboutsummaryrefslogtreecommitdiffstats
path: root/e-util/e-activity.c
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2010-09-19 03:57:27 +0800
committerMatthew Barnes <mbarnes@redhat.com>2010-09-19 04:40:19 +0800
commita98c07a569292fa66f91d3fa4bd32f32adff1880 (patch)
tree98caa43594f61662289fd696b409978946e92255 /e-util/e-activity.c
parentb145c0a2522c5c9942c0827bf03baefea68f5d99 (diff)
downloadgsoc2013-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.c170
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