[evolution] Add a GCancellable to EActivity.



commit a98c07a569292fa66f91d3fa4bd32f32adff1880
Author: Matthew Barnes <mbarnes redhat com>
Date:   Sat Sep 18 15:57:27 2010 -0400

    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.

 addressbook/gui/widgets/e-addressbook-view.c |    3 +-
 doc/reference/shell/eshell-sections.txt      |    6 +-
 doc/reference/shell/tmpl/e-activity.sgml     |   25 +--
 doc/reference/shell/tmpl/eshell-unused.sgml  |   31 +++
 e-util/e-activity.c                          |  170 +++++++++------
 e-util/e-activity.h                          |   10 +-
 e-util/e-io-activity.c                       |   82 +-------
 e-util/e-io-activity.h                       |    3 -
 e-util/e-timeout-activity.c                  |    2 +-
 mail/mail-mt.c                               |  296 +++++++-------------------
 modules/calendar/e-cal-shell-view-memopad.c  |    3 +-
 modules/calendar/e-cal-shell-view-private.c  |    3 +-
 modules/calendar/e-cal-shell-view-taskpad.c  |    3 +-
 modules/calendar/e-memo-shell-view-private.c |    3 +-
 modules/calendar/e-task-shell-view-private.c |    3 +-
 shell/e-shell-taskbar.c                      |   21 +-
 shell/e-shell.c                              |   21 ++-
 widgets/misc/e-activity-proxy.c              |   27 ++-
 18 files changed, 288 insertions(+), 424 deletions(-)
---
diff --git a/addressbook/gui/widgets/e-addressbook-view.c b/addressbook/gui/widgets/e-addressbook-view.c
index bb6e58f..957d85e 100644
--- a/addressbook/gui/widgets/e-addressbook-view.c
+++ b/addressbook/gui/widgets/e-addressbook-view.c
@@ -1082,8 +1082,9 @@ status_message (EAddressbookView *view,
 		}
 
 	} else if (activity == NULL) {
-		activity = e_activity_new (status);
+		activity = e_activity_new ();
 		view->priv->activity = activity;
+		e_activity_set_primary_text (activity, status);
 		e_shell_backend_add_activity (shell_backend, activity);
 
 	} else
diff --git a/doc/reference/shell/eshell-sections.txt b/doc/reference/shell/eshell-sections.txt
index 05ac158..d8b8a5c 100644
--- a/doc/reference/shell/eshell-sections.txt
+++ b/doc/reference/shell/eshell-sections.txt
@@ -461,14 +461,12 @@ EActionComboBoxPrivate
 EActivity
 e_activity_new
 e_activity_newv
-e_activity_cancel
 e_activity_complete
 e_activity_clicked
 e_activity_describe
-e_activity_is_cancelled
 e_activity_is_completed
-e_activity_get_allow_cancel
-e_activity_set_allow_cancel
+e_activity_get_cancellable
+e_activity_set_cancellable
 e_activity_get_clickable
 e_activity_set_clickable
 e_activity_get_icon_name
diff --git a/doc/reference/shell/tmpl/e-activity.sgml b/doc/reference/shell/tmpl/e-activity.sgml
index d56bd07..871758f 100644
--- a/doc/reference/shell/tmpl/e-activity.sgml
+++ b/doc/reference/shell/tmpl/e-activity.sgml
@@ -31,7 +31,7 @@ e-activity
 
 </para>
 
- primary_text: 
+ void: 
 @Returns: 
 
 
@@ -45,14 +45,6 @@ e-activity
 @Returns: 
 
 
-<!-- ##### FUNCTION e_activity_cancel ##### -->
-<para>
-
-</para>
-
- activity: 
-
-
 <!-- ##### FUNCTION e_activity_complete ##### -->
 <para>
 
@@ -78,15 +70,6 @@ e-activity
 @Returns: 
 
 
-<!-- ##### FUNCTION e_activity_is_cancelled ##### -->
-<para>
-
-</para>
-
- activity: 
- Returns: 
-
-
 <!-- ##### FUNCTION e_activity_is_completed ##### -->
 <para>
 
@@ -96,7 +79,7 @@ e-activity
 @Returns: 
 
 
-<!-- ##### FUNCTION e_activity_get_allow_cancel ##### -->
+<!-- ##### FUNCTION e_activity_get_cancellable ##### -->
 <para>
 
 </para>
@@ -105,13 +88,13 @@ e-activity
 @Returns: 
 
 
-<!-- ##### FUNCTION e_activity_set_allow_cancel ##### -->
+<!-- ##### FUNCTION e_activity_set_cancellable ##### -->
 <para>
 
 </para>
 
 @activity: 
- allow_cancel: 
+ cancellable: 
 
 
 <!-- ##### FUNCTION e_activity_get_clickable ##### -->
diff --git a/doc/reference/shell/tmpl/eshell-unused.sgml b/doc/reference/shell/tmpl/eshell-unused.sgml
index 15c9658..59aed5d 100644
--- a/doc/reference/shell/tmpl/eshell-unused.sgml
+++ b/doc/reference/shell/tmpl/eshell-unused.sgml
@@ -95,6 +95,37 @@ e-shell-window.sgml
 
 @window: 
 
+<!-- ##### FUNCTION e_activity_cancel ##### -->
+<para>
+
+</para>
+
+ activity: 
+
+<!-- ##### FUNCTION e_activity_get_allow_cancel ##### -->
+<para>
+
+</para>
+
+ activity: 
+ Returns: 
+
+<!-- ##### FUNCTION e_activity_is_cancelled ##### -->
+<para>
+
+</para>
+
+ activity: 
+ Returns: 
+
+<!-- ##### FUNCTION e_activity_set_allow_cancel ##### -->
+<para>
+
+</para>
+
+ activity: 
+ allow_cancel: 
+
 <!-- ##### FUNCTION e_get_user_data_dir ##### -->
 <para>
 
diff --git a/e-util/e-activity.c b/e-util/e-activity.c
index 631915d..f90361d 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
diff --git a/e-util/e-activity.h b/e-util/e-activity.h
index b396e3a..4573fad 100644
--- a/e-util/e-activity.h
+++ b/e-util/e-activity.h
@@ -65,18 +65,16 @@ struct _EActivityClass {
 };
 
 GType		e_activity_get_type		(void);
-EActivity *	e_activity_new			(const gchar *primary_text);
+EActivity *	e_activity_new			(void);
 EActivity *	e_activity_newv			(const gchar *format,
 						 ...) G_GNUC_PRINTF (1, 2);
-void		e_activity_cancel		(EActivity *activity);
 void		e_activity_complete		(EActivity *activity);
 void		e_activity_clicked		(EActivity *activity);
 gchar *		e_activity_describe		(EActivity *activity);
-gboolean	e_activity_is_cancelled		(EActivity *activity);
 gboolean	e_activity_is_completed		(EActivity *activity);
-gboolean	e_activity_get_allow_cancel	(EActivity *activity);
-void		e_activity_set_allow_cancel	(EActivity *activity,
-						 gboolean allow_cancel);
+GCancellable *	e_activity_get_cancellable	(EActivity *activity);
+void		e_activity_set_cancellable	(EActivity *activity,
+						 GCancellable *cancellable);
 gboolean	e_activity_get_clickable	(EActivity *activity);
 void		e_activity_set_clickable	(EActivity *activity,
 						 gboolean clickable);
diff --git a/e-util/e-io-activity.c b/e-util/e-io-activity.c
index c8eb761..e519fea 100644
--- a/e-util/e-io-activity.c
+++ b/e-util/e-io-activity.c
@@ -27,13 +27,11 @@
 
 struct _EIOActivityPrivate {
 	GAsyncResult *async_result;
-	GCancellable *cancellable;
 };
 
 enum {
 	PROP_0,
-	PROP_ASYNC_RESULT,
-	PROP_CANCELLABLE
+	PROP_ASYNC_RESULT
 };
 
 G_DEFINE_TYPE (
@@ -53,12 +51,6 @@ io_activity_set_property (GObject *object,
 				E_IO_ACTIVITY (object),
 				g_value_get_object (value));
 			return;
-
-		case PROP_CANCELLABLE:
-			e_io_activity_set_cancellable (
-				E_IO_ACTIVITY (object),
-				g_value_get_object (value));
-			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -76,12 +68,6 @@ io_activity_get_property (GObject *object,
 				value, e_io_activity_get_async_result (
 				E_IO_ACTIVITY (object)));
 			return;
-
-		case PROP_CANCELLABLE:
-			g_value_set_object (
-				value, e_io_activity_get_cancellable (
-				E_IO_ACTIVITY (object)));
-			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -99,32 +85,11 @@ io_activity_dispose (GObject *object)
 		priv->async_result = NULL;
 	}
 
-	if (priv->cancellable != NULL) {
-		g_object_unref (priv->cancellable);
-		priv->cancellable = NULL;
-	}
-
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (e_io_activity_parent_class)->dispose (object);
 }
 
 static void
-io_activity_cancelled (EActivity *activity)
-{
-	EIOActivity *io_activity;
-	GCancellable *cancellable;
-
-	/* Chain up to parent's cancelled() method. */
-	E_ACTIVITY_CLASS (e_io_activity_parent_class)->cancelled (activity);
-
-	io_activity = E_IO_ACTIVITY (activity);
-	cancellable = e_io_activity_get_cancellable (io_activity);
-
-	if (cancellable != NULL)
-		g_cancellable_cancel (cancellable);
-}
-
-static void
 io_activity_completed (EActivity *activity)
 {
 	EIOActivity *io_activity;
@@ -158,7 +123,6 @@ e_io_activity_class_init (EIOActivityClass *class)
 	object_class->dispose = io_activity_dispose;
 
 	activity_class = E_ACTIVITY_CLASS (class);
-	activity_class->cancelled = io_activity_cancelled;
 	activity_class->completed = io_activity_completed;
 
 	g_object_class_install_property (
@@ -171,17 +135,6 @@ e_io_activity_class_init (EIOActivityClass *class)
 			G_TYPE_ASYNC_RESULT,
 			G_PARAM_READWRITE |
 			G_PARAM_CONSTRUCT));
-
-	g_object_class_install_property (
-		object_class,
-		PROP_CANCELLABLE,
-		g_param_spec_object (
-			"cancellable",
-			"Cancellable",
-			NULL,
-			G_TYPE_CANCELLABLE,
-			G_PARAM_READWRITE |
-			G_PARAM_CONSTRUCT));
 }
 
 static void
@@ -236,36 +189,3 @@ e_io_activity_set_async_result (EIOActivity *io_activity,
 	g_object_notify (G_OBJECT (io_activity), "async-result");
 }
 
-GCancellable *
-e_io_activity_get_cancellable (EIOActivity *io_activity)
-{
-	g_return_val_if_fail (E_IS_IO_ACTIVITY (io_activity), NULL);
-
-	return io_activity->priv->cancellable;
-}
-
-void
-e_io_activity_set_cancellable (EIOActivity *io_activity,
-                               GCancellable *cancellable)
-{
-	g_return_if_fail (E_IS_IO_ACTIVITY (io_activity));
-
-	if (cancellable != NULL) {
-		g_return_if_fail (G_IS_CANCELLABLE (cancellable));
-		g_object_ref (cancellable);
-	}
-
-	if (io_activity->priv->cancellable != NULL)
-		g_object_unref (io_activity->priv->cancellable);
-
-	io_activity->priv->cancellable = cancellable;
-
-	g_object_freeze_notify (G_OBJECT (io_activity));
-
-	e_activity_set_allow_cancel (
-		E_ACTIVITY (io_activity), (cancellable != NULL));
-
-	g_object_notify (G_OBJECT (io_activity), "cancellable");
-
-	g_object_thaw_notify (G_OBJECT (io_activity));
-}
diff --git a/e-util/e-io-activity.h b/e-util/e-io-activity.h
index 7734174..20a7a06 100644
--- a/e-util/e-io-activity.h
+++ b/e-util/e-io-activity.h
@@ -66,9 +66,6 @@ EActivity *	e_io_activity_new		(const gchar *primary_text,
 GAsyncResult *	e_io_activity_get_async_result	(EIOActivity *io_activity);
 void		e_io_activity_set_async_result	(EIOActivity *io_activity,
 						 GAsyncResult *async_result);
-GCancellable *	e_io_activity_get_cancellable	(EIOActivity *io_activity);
-void		e_io_activity_set_cancellable	(EIOActivity *io_activity,
-						 GCancellable *cancellable);
 
 G_END_DECLS
 
diff --git a/e-util/e-timeout-activity.c b/e-util/e-timeout-activity.c
index 4ddf39f..b5a48f0 100644
--- a/e-util/e-timeout-activity.c
+++ b/e-util/e-timeout-activity.c
@@ -168,7 +168,7 @@ e_timeout_activity_set_timeout (ETimeoutActivity *timeout_activity,
 	g_return_if_fail (E_IS_TIMEOUT_ACTIVITY (timeout_activity));
 
 	if (timeout_activity->priv->timeout_id > 0)
-		e_activity_cancel (E_ACTIVITY (timeout_activity));
+		g_source_remove (timeout_activity->priv->timeout_id);
 
 	timeout_activity->priv->timeout_id = g_timeout_add_seconds (
 		seconds, (GSourceFunc) timeout_activity_cb, timeout_activity);
diff --git a/mail/mail-mt.c b/mail/mail-mt.c
index ce26572..76e2629 100644
--- a/mail/mail-mt.c
+++ b/mail/mail-mt.c
@@ -40,16 +40,8 @@
  *     to rework or get rid of the functions that use this. */
 const gchar *shell_builtin_backend = "mail";
 
-static void mail_operation_status		(CamelOperation *op,
-						 const gchar *what,
-						 gint pc,
-						 gpointer data);
-
 /* background operation status stuff */
 struct _MailMsgPrivate {
-	/* XXX We need to keep track of the state external to the
-	 *     pointer itself for locking/race conditions. */
-	gint activity_state;
 	EActivity *activity;
 	GtkWidget *error;
 	gboolean cancelable;
@@ -64,6 +56,28 @@ static GCond *mail_msg_cond;
 
 MailAsyncEvent *mail_async_event;
 
+static void
+mail_msg_cancelled (CamelOperation *operation,
+                    gpointer user_data)
+{
+	mail_msg_cancel (GPOINTER_TO_UINT (user_data));
+}
+
+static gboolean
+mail_msg_submit (EActivity *activity)
+{
+	EShell *shell;
+	EShellBackend *shell_backend;
+
+	shell = e_shell_get_default ();
+	shell_backend = e_shell_get_backend_by_name (
+		shell, shell_builtin_backend);
+
+	e_shell_backend_add_activity (shell_backend, activity);
+
+	return FALSE;
+}
+
 gpointer
 mail_msg_new (MailMsgInfo *info)
 {
@@ -78,14 +92,22 @@ mail_msg_new (MailMsgInfo *info)
 	msg->cancel = camel_operation_new ();
 
 	msg->priv = g_slice_new0 (MailMsgPrivate);
+	msg->priv->activity = e_activity_new ();
 	msg->priv->cancelable = TRUE;
 
+	e_activity_set_percent (msg->priv->activity, 0.0);
+
+	e_activity_set_cancellable (
+		msg->priv->activity,
+		G_CANCELLABLE (msg->cancel));
+
 	g_signal_connect (
-		msg->cancel, "status",
-		G_CALLBACK (mail_operation_status),
+		msg->cancel, "cancelled",
+		G_CALLBACK (mail_msg_cancelled),
 		GINT_TO_POINTER (msg->seq));
 
-	g_hash_table_insert (mail_msg_active_table, GINT_TO_POINTER (msg->seq), msg);
+	g_hash_table_insert (
+		mail_msg_active_table, GINT_TO_POINTER (msg->seq), msg);
 
 	d(printf("New message %p\n", msg));
 
@@ -94,28 +116,6 @@ mail_msg_new (MailMsgInfo *info)
 	return msg;
 }
 
-static void
-end_event_callback (CamelObject *o, EActivity *activity, gpointer error)
-{
-	EShell *shell;
-	EShellBackend *shell_backend;
-
-	shell = e_shell_get_default ();
-	shell_backend = e_shell_get_backend_by_name (
-		shell, shell_builtin_backend);
-
-	if (activity != NULL) {
-		e_activity_complete (activity);
-		g_object_unref (activity);
-	}
-
-	if (error != NULL) {
-		activity = e_alert_activity_new_warning (error);
-		e_shell_backend_add_activity (shell_backend, activity);
-		g_object_unref (activity);
-	}
-}
-
 #ifdef MALLOC_CHECK
 #include <mcheck.h>
 
@@ -140,11 +140,31 @@ checkmem (gpointer p)
 }
 #endif
 
-static void
+static gboolean
 mail_msg_free (MailMsg *mail_msg)
 {
-	if (mail_msg->priv->activity != NULL)
+	EShell *shell;
+	EShellBackend *shell_backend;
+
+	/* This is an idle callback. */
+
+	shell = e_shell_get_default ();
+	shell_backend = e_shell_get_backend_by_name (
+		shell, shell_builtin_backend);
+
+	g_mutex_lock (mail_msg_lock);
+
+	g_hash_table_remove (
+		mail_msg_active_table,
+		GINT_TO_POINTER (mail_msg->seq));
+	g_cond_broadcast (mail_msg_cond);
+
+	g_mutex_unlock (mail_msg_lock);
+
+	if (mail_msg->priv->activity != NULL) {
+		e_activity_complete (mail_msg->priv->activity);
 		g_object_unref (mail_msg->priv->activity);
+	}
 
 	if (mail_msg->cancel != NULL)
 		g_object_unref (mail_msg->cancel);
@@ -152,8 +172,20 @@ mail_msg_free (MailMsg *mail_msg)
 	if (mail_msg->error != NULL)
 		g_error_free (mail_msg->error);
 
+	if (mail_msg->priv->error != NULL) {
+		EActivity *activity;
+		GtkWidget *widget;
+
+		widget = mail_msg->priv->error;
+		activity = e_alert_activity_new_warning (widget);
+		e_shell_backend_add_activity (shell_backend, activity);
+		g_object_unref (activity);
+	}
+
 	g_slice_free (MailMsgPrivate, mail_msg->priv);
 	g_slice_free1 (mail_msg->info->size, mail_msg);
+
+	return FALSE;
 }
 
 gpointer
@@ -172,8 +204,6 @@ void
 mail_msg_unref (gpointer msg)
 {
 	MailMsg *mail_msg = msg;
-	EActivity *activity = NULL;
-	GtkWidget *error = NULL;
 
 	g_return_if_fail (mail_msg != NULL);
 	g_return_if_fail (mail_msg->ref_count > 0);
@@ -191,36 +221,9 @@ mail_msg_unref (gpointer msg)
 	if (mail_msg->info->free)
 		mail_msg->info->free (mail_msg);
 
-	g_mutex_lock (mail_msg_lock);
-
-	g_hash_table_remove (
-		mail_msg_active_table, GINT_TO_POINTER (mail_msg->seq));
-	g_cond_broadcast (mail_msg_cond);
-
-	/* We need to make sure we dont lose a reference here YUCK YUCK */
-	/* This is tightly integrated with the code in do_op_status,
-	   as it closely relates to the CamelOperation setup in msg_new () above */
-	if (mail_msg->priv->activity_state == 1) {
-		/* tell the other to free it itself */
-		mail_msg->priv->activity_state = 3;
-		g_mutex_unlock (mail_msg_lock);
-		return;
-	} else {
-		activity = mail_msg->priv->activity;
-		if (activity != NULL)
-			g_object_ref (activity);
-		error = mail_msg->priv->error;
-	}
-
-	g_mutex_unlock (mail_msg_lock);
-
-	mail_msg_free (mail_msg);
-
-	if (activity != NULL)
-		mail_async_event_emit (
-			mail_async_event, MAIL_ASYNC_GUI,
-			(MailAsyncFunc) end_event_callback,
-			NULL, activity, error);
+	/* Destroy the message from an idle callback
+	 * so we know we're in the main loop thread. */
+	g_idle_add ((GSourceFunc) mail_msg_free, mail_msg);
 }
 
 /* hash table of ops->dialogue of active errors */
@@ -442,6 +445,11 @@ mail_msg_idle_cb (void)
 	G_UNLOCK (idle_source_id);
 	/* check the main loop queue */
 	while ((msg = g_async_queue_try_pop (main_loop_queue)) != NULL) {
+		g_idle_add_full (
+			G_PRIORITY_DEFAULT,
+			(GSourceFunc) mail_msg_submit,
+			g_object_ref (msg->priv->activity),
+			(GDestroyNotify) g_object_unref);
 		if (msg->info->exec != NULL)
 			msg->info->exec (msg);
 		if (msg->info->done != NULL)
@@ -469,6 +477,12 @@ mail_msg_proxy (MailMsg *msg)
 		g_free (text);
 	}
 
+	g_idle_add_full (
+		G_PRIORITY_DEFAULT,
+		(GSourceFunc) mail_msg_submit,
+		g_object_ref (msg->priv->activity),
+		(GDestroyNotify) g_object_unref);
+
 	if (msg->info->exec != NULL)
 		msg->info->exec (msg);
 
@@ -840,154 +854,6 @@ mail_call_main (mail_call_t type, MailMainFunc func, ...)
 	return ret;
 }
 
-/* ******************************************************************************** */
-
-struct _op_status_msg {
-	MailMsg base;
-
-	CamelOperation *op;
-	gchar *what;
-	gint pc;
-	gpointer data;
-};
-
-static void
-op_cancelled_cb (EActivity *activity,
-                 gpointer user_data)
-{
-	mail_msg_cancel (GPOINTER_TO_UINT (user_data));
-}
-
-static void
-op_status_exec (struct _op_status_msg *m)
-{
-	EShell *shell;
-	EShellBackend *shell_backend;
-	MailMsg *msg;
-	MailMsgPrivate *data;
-	gchar *out, *p, *o, c;
-	gint pc;
-
-	g_return_if_fail (mail_in_main_thread ());
-
-	shell = e_shell_get_default ();
-	shell_backend = e_shell_get_backend_by_name (
-		shell, shell_builtin_backend);
-
-	g_mutex_lock (mail_msg_lock);
-
-	msg = g_hash_table_lookup (mail_msg_active_table, m->data);
-
-	if (msg == NULL) {
-		g_mutex_unlock (mail_msg_lock);
-		return;
-	}
-
-	data = msg->priv;
-
-	out = g_alloca (strlen (m->what) * 2 + 1);
-	o = out;
-	p = m->what;
-	while ((c = *p++)) {
-		if (c == '%')
-			*o++ = '%';
-		*o++ = c;
-	}
-	*o = 0;
-
-	pc = m->pc;
-
-	if (data->activity == NULL) {
-		gchar *what;
-
-		/* its being created/removed?  well leave it be */
-		if (data->activity_state == 1 || data->activity_state == 3) {
-			g_mutex_unlock (mail_msg_lock);
-			return;
-		} else {
-			data->activity_state = 1;
-
-			g_mutex_unlock (mail_msg_lock);
-			if (msg->info->desc)
-				what = msg->info->desc (msg);
-			else if (m->what)
-				what = g_strdup (m->what);
-			/* uncommenting because message is not very useful for a user, see bug 271734*/
-			else {
-				what = g_strdup("");
-			}
-
-			data->activity = e_activity_new (what);
-			e_activity_set_allow_cancel (data->activity, TRUE);
-			e_activity_set_percent (data->activity, 0.0);
-			e_shell_backend_add_activity (shell_backend, data->activity);
-
-			g_signal_connect (
-				data->activity, "cancelled",
-				G_CALLBACK (op_cancelled_cb),
-				GUINT_TO_POINTER (msg->seq));
-
-			g_free (what);
-			g_mutex_lock (mail_msg_lock);
-			if (data->activity_state == 3) {
-				EActivity *activity;
-
-				activity = g_object_ref (data->activity);
-
-				g_mutex_unlock (mail_msg_lock);
-				mail_msg_free (msg);
-
-				if (activity != 0)
-					mail_async_event_emit (
-						mail_async_event, MAIL_ASYNC_GUI, (MailAsyncFunc) end_event_callback,
-								NULL, activity, NULL);
-			} else {
-				data->activity_state = 2;
-				g_mutex_unlock (mail_msg_lock);
-			}
-			return;
-		}
-	} else if (data->activity != NULL) {
-		e_activity_set_primary_text (data->activity, out);
-		e_activity_set_percent (data->activity, pc);
-		g_mutex_unlock (mail_msg_lock);
-	} else {
-		g_mutex_unlock (mail_msg_lock);
-	}
-}
-
-static void
-op_status_free (struct _op_status_msg *m)
-{
-	g_free (m->what);
-}
-
-static MailMsgInfo op_status_info = {
-	sizeof (struct _op_status_msg),
-	(MailMsgDescFunc) NULL,
-	(MailMsgExecFunc) op_status_exec,
-	(MailMsgDoneFunc) NULL,
-	(MailMsgFreeFunc) op_status_free
-};
-
-static void
-mail_operation_status (CamelOperation *op,
-                       const gchar *what,
-                       gint pc,
-                       gpointer data)
-{
-	struct _op_status_msg *m;
-
-	d(printf("got operation statys: %s %d%%\n", what, pc));
-
-	m = mail_msg_new (&op_status_info);
-	m->op = op;
-	m->what = g_strdup (what);
-	m->pc = pc;
-	m->data = data;
-	mail_msg_main_loop_push (m);
-}
-
 void
 mail_mt_set_backend (gchar *backend)
 {
diff --git a/modules/calendar/e-cal-shell-view-memopad.c b/modules/calendar/e-cal-shell-view-memopad.c
index 267f814..7fdf356 100644
--- a/modules/calendar/e-cal-shell-view-memopad.c
+++ b/modules/calendar/e-cal-shell-view-memopad.c
@@ -435,8 +435,9 @@ e_cal_shell_view_memopad_set_status_message (ECalShellView *cal_shell_view,
 		}
 
 	} else if (activity == NULL) {
-		activity = e_activity_new (status_message);
+		activity = e_activity_new ();
 		e_activity_set_percent (activity, percent);
+		e_activity_set_primary_text (activity, status_message);
 		e_shell_backend_add_activity (shell_backend, activity);
 
 	} else {
diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c
index a02888d..c5a9f22 100644
--- a/modules/calendar/e-cal-shell-view-private.c
+++ b/modules/calendar/e-cal-shell-view-private.c
@@ -810,8 +810,9 @@ e_cal_shell_view_set_status_message (ECalShellView *cal_shell_view,
 			activity = NULL;
 		}
 	} else if (activity == NULL) {
-		activity = e_activity_new (status_message);
+		activity = e_activity_new ();
 		e_activity_set_percent (activity, percent);
+		e_activity_set_primary_text (activity, status_message);
 		e_shell_backend_add_activity (shell_backend, activity);
 	} else {
 		e_activity_set_percent (activity, percent);
diff --git a/modules/calendar/e-cal-shell-view-taskpad.c b/modules/calendar/e-cal-shell-view-taskpad.c
index c7269bc..a00e630 100644
--- a/modules/calendar/e-cal-shell-view-taskpad.c
+++ b/modules/calendar/e-cal-shell-view-taskpad.c
@@ -562,8 +562,9 @@ e_cal_shell_view_taskpad_set_status_message (ECalShellView *cal_shell_view,
 		}
 
 	} else if (activity == NULL) {
-		activity = e_activity_new (status_message);
+		activity = e_activity_new ();
 		e_activity_set_percent (activity, percent);
+		e_activity_set_primary_text (activity, status_message);
 		e_shell_backend_add_activity (shell_backend, activity);
 
 	} else {
diff --git a/modules/calendar/e-memo-shell-view-private.c b/modules/calendar/e-memo-shell-view-private.c
index 061e3c0..a33296d 100644
--- a/modules/calendar/e-memo-shell-view-private.c
+++ b/modules/calendar/e-memo-shell-view-private.c
@@ -375,8 +375,9 @@ e_memo_shell_view_set_status_message (EMemoShellView *memo_shell_view,
 		}
 
 	} else if (activity == NULL) {
-		activity = e_activity_new (status_message);
+		activity = e_activity_new ();
 		e_activity_set_percent (activity, percent);
+		e_activity_set_primary_text (activity, status_message);
 		e_shell_backend_add_activity (shell_backend, activity);
 
 	} else {
diff --git a/modules/calendar/e-task-shell-view-private.c b/modules/calendar/e-task-shell-view-private.c
index e5cf757..5e1b352 100644
--- a/modules/calendar/e-task-shell-view-private.c
+++ b/modules/calendar/e-task-shell-view-private.c
@@ -524,8 +524,9 @@ e_task_shell_view_set_status_message (ETaskShellView *task_shell_view,
 		}
 
 	} else if (activity == NULL) {
-		activity = e_activity_new (status_message);
+		activity = e_activity_new ();
 		e_activity_set_percent (activity, percent);
+		e_activity_set_primary_text (activity, status_message);
 		e_shell_backend_add_activity (shell_backend, activity);
 
 	} else {
diff --git a/shell/e-shell-taskbar.c b/shell/e-shell-taskbar.c
index a82d3d6..47f900a 100644
--- a/shell/e-shell-taskbar.c
+++ b/shell/e-shell-taskbar.c
@@ -96,12 +96,13 @@ shell_taskbar_activity_add (EShellTaskbar *shell_taskbar,
 	GtkBox *box;
 	GtkWidget *proxy;
 
+	/* Proxy widgets manage their own visibility.
+	 * Don't call gtk_widget_show() on it here. */
 	proxy = e_activity_proxy_new (activity);
 	box = GTK_BOX (shell_taskbar->priv->hbox);
 	gtk_box_pack_start (box, proxy, TRUE, TRUE, 0);
 	gtk_box_reorder_child (box, proxy, 0);
 	gtk_widget_show (GTK_WIDGET (box));
-	gtk_widget_show (proxy);
 
 	g_hash_table_insert (
 		shell_taskbar->priv->proxy_table,
@@ -176,13 +177,14 @@ shell_taskbar_get_property (GObject *object,
 }
 
 static gboolean
-disconnect_remove (EActivity      *activity,
-		   EActivityProxy *proxy,
-		   EShellTaskbar  *shell_taskbar)
+disconnect_remove (EActivity *activity,
+                   EActivityProxy *proxy,
+                   EShellTaskbar *shell_taskbar)
 {
-	g_signal_handlers_disconnect_matched
-		(activity, G_SIGNAL_MATCH_DATA,
-		 0, 0, NULL, NULL, shell_taskbar);
+	g_signal_handlers_disconnect_matched (
+		activity, G_SIGNAL_MATCH_DATA,
+		0, 0, NULL, NULL, shell_taskbar);
+
 	return TRUE;
 }
 
@@ -217,9 +219,8 @@ shell_taskbar_dispose (GObject *object)
 		priv->hbox = NULL;
 	}
 
-	g_hash_table_foreach_remove (priv->proxy_table,
-				     (GHRFunc) disconnect_remove,
-				     object);
+	g_hash_table_foreach_remove (
+		priv->proxy_table, (GHRFunc) disconnect_remove, object);
 
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (e_shell_taskbar_parent_class)->dispose (object);
diff --git a/shell/e-shell.c b/shell/e-shell.c
index 93832ec..28abe02 100644
--- a/shell/e-shell.c
+++ b/shell/e-shell.c
@@ -240,8 +240,11 @@ shell_prepare_for_offline (EShell *shell)
 	if (shell->priv->preparing_for_line_change != NULL)
 		return;
 
-	shell->priv->preparing_for_line_change =
-		e_activity_new (_("Preparing to go offline..."));
+	shell->priv->preparing_for_line_change = e_activity_new ();
+
+	e_activity_set_primary_text (
+		shell->priv->preparing_for_line_change,
+		_("Preparing to go offline..."));
 
 	g_object_add_toggle_ref (
 		G_OBJECT (shell->priv->preparing_for_line_change),
@@ -290,8 +293,11 @@ shell_prepare_for_online (EShell *shell)
 	if (shell->priv->preparing_for_line_change != NULL)
 		return;
 
-	shell->priv->preparing_for_line_change =
-		e_activity_new (_("Preparing to go online..."));
+	shell->priv->preparing_for_line_change = e_activity_new ();
+
+	e_activity_set_primary_text (
+		shell->priv->preparing_for_line_change,
+		_("Preparing to go online..."));
 
 	g_object_add_toggle_ref (
 		G_OBJECT (shell->priv->preparing_for_line_change),
@@ -349,8 +355,11 @@ shell_prepare_for_quit (EShell *shell)
 	if (shell->priv->preparing_for_quit != NULL)
 		return;
 
-	shell->priv->preparing_for_quit =
-		e_activity_new (_("Preparing to quit..."));
+	shell->priv->preparing_for_quit = e_activity_new ();
+
+	e_activity_set_primary_text (
+		shell->priv->preparing_for_quit,
+		_("Preparing to quit..."));
 
 	g_object_add_toggle_ref (
 		G_OBJECT (shell->priv->preparing_for_quit),
diff --git a/widgets/misc/e-activity-proxy.c b/widgets/misc/e-activity-proxy.c
index 8e20e67..e96f18e 100644
--- a/widgets/misc/e-activity-proxy.c
+++ b/widgets/misc/e-activity-proxy.c
@@ -47,19 +47,33 @@ G_DEFINE_TYPE (
 	GTK_TYPE_EVENT_BOX)
 
 static void
+activity_proxy_cancel (EActivity *activity)
+{
+	GCancellable *cancellable;
+
+	/* We shouldn't get here unless the EActivity has a GCancellable,
+	 * since otherwise the cancel button is invisible and unclickable.
+	 * g_cancellable_cancel() will emit a warning if this breaks. */
+
+	cancellable = e_activity_get_cancellable (activity);
+	g_cancellable_cancel (cancellable);
+}
+
+static void
 activity_proxy_update (EActivityProxy *proxy)
 {
-	EActivity *activity = proxy->priv->activity;
+	EActivity *activity;
+	GCancellable *cancellable;
 	const gchar *icon_name;
-	gboolean allow_cancel;
 	gboolean cancelled;
 	gboolean clickable;
 	gboolean completed;
 	gboolean sensitive;
 	gchar *description;
 
-	allow_cancel = e_activity_get_allow_cancel (activity);
-	cancelled = e_activity_is_cancelled (activity);
+	activity = proxy->priv->activity;
+	cancellable = e_activity_get_cancellable (activity);
+	cancelled = g_cancellable_is_cancelled (cancellable);
 	clickable = e_activity_get_clickable (activity);
 	completed = e_activity_is_completed (activity);
 	icon_name = e_activity_get_icon_name (activity);
@@ -67,6 +81,7 @@ activity_proxy_update (EActivityProxy *proxy)
 	description = e_activity_describe (activity);
 	gtk_widget_set_tooltip_text (GTK_WIDGET (proxy), description);
 	gtk_label_set_text (GTK_LABEL (proxy->priv->label), description);
+	gtk_widget_set_visible (GTK_WIDGET (proxy), (description != NULL));
 	g_free (description);
 
 	/* Note, an activity requires an icon name in order to
@@ -93,7 +108,7 @@ activity_proxy_update (EActivityProxy *proxy)
 		gtk_widget_hide (proxy->priv->image);
 	}
 
-	if (allow_cancel)
+	if (cancellable != NULL)
 		gtk_widget_show (proxy->priv->cancel);
 	else
 		gtk_widget_hide (proxy->priv->cancel);
@@ -202,7 +217,7 @@ activity_proxy_constructed (GObject *object)
 
 	g_signal_connect_swapped (
 		proxy->priv->cancel, "clicked",
-		G_CALLBACK (e_activity_cancel), proxy->priv->activity);
+		G_CALLBACK (activity_proxy_cancel), proxy->priv->activity);
 
 	g_signal_connect_swapped (
 		proxy->priv->activity, "cancelled",



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