diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2010-10-22 04:21:19 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2010-10-23 02:21:22 +0800 |
commit | c881b5bc5e61d04b18d4ab46ad70533e7340d15b (patch) | |
tree | e70a3ed0d2f93dacfe20d856de4d29578beb2e50 | |
parent | f0714755e2fa8b06425907c2cf189abd3a1b7119 (diff) | |
download | gsoc2013-evolution-c881b5bc5e61d04b18d4ab46ad70533e7340d15b.tar.gz gsoc2013-evolution-c881b5bc5e61d04b18d4ab46ad70533e7340d15b.tar.zst gsoc2013-evolution-c881b5bc5e61d04b18d4ab46ad70533e7340d15b.zip |
Simplify EActivity.
With unintrusive error dialogs gone, we can cut some unnecessary bits
out of EActivity.
I'm also adding a new enum property called "state", which is one of:
E_ACTIVITY_RUNNING
E_ACTIVITY_WAITING
E_ACTIVITY_CANCELLED
E_ACTIVITY_COMPLETED
The state of an activity must be explicitly changed. In particular,
when the user cancels an activity the state should be set only after
confirming the operation has been cancelled and not when cancellation
is requested (e.g. after receiving a G_IO_ERROR_CANCELLED, not when
the GCancellable emits "cancelled"). EActivityBar and EActivityProxy
widgets have been updated to make this distinction clearer in the UI.
E_ACTIVITY_WAITING will be used when activities have to be queued and
dispatched in sequence, which I haven't written yet.
46 files changed, 942 insertions, 1124 deletions
diff --git a/addressbook/gui/widgets/e-addressbook-view.c b/addressbook/gui/widgets/e-addressbook-view.c index fac9723923..fcf4dd3f7c 100644 --- a/addressbook/gui/widgets/e-addressbook-view.c +++ b/addressbook/gui/widgets/e-addressbook-view.c @@ -517,7 +517,7 @@ addressbook_view_dispose (GObject *object) if (priv->activity != NULL) { /* XXX Activity is not cancellable. */ - e_activity_complete (priv->activity); + e_activity_set_state (priv->activity, E_ACTIVITY_COMPLETED); g_object_unref (priv->activity); priv->activity = NULL; } @@ -1075,7 +1075,7 @@ status_message (EAddressbookView *view, if (status == NULL || *status == '\0') { if (activity != NULL) { - e_activity_complete (activity); + e_activity_set_state (activity, E_ACTIVITY_COMPLETED); g_object_unref (activity); view->priv->activity = NULL; } @@ -1083,11 +1083,11 @@ status_message (EAddressbookView *view, } else if (activity == NULL) { activity = e_activity_new (); view->priv->activity = activity; - e_activity_set_primary_text (activity, status); + e_activity_set_text (activity, status); e_shell_backend_add_activity (shell_backend, activity); } else - e_activity_set_primary_text (activity, status); + e_activity_set_text (activity, status); } static void diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c index a30a48263b..34cf70597a 100644 --- a/composer/e-msg-composer.c +++ b/composer/e-msg-composer.c @@ -3533,11 +3533,9 @@ void e_msg_composer_send (EMsgComposer *composer) { AsyncContext *context; - GtkAction *action; EActivityBar *activity_bar; GCancellable *cancellable; gboolean proceed_with_send = TRUE; - const gchar *icon_name; g_return_if_fail (E_IS_MSG_COMPOSER (composer)); @@ -3554,10 +3552,6 @@ e_msg_composer_send (EMsgComposer *composer) e_activity_set_cancellable (context->activity, cancellable); g_object_unref (cancellable); - action = ACTION (SEND); - icon_name = gtk_action_get_icon_name (action); - e_activity_set_icon_name (context->activity, icon_name); - activity_bar = E_ACTIVITY_BAR (composer->priv->activity_bar); e_activity_bar_set_activity (activity_bar, context->activity); @@ -3623,10 +3617,8 @@ void e_msg_composer_save_draft (EMsgComposer *composer) { AsyncContext *context; - GtkAction *action; EActivityBar *activity_bar; GCancellable *cancellable; - const gchar *icon_name; g_return_if_fail (E_IS_MSG_COMPOSER (composer)); @@ -3637,10 +3629,6 @@ e_msg_composer_save_draft (EMsgComposer *composer) e_activity_set_cancellable (context->activity, cancellable); g_object_unref (cancellable); - action = ACTION (SAVE_DRAFT); - icon_name = gtk_action_get_icon_name (action); - e_activity_set_icon_name (context->activity, icon_name); - activity_bar = E_ACTIVITY_BAR (composer->priv->activity_bar); e_activity_bar_set_activity (activity_bar, context->activity); @@ -3703,10 +3691,8 @@ e_msg_composer_print (EMsgComposer *composer, GtkPrintOperationAction print_action) { AsyncContext *context; - GtkAction *action; EActivityBar *activity_bar; GCancellable *cancellable; - const gchar *icon_name; g_return_if_fail (E_IS_MSG_COMPOSER (composer)); @@ -3718,10 +3704,6 @@ e_msg_composer_print (EMsgComposer *composer, e_activity_set_cancellable (context->activity, cancellable); g_object_unref (cancellable); - action = ACTION (PRINT); - icon_name = gtk_action_get_icon_name (action); - e_activity_set_icon_name (context->activity, icon_name); - activity_bar = E_ACTIVITY_BAR (composer->priv->activity_bar); e_activity_bar_set_activity (activity_bar, context->activity); diff --git a/doc/reference/shell/eshell-sections.txt b/doc/reference/shell/eshell-sections.txt index 07ee9b495d..63a8578145 100644 --- a/doc/reference/shell/eshell-sections.txt +++ b/doc/reference/shell/eshell-sections.txt @@ -471,21 +471,16 @@ EActivity e_activity_new e_activity_newv e_activity_complete -e_activity_clicked e_activity_describe e_activity_is_completed e_activity_get_cancellable e_activity_set_cancellable -e_activity_get_clickable -e_activity_set_clickable e_activity_get_icon_name e_activity_set_icon_name e_activity_get_percent e_activity_set_percent -e_activity_get_primary_text -e_activity_set_primary_text -e_activity_get_secondary_text -e_activity_set_secondary_text +e_activity_get_text +e_activity_set_text <SUBSECTION Standard> E_ACTIVITY E_IS_ACTIVITY diff --git a/doc/reference/shell/tmpl/e-activity.sgml b/doc/reference/shell/tmpl/e-activity.sgml index 871758fb5e..1d4d1b3f3c 100644 --- a/doc/reference/shell/tmpl/e-activity.sgml +++ b/doc/reference/shell/tmpl/e-activity.sgml @@ -45,22 +45,6 @@ e-activity @Returns: -<!-- ##### FUNCTION e_activity_complete ##### --> -<para> - -</para> - -@activity: - - -<!-- ##### FUNCTION e_activity_clicked ##### --> -<para> - -</para> - -@activity: - - <!-- ##### FUNCTION e_activity_describe ##### --> <para> @@ -70,15 +54,6 @@ e-activity @Returns: -<!-- ##### FUNCTION e_activity_is_completed ##### --> -<para> - -</para> - -@activity: -@Returns: - - <!-- ##### FUNCTION e_activity_get_cancellable ##### --> <para> @@ -97,24 +72,6 @@ e-activity @cancellable: -<!-- ##### FUNCTION e_activity_get_clickable ##### --> -<para> - -</para> - -@activity: -@Returns: - - -<!-- ##### FUNCTION e_activity_set_clickable ##### --> -<para> - -</para> - -@activity: -@clickable: - - <!-- ##### FUNCTION e_activity_get_icon_name ##### --> <para> @@ -151,25 +108,7 @@ e-activity @percent: -<!-- ##### FUNCTION e_activity_get_primary_text ##### --> -<para> - -</para> - -@activity: -@Returns: - - -<!-- ##### FUNCTION e_activity_set_primary_text ##### --> -<para> - -</para> - -@activity: -@primary_text: - - -<!-- ##### FUNCTION e_activity_get_secondary_text ##### --> +<!-- ##### FUNCTION e_activity_get_text ##### --> <para> </para> @@ -178,12 +117,12 @@ e-activity @Returns: -<!-- ##### FUNCTION e_activity_set_secondary_text ##### --> +<!-- ##### FUNCTION e_activity_set_text ##### --> <para> </para> @activity: -@secondary_text: +@text: diff --git a/doc/reference/shell/tmpl/eshell-unused.sgml b/doc/reference/shell/tmpl/eshell-unused.sgml index e60ce1256a..4c9b60d43d 100644 --- a/doc/reference/shell/tmpl/eshell-unused.sgml +++ b/doc/reference/shell/tmpl/eshell-unused.sgml @@ -245,6 +245,20 @@ e-shell-window.sgml @activity: +<!-- ##### FUNCTION e_activity_clicked ##### --> +<para> + +</para> + +@activity: + +<!-- ##### FUNCTION e_activity_complete ##### --> +<para> + +</para> + +@activity: + <!-- ##### FUNCTION e_activity_get_allow_cancel ##### --> <para> @@ -253,6 +267,30 @@ e-shell-window.sgml @activity: @Returns: +<!-- ##### FUNCTION e_activity_get_clickable ##### --> +<para> + +</para> + +@activity: +@Returns: + +<!-- ##### FUNCTION e_activity_get_primary_text ##### --> +<para> + +</para> + +@activity: +@Returns: + +<!-- ##### FUNCTION e_activity_get_secondary_text ##### --> +<para> + +</para> + +@activity: +@Returns: + <!-- ##### FUNCTION e_activity_is_cancelled ##### --> <para> @@ -261,6 +299,14 @@ e-shell-window.sgml @activity: @Returns: +<!-- ##### FUNCTION e_activity_is_completed ##### --> +<para> + +</para> + +@activity: +@Returns: + <!-- ##### FUNCTION e_activity_set_allow_cancel ##### --> <para> @@ -269,6 +315,30 @@ e-shell-window.sgml @activity: @allow_cancel: +<!-- ##### FUNCTION e_activity_set_clickable ##### --> +<para> + +</para> + +@activity: +@clickable: + +<!-- ##### FUNCTION e_activity_set_primary_text ##### --> +<para> + +</para> + +@activity: +@primary_text: + +<!-- ##### FUNCTION e_activity_set_secondary_text ##### --> +<para> + +</para> + +@activity: +@secondary_text: + <!-- ##### FUNCTION e_alert_dialog_count_buttons ##### --> <para> diff --git a/e-util/Makefile.am b/e-util/Makefile.am index d96b2b0bc3..3f4388ebe1 100644 --- a/e-util/Makefile.am +++ b/e-util/Makefile.am @@ -2,6 +2,14 @@ eutilincludedir = $(privincludedir)/e-util ecpsdir = $(privdatadir)/ecps ruledir = $(privdatadir) +include $(top_srcdir)/glib-gen.mak +glib_enum_headers=e-util-enums.h +glib_enum_define=E +glib_enum_prefix=e + +ENUM_GENERATED = e-util-enumtypes.h e-util-enumtypes.c +MARSHAL_GENERATED = e-marshal.c e-marshal.h + if OS_WIN32 PLATFORM_SOURCES = e-win32-reloc.c e-win32-defaults.c e-win32-defaults.h endif @@ -28,7 +36,6 @@ eutilinclude_HEADERS = \ e-html-utils.h \ e-icon-factory.h \ e-import.h \ - e-io-activity.h \ e-marshal.h \ e-mktemp.h \ e-module.h \ @@ -49,6 +56,8 @@ eutilinclude_HEADERS = \ e-text-event-processor.h \ e-ui-manager.h \ e-util.h \ + e-util-enums.h \ + e-util-enumtypes.h \ e-unicode.h \ e-xml-utils.h \ gconf-bridge.h @@ -103,7 +112,6 @@ libeutil_la_SOURCES = \ e-html-utils.c \ e-icon-factory.c \ e-import.c \ - e-io-activity.c \ e-marshal.c \ e-mktemp.c \ e-module.c \ @@ -124,15 +132,13 @@ libeutil_la_SOURCES = \ e-ui-manager.c \ e-util.c \ e-unicode.c \ + e-util-enumtypes.c \ e-util-private.h \ e-xml-utils.c \ gconf-bridge.c \ gtk-compat.h \ $(PLATFORM_SOURCES) -MARSHAL_GENERATED = e-marshal.c e-marshal.h -@EVO_MARSHAL_RULE@ - libeutil_la_LDFLAGS = $(NO_UNDEFINED) libeutil_la_LIBADD = \ @@ -149,7 +155,7 @@ EXTRA_DIST = \ e-system.error.xml \ e-marshal.list -BUILT_SOURCES = $(MARSHAL_GENERATED) $(error_DATA) +BUILT_SOURCES = $(ENUM_GENERATED) $(MARSHAL_GENERATED) $(error_DATA) CLEANFILES = $(BUILT_SOURCES) dist-hook: diff --git a/e-util/e-activity.c b/e-util/e-activity.c index 38196e8484..7e0cb1c8be 100644 --- a/e-util/e-activity.c +++ b/e-util/e-activity.c @@ -26,6 +26,7 @@ #include <camel/camel.h> #include "e-util/e-util.h" +#include "e-util/e-util-enumtypes.h" #define E_ACTIVITY_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ @@ -33,36 +34,22 @@ struct _EActivityPrivate { GCancellable *cancellable; + EActivityState state; gchar *icon_name; - gchar *primary_text; - gchar *secondary_text; + gchar *text; gdouble percent; - - guint clickable : 1; - guint completed : 1; }; enum { PROP_0, PROP_CANCELLABLE, - PROP_CLICKABLE, PROP_ICON_NAME, PROP_PERCENT, - PROP_PRIMARY_TEXT, - PROP_SECONDARY_TEXT + PROP_STATE, + PROP_TEXT }; -enum { - CANCELLED, - CLICKED, - COMPLETED, - DESCRIBE, - LAST_SIGNAL -}; - -static gulong signals[LAST_SIGNAL]; - G_DEFINE_TYPE ( EActivity, e_activity, @@ -78,29 +65,7 @@ activity_camel_status_cb (EActivity *activity, g_object_set ( activity, "percent", (gdouble) percent, - "primary-text", description, NULL); -} - -static gboolean -activity_describe_accumulator (GSignalInvocationHint *ihint, - GValue *return_accu, - const GValue *handler_return, - gpointer accu_data) -{ - const gchar *string; - - string = g_value_get_string (handler_return); - g_value_set_string (return_accu, string); - - return (string == NULL); -} - -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); + "text", description, NULL); } static void @@ -116,12 +81,6 @@ activity_set_property (GObject *object, g_value_get_object (value)); return; - case PROP_CLICKABLE: - e_activity_set_clickable ( - E_ACTIVITY (object), - g_value_get_boolean (value)); - return; - case PROP_ICON_NAME: e_activity_set_icon_name ( E_ACTIVITY (object), @@ -134,14 +93,14 @@ activity_set_property (GObject *object, g_value_get_double (value)); return; - case PROP_PRIMARY_TEXT: - e_activity_set_primary_text ( + case PROP_STATE: + e_activity_set_state ( E_ACTIVITY (object), - g_value_get_string (value)); + g_value_get_enum (value)); return; - case PROP_SECONDARY_TEXT: - e_activity_set_secondary_text ( + case PROP_TEXT: + e_activity_set_text ( E_ACTIVITY (object), g_value_get_string (value)); return; @@ -163,12 +122,6 @@ activity_get_property (GObject *object, E_ACTIVITY (object))); return; - case PROP_CLICKABLE: - g_value_set_boolean ( - value, e_activity_get_clickable ( - E_ACTIVITY (object))); - return; - case PROP_ICON_NAME: g_value_set_string ( value, e_activity_get_icon_name ( @@ -181,15 +134,15 @@ activity_get_property (GObject *object, E_ACTIVITY (object))); return; - case PROP_PRIMARY_TEXT: - g_value_set_string ( - value, e_activity_get_primary_text ( + case PROP_STATE: + g_value_set_enum ( + value, e_activity_get_state ( E_ACTIVITY (object))); return; - case PROP_SECONDARY_TEXT: + case PROP_TEXT: g_value_set_string ( - value, e_activity_get_secondary_text ( + value, e_activity_get_text ( E_ACTIVITY (object))); return; } @@ -225,55 +178,51 @@ activity_finalize (GObject *object) priv = E_ACTIVITY_GET_PRIVATE (object); g_free (priv->icon_name); - g_free (priv->primary_text); - g_free (priv->secondary_text); + g_free (priv->text); /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (e_activity_parent_class)->finalize (object); } -static void -activity_completed (EActivity *activity) -{ - activity->priv->completed = TRUE; -} - -static void -activity_clicked (EActivity *activity) -{ - /* Allow subclasses to safely chain up. */ -} - static gchar * activity_describe (EActivity *activity) { GString *string; GCancellable *cancellable; + EActivityState state; const gchar *text; gdouble percent; string = g_string_sized_new (256); cancellable = e_activity_get_cancellable (activity); - text = e_activity_get_primary_text (activity); percent = e_activity_get_percent (activity); + state = e_activity_get_state (activity); + text = e_activity_get_text (activity); if (text == NULL) return NULL; - if (g_cancellable_is_cancelled (cancellable)) { + if (state == E_ACTIVITY_CANCELLED) { /* Translators: This is a cancelled activity. */ g_string_printf (string, _("%s (cancelled)"), text); - } else if (e_activity_is_completed (activity)) { + } else if (state == E_ACTIVITY_COMPLETED) { /* Translators: This is a completed activity. */ g_string_printf (string, _("%s (completed)"), text); + } else if (state == E_ACTIVITY_WAITING) { + /* Translators: This is an activity waiting to run. */ + g_string_printf (string, _("%s (waiting)"), text); + } else if (g_cancellable_is_cancelled (cancellable)) { + /* Translators: This is a running activity which + * the user has requested to cancel. */ + g_string_printf (string, _("%s (cancelling)"), text); } else if (percent <= 0.0) { g_string_printf (string, _("%s"), text); } else { - /* Translators: This is an activity whose percent - * complete is known. */ + /* Translators: This is a running activity whose + * percent complete is known. */ g_string_printf ( - string, _("%s (%d%% complete)"), text, - (gint) (percent)); + string, _("%s (%d%% complete)"), + text, (gint) (percent)); } return g_string_free (string, FALSE); @@ -292,8 +241,6 @@ e_activity_class_init (EActivityClass *class) object_class->dispose = activity_dispose; object_class->finalize = activity_finalize; - class->completed = activity_completed; - class->clicked = activity_clicked; class->describe = activity_describe; g_object_class_install_property ( @@ -309,17 +256,6 @@ e_activity_class_init (EActivityClass *class) g_object_class_install_property ( object_class, - PROP_CLICKABLE, - g_param_spec_boolean ( - "clickable", - NULL, - NULL, - FALSE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, PROP_ICON_NAME, g_param_spec_string ( "icon-name", @@ -344,61 +280,26 @@ e_activity_class_init (EActivityClass *class) g_object_class_install_property ( object_class, - PROP_PRIMARY_TEXT, - g_param_spec_string ( - "primary-text", - NULL, + PROP_STATE, + g_param_spec_enum ( + "state", NULL, NULL, + E_TYPE_ACTIVITY_STATE, + E_ACTIVITY_RUNNING, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property ( object_class, - PROP_SECONDARY_TEXT, + PROP_TEXT, g_param_spec_string ( - "secondary-text", + "text", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - signals[CANCELLED] = g_signal_new ( - "cancelled", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (EActivityClass, cancelled), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[CLICKED] = g_signal_new ( - "clicked", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (EActivityClass, clicked), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[COMPLETED] = g_signal_new ( - "completed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (EActivityClass, completed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[DESCRIBE] = g_signal_new ( - "describe", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (EActivityClass, describe), - activity_describe_accumulator, NULL, - e_marshal_STRING__VOID, - G_TYPE_STRING, 0); } static void @@ -417,46 +318,20 @@ EActivity * e_activity_newv (const gchar *format, ...) { EActivity *activity; - gchar *primary_text; + gchar *text; va_list args; activity = e_activity_new (); va_start (args, format); - primary_text = g_strdup_vprintf (format, args); - e_activity_set_primary_text (activity, primary_text); - g_free (primary_text); + text = g_strdup_vprintf (format, args); + e_activity_set_text (activity, text); + g_free (text); va_end (args); return activity; } -void -e_activity_complete (EActivity *activity) -{ - GCancellable *cancellable; - - g_return_if_fail (E_IS_ACTIVITY (activity)); - - cancellable = e_activity_get_cancellable (activity); - - if (g_cancellable_is_cancelled (cancellable)) - return; - - if (activity->priv->completed) - return; - - g_signal_emit (activity, signals[COMPLETED], 0); -} - -void -e_activity_clicked (EActivity *activity) -{ - g_return_if_fail (E_IS_ACTIVITY (activity)); - - g_signal_emit (activity, signals[CLICKED], 0); -} - gchar * e_activity_describe (EActivity *activity) { @@ -470,14 +345,6 @@ e_activity_describe (EActivity *activity) return class->describe (activity); } -gboolean -e_activity_is_completed (EActivity *activity) -{ - g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE); - - return activity->priv->completed; -} - GCancellable * e_activity_get_cancellable (EActivity *activity) { @@ -506,11 +373,6 @@ e_activity_set_cancellable (EActivity *activity, 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)) @@ -521,25 +383,6 @@ e_activity_set_cancellable (EActivity *activity, g_object_notify (G_OBJECT (activity), "cancellable"); } -gboolean -e_activity_get_clickable (EActivity *activity) -{ - g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE); - - return activity->priv->clickable; -} - -void -e_activity_set_clickable (EActivity *activity, - gboolean clickable) -{ - g_return_if_fail (E_IS_ACTIVITY (activity)); - - activity->priv->clickable = clickable; - - g_object_notify (G_OBJECT (activity), "clickable"); -} - const gchar * e_activity_get_icon_name (EActivity *activity) { @@ -579,42 +422,42 @@ e_activity_set_percent (EActivity *activity, g_object_notify (G_OBJECT (activity), "percent"); } -const gchar * -e_activity_get_primary_text (EActivity *activity) +EActivityState +e_activity_get_state (EActivity *activity) { - g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL); + g_return_val_if_fail (E_IS_ACTIVITY (activity), 0); - return activity->priv->primary_text; + return activity->priv->state; } void -e_activity_set_primary_text (EActivity *activity, - const gchar *primary_text) +e_activity_set_state (EActivity *activity, + EActivityState state) { g_return_if_fail (E_IS_ACTIVITY (activity)); - g_free (activity->priv->primary_text); - activity->priv->primary_text = g_strdup (primary_text); + activity->priv->state = state; - g_object_notify (G_OBJECT (activity), "primary-text"); + g_object_notify (G_OBJECT (activity), "state"); } const gchar * -e_activity_get_secondary_text (EActivity *activity) +e_activity_get_text (EActivity *activity) { g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL); - return activity->priv->secondary_text; + return activity->priv->text; } void -e_activity_set_secondary_text (EActivity *activity, - const gchar *secondary_text) +e_activity_set_text (EActivity *activity, + const gchar *text) { g_return_if_fail (E_IS_ACTIVITY (activity)); - g_free (activity->priv->secondary_text); - activity->priv->secondary_text = g_strdup (secondary_text); + g_free (activity->priv->text); + activity->priv->text = g_strdup (text); - g_object_notify (G_OBJECT (activity), "secondary-text"); + g_object_notify (G_OBJECT (activity), "text"); } + diff --git a/e-util/e-activity.h b/e-util/e-activity.h index 4573fada57..63195b770a 100644 --- a/e-util/e-activity.h +++ b/e-util/e-activity.h @@ -23,6 +23,7 @@ #define E_ACTIVITY_H #include <gtk/gtk.h> +#include <e-util/e-util-enums.h> /* Standard GObject macros */ #define E_TYPE_ACTIVITY \ @@ -57,10 +58,7 @@ struct _EActivity { struct _EActivityClass { GObjectClass parent_class; - /* Signals */ - void (*cancelled) (EActivity *activity); - void (*completed) (EActivity *activity); - void (*clicked) (EActivity *activity); + /* Methods */ gchar * (*describe) (EActivity *activity); }; @@ -68,28 +66,22 @@ GType e_activity_get_type (void); EActivity * e_activity_new (void); EActivity * e_activity_newv (const gchar *format, ...) G_GNUC_PRINTF (1, 2); -void e_activity_complete (EActivity *activity); -void e_activity_clicked (EActivity *activity); gchar * e_activity_describe (EActivity *activity); -gboolean e_activity_is_completed (EActivity *activity); 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); const gchar * e_activity_get_icon_name (EActivity *activity); void e_activity_set_icon_name (EActivity *activity, const gchar *icon_name); gdouble e_activity_get_percent (EActivity *activity); void e_activity_set_percent (EActivity *activity, gdouble percent); -const gchar * e_activity_get_primary_text (EActivity *activity); -void e_activity_set_primary_text (EActivity *activity, - const gchar *primary_text); -const gchar * e_activity_get_secondary_text (EActivity *activity); -void e_activity_set_secondary_text (EActivity *activity, - const gchar *secondary_text); +EActivityState e_activity_get_state (EActivity *activity); +void e_activity_set_state (EActivity *activity, + EActivityState state); +const gchar * e_activity_get_text (EActivity *activity); +void e_activity_set_text (EActivity *activity, + const gchar *text); G_END_DECLS diff --git a/e-util/e-file-utils.c b/e-util/e-file-utils.c index e647b8deb1..2d5ff30ff7 100644 --- a/e-util/e-file-utils.c +++ b/e-util/e-file-utils.c @@ -51,40 +51,56 @@ #include <glib/gstdio.h> #include <glib/gi18n-lib.h> +#include "e-activity.h" #include "e-file-utils.h" -#include "e-io-activity.h" + +typedef struct _AsyncContext AsyncContext; + +struct _AsyncContext { + EActivity *activity; + gchar *new_etag; +}; + +static void +async_context_free (AsyncContext *context) +{ + if (context->activity != NULL) + g_object_unref (context->activity); + + g_free (context->new_etag); + + g_slice_free (AsyncContext, context); +} static void file_replace_contents_cb (GFile *file, GAsyncResult *result, - EActivity *activity) + GSimpleAsyncResult *simple) { - gchar *new_etag; - gboolean success; + AsyncContext *context; + gchar *new_etag = NULL; GError *error = NULL; - success = g_file_replace_contents_finish ( - file, result, &new_etag, &error); + context = g_simple_async_result_get_op_res_gpointer (simple); - result = e_io_activity_get_async_result (E_IO_ACTIVITY (activity)); + g_file_replace_contents_finish (file, result, &new_etag, &error); - if (error == NULL) { - g_object_set_data_full ( - G_OBJECT (result), - "__new_etag__", new_etag, - (GDestroyNotify) g_free); - } else { - g_simple_async_result_set_from_error ( - G_SIMPLE_ASYNC_RESULT (result), error); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + e_activity_set_state (context->activity, E_ACTIVITY_CANCELLED); + else + e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED); + + if (error == NULL) + context->new_etag = new_etag; + else { + g_warn_if_fail (new_etag == NULL); + g_simple_async_result_set_from_error (simple, error); g_error_free (error); } - g_simple_async_result_set_op_res_gboolean ( - G_SIMPLE_ASYNC_RESULT (result), success); - - e_activity_complete (activity); + g_simple_async_result_complete (simple); - g_object_unref (activity); + g_object_unref (simple); } /** @@ -115,9 +131,9 @@ e_file_replace_contents_async (GFile *file, GAsyncReadyCallback callback, gpointer user_data) { - EActivity *activity; GSimpleAsyncResult *simple; GCancellable *cancellable; + AsyncContext *context; const gchar *format; gchar *description; gchar *basename; @@ -148,21 +164,26 @@ e_file_replace_contents_async (GFile *file, cancellable = g_cancellable_new (); + context = g_slice_new0 (AsyncContext); + context->activity = e_activity_new (); + + e_activity_set_text (context->activity, description); + e_activity_set_cancellable (context->activity, cancellable); + simple = g_simple_async_result_new ( G_OBJECT (file), callback, user_data, e_file_replace_contents_async); - activity = e_io_activity_new ( - description, G_ASYNC_RESULT (simple), cancellable); + g_simple_async_result_set_op_res_gpointer ( + simple, context, (GDestroyNotify) async_context_free); g_file_replace_contents_async ( file, contents, length, etag, make_backup, flags, cancellable, (GAsyncReadyCallback) file_replace_contents_cb, - activity); + simple); g_object_unref (cancellable); - g_object_unref (simple); g_free (description); g_free (basename); @@ -170,7 +191,7 @@ e_file_replace_contents_async (GFile *file, g_free (hostname); g_free (uri); - return activity; + return context->activity; } /** @@ -194,18 +215,19 @@ e_file_replace_contents_finish (GFile *file, GError **error) { GSimpleAsyncResult *simple; + AsyncContext *context; g_return_val_if_fail (G_IS_FILE (file), FALSE); g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE); simple = G_SIMPLE_ASYNC_RESULT (result); + context = g_simple_async_result_get_op_res_gpointer (simple); if (g_simple_async_result_propagate_error (simple, error)) return FALSE; if (new_etag != NULL) - *new_etag = g_object_steal_data ( - G_OBJECT (result), "__new_etag__"); + *new_etag = g_strdup (context->new_etag); return TRUE; } diff --git a/e-util/e-io-activity.c b/e-util/e-io-activity.c deleted file mode 100644 index e519fea18b..0000000000 --- a/e-util/e-io-activity.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * e-io-activity.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-io-activity.h" - -#define E_IO_ACTIVITY_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_IO_ACTIVITY, EIOActivityPrivate)) - -struct _EIOActivityPrivate { - GAsyncResult *async_result; -}; - -enum { - PROP_0, - PROP_ASYNC_RESULT -}; - -G_DEFINE_TYPE ( - EIOActivity, - e_io_activity, - E_TYPE_ACTIVITY) - -static void -io_activity_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_ASYNC_RESULT: - e_io_activity_set_async_result ( - E_IO_ACTIVITY (object), - g_value_get_object (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -io_activity_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_ASYNC_RESULT: - g_value_set_object ( - value, e_io_activity_get_async_result ( - E_IO_ACTIVITY (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -io_activity_dispose (GObject *object) -{ - EIOActivityPrivate *priv; - - priv = E_IO_ACTIVITY_GET_PRIVATE (object); - - if (priv->async_result != NULL) { - g_object_unref (priv->async_result); - priv->async_result = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (e_io_activity_parent_class)->dispose (object); -} - -static void -io_activity_completed (EActivity *activity) -{ - EIOActivity *io_activity; - GAsyncResult *async_result; - - /* Chain up to parent's completed() method. */ - E_ACTIVITY_CLASS (e_io_activity_parent_class)->completed (activity); - - io_activity = E_IO_ACTIVITY (activity); - async_result = e_io_activity_get_async_result (io_activity); - - /* We know how to invoke a GSimpleAsyncResult. For any other - * type of GAsyncResult the caller will have to take measures - * to invoke it himself. */ - if (G_IS_SIMPLE_ASYNC_RESULT (async_result)) - g_simple_async_result_complete ( - G_SIMPLE_ASYNC_RESULT (async_result)); -} - -static void -e_io_activity_class_init (EIOActivityClass *class) -{ - GObjectClass *object_class; - EActivityClass *activity_class; - - g_type_class_add_private (class, sizeof (EIOActivityPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = io_activity_set_property; - object_class->get_property = io_activity_get_property; - object_class->dispose = io_activity_dispose; - - activity_class = E_ACTIVITY_CLASS (class); - activity_class->completed = io_activity_completed; - - g_object_class_install_property ( - object_class, - PROP_ASYNC_RESULT, - g_param_spec_object ( - "async-result", - "Asynchronous Result", - NULL, - G_TYPE_ASYNC_RESULT, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); -} - -static void -e_io_activity_init (EIOActivity *io_activity) -{ - io_activity->priv = E_IO_ACTIVITY_GET_PRIVATE (io_activity); -} - -EActivity * -e_io_activity_new (const gchar *primary_text, - GAsyncResult *async_result, - GCancellable *cancellable) -{ - g_return_val_if_fail (primary_text != NULL, NULL); - - if (async_result != NULL) - g_return_val_if_fail (G_IS_ASYNC_RESULT (async_result), NULL); - - if (cancellable != NULL) - g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), NULL); - - return g_object_new ( - E_TYPE_IO_ACTIVITY, - "async-result", async_result, "cancellable", - cancellable, "primary-text", primary_text, NULL); -} - -GAsyncResult * -e_io_activity_get_async_result (EIOActivity *io_activity) -{ - g_return_val_if_fail (E_IS_IO_ACTIVITY (io_activity), NULL); - - return io_activity->priv->async_result; -} - -void -e_io_activity_set_async_result (EIOActivity *io_activity, - GAsyncResult *async_result) -{ - g_return_if_fail (E_IS_IO_ACTIVITY (io_activity)); - - if (async_result != NULL) { - g_return_if_fail (G_IS_ASYNC_RESULT (async_result)); - g_object_ref (async_result); - } - - if (io_activity->priv->async_result != NULL) - g_object_unref (io_activity->priv->async_result); - - io_activity->priv->async_result = async_result; - - g_object_notify (G_OBJECT (io_activity), "async-result"); -} - diff --git a/e-util/e-io-activity.h b/e-util/e-io-activity.h deleted file mode 100644 index 20a7a06082..0000000000 --- a/e-util/e-io-activity.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * e-io-activity.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_IO_ACTIVITY_H -#define E_IO_ACTIVITH_H - -#include <gio/gio.h> -#include <e-util/e-activity.h> - -/* Standard GObject macros */ -#define E_TYPE_IO_ACTIVITY \ - (e_io_activity_get_type ()) -#define E_IO_ACTIVITY(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_IO_ACTIVITY, EIOActivity)) -#define E_IO_ACTIVITY_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_IO_ACTIVITY, EIOActivityClass)) -#define E_IS_IO_ACTIVITY(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_IO_ACTIVITY)) -#define E_IS_IO_ACTIVITY_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_IO_ACTIVITY)) -#define E_IS_IO_ACTIVITY_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_IO_ACTIVITY, EIOActivityClass)) - -G_BEGIN_DECLS - -typedef struct _EIOActivity EIOActivity; -typedef struct _EIOActivityClass EIOActivityClass; -typedef struct _EIOActivityPrivate EIOActivityPrivate; - -struct _EIOActivity { - EActivity parent; - EIOActivityPrivate *priv; -}; - -struct _EIOActivityClass { - EActivityClass parent_class; -}; - -GType e_io_activity_get_type (void); -EActivity * e_io_activity_new (const gchar *primary_text, - GAsyncResult *async_result, - GCancellable *cancellable); -GAsyncResult * e_io_activity_get_async_result (EIOActivity *io_activity); -void e_io_activity_set_async_result (EIOActivity *io_activity, - GAsyncResult *async_result); - -G_END_DECLS - -#endif /* E_IO_ACTIVITY_H */ diff --git a/e-util/e-util-enums.h b/e-util/e-util-enums.h new file mode 100644 index 0000000000..bcf214ea33 --- /dev/null +++ b/e-util/e-util-enums.h @@ -0,0 +1,35 @@ +/* + * e-util-enums.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + */ + +#ifndef E_UTIL_ENUMS_H +#define E_UTIL_ENUMS_H + +#include <glib.h> + +G_BEGIN_DECLS + +typedef enum { + E_ACTIVITY_RUNNING, + E_ACTIVITY_WAITING, + E_ACTIVITY_CANCELLED, + E_ACTIVITY_COMPLETED +} EActivityState; + +G_END_DECLS + +#endif /* E_UTIL_ENUMS_H */ diff --git a/e-util/e-util.h b/e-util/e-util.h index 9aa24f3d87..d4f29c9c34 100644 --- a/e-util/e-util.h +++ b/e-util/e-util.h @@ -29,6 +29,7 @@ #include <gconf/gconf-client.h> #include <e-util/e-marshal.h> +#include <e-util/e-util-enums.h> /* e_get_user_data_dir() used to live here, so #include its new home * for backward-compatibility (not that we really care about that). */ diff --git a/mail/e-mail-session.c b/mail/e-mail-session.c index 23076807b3..7b726cfec5 100644 --- a/mail/e-mail-session.c +++ b/mail/e-mail-session.c @@ -96,7 +96,9 @@ enum { static gchar *mail_data_dir; static gchar *mail_config_dir; +#if 0 static MailMsgInfo ms_thread_info_dummy = { sizeof (MailMsg) }; +#endif G_DEFINE_TYPE ( EMailSession, @@ -120,7 +122,9 @@ struct _user_message_msg { guint ismain:1; }; -static void user_message_exec (struct _user_message_msg *m); +static void user_message_exec (struct _user_message_msg *m, + GCancellable *cancellable, + GError **error); static void user_message_response_free (GtkDialog *dialog, @@ -133,8 +137,11 @@ user_message_response_free (GtkDialog *dialog, /* check for pendings */ if (!g_queue_is_empty (&user_message_queue)) { + GCancellable *cancellable; + m = g_queue_pop_head (&user_message_queue); - user_message_exec (m); + cancellable = e_activity_get_cancellable (m->base.activity); + user_message_exec (m, cancellable, &m->base.error); mail_msg_unref (m); } } @@ -155,7 +162,9 @@ user_message_response (GtkDialog *dialog, } static void -user_message_exec (struct _user_message_msg *m) +user_message_exec (struct _user_message_msg *m, + GCancellable *cancellable, + GError **error) { GtkWindow *parent; const gchar *error_type; @@ -716,6 +725,7 @@ mail_session_alert_user (CamelSession *session, gboolean cancel) { struct _user_message_msg *m; + GCancellable *cancellable; gboolean result = TRUE; m = mail_msg_new (&user_message_info); @@ -728,8 +738,10 @@ mail_session_alert_user (CamelSession *session, if (cancel) mail_msg_ref (m); + cancellable = e_activity_get_cancellable (m->base.activity); + if (m->ismain) - user_message_exec (m); + user_message_exec (m, cancellable, &m->base.error); else mail_msg_main_loop_push (m); @@ -788,6 +800,7 @@ mail_session_thread_msg_new (CamelSession *session, session_class = CAMEL_SESSION_CLASS (e_mail_session_parent_class); msg = session_class->thread_msg_new (session, ops, size); +#if 0 /* We create a dummy mail_msg, and then copy its cancellation * port over to ours, so we get cancellation and progress in * common with hte existing mail code, for free. */ @@ -795,9 +808,10 @@ mail_session_thread_msg_new (CamelSession *session, MailMsg *m = mail_msg_new (&ms_thread_info_dummy); msg->data = m; - g_object_unref (msg->cancellable); - msg->cancellable = g_object_ref (m->cancellable); + e_activity_set_cancellable ( + m->activity, msg->cancellable); } +#endif return msg; } @@ -808,7 +822,9 @@ mail_session_thread_msg_free (CamelSession *session, { CamelSessionClass *session_class; +#if 0 mail_msg_unref (msg->data); +#endif /* Chain up to parent's thread_msg_free() method. */ session_class = CAMEL_SESSION_CLASS (e_mail_session_parent_class); @@ -821,8 +837,6 @@ mail_session_thread_status (CamelSession *session, const gchar *text, gint pc) { - /* This should never be called since we bypass it in alloc! */ - g_warn_if_reached (); } static gboolean diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c index 704bd2bd37..f084155362 100644 --- a/mail/em-composer-utils.c +++ b/mail/em-composer-utils.c @@ -482,6 +482,7 @@ composer_send_completed (EMailSession *session, /* Ignore cancellations. */ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + e_activity_set_state (context->activity, E_ACTIVITY_CANCELLED); g_error_free (error); goto exit; } @@ -495,7 +496,7 @@ composer_send_completed (EMailSession *session, goto exit; } - e_activity_complete (context->activity); + e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED); /* Wait for the EActivity's completion message to * time out and then destroy the composer window. */ @@ -625,13 +626,16 @@ composer_save_draft_complete (EMailSession *session, e_mail_session_handle_draft_headers_finish (session, result, &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + e_activity_set_state (context->activity, E_ACTIVITY_CANCELLED); g_error_free (error); - else if (error != NULL) { + } else if (error != NULL) { g_warning ("%s", error->message); g_error_free (error); - } + + } else + e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED); /* Encode the draft message we just saved into the EMsgComposer * as X-Evolution-Draft headers. The message will be marked for @@ -641,8 +645,6 @@ composer_save_draft_complete (EMailSession *session, context->composer, context->folder_uri, context->message_uid); - e_activity_complete (context->activity); - async_context_free (context); } diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c index 15cf4a5f35..b08da8c849 100644 --- a/mail/em-folder-tree.c +++ b/mail/em-folder-tree.c @@ -204,20 +204,24 @@ folder_tree_get_folder_info__desc (struct _EMFolderTreeGetFolderInfo *m) } static void -folder_tree_get_folder_info__exec (struct _EMFolderTreeGetFolderInfo *m) +folder_tree_get_folder_info__exec (struct _EMFolderTreeGetFolderInfo *m, + GCancellable *cancellable, + GError **error) { guint32 flags = m->flags | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; + GError *local_error = NULL; m->fi = camel_store_get_folder_info_sync ( - m->store, m->top, flags, - m->base.cancellable, &m->base.error); + m->store, m->top, flags, cancellable, &local_error); /* XXX POP3 stores always return an error because they have * no folder hierarchy to scan. Clear that error so the * user doesn't see it. */ - if (g_error_matches (m->base.error, + if (g_error_matches (local_error, CAMEL_STORE_ERROR, CAMEL_STORE_ERROR_NO_FOLDER)) - g_clear_error (&m->base.error); + g_error_free (local_error); + else if (local_error != NULL) + g_propagate_error (error, local_error); } static void @@ -1741,6 +1745,7 @@ folder_tree_drop_folder (struct _DragDataReceivedAsync *m) { CamelFolder *folder; CamelStore *parent_store; + GCancellable *cancellable; const gchar *full_name; const guchar *data; @@ -1748,9 +1753,11 @@ folder_tree_drop_folder (struct _DragDataReceivedAsync *m) d(printf(" * Drop folder '%s' onto '%s'\n", data, m->full_name)); + cancellable = e_activity_get_cancellable (m->base.activity); + folder = e_mail_session_uri_to_folder_sync ( m->session, (gchar *) data, 0, - m->base.cancellable, &m->base.error); + cancellable, &m->base.error); if (folder == NULL) return; @@ -1801,7 +1808,9 @@ folder_tree_drop_async__desc (struct _DragDataReceivedAsync *m) } static void -folder_tree_drop_async__exec (struct _DragDataReceivedAsync *m) +folder_tree_drop_async__exec (struct _DragDataReceivedAsync *m, + GCancellable *cancellable, + GError **error) { CamelFolder *folder; @@ -1811,19 +1820,18 @@ folder_tree_drop_async__exec (struct _DragDataReceivedAsync *m) folder_tree_drop_folder (m); } else if (m->full_name == NULL) { g_set_error ( - &m->base.error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, + error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot drop message(s) into toplevel store")); } else if ((folder = camel_store_get_folder_sync ( - m->store, m->full_name, 0, - m->base.cancellable, &m->base.error))) { + m->store, m->full_name, 0, cancellable, error))) { switch (m->info) { case DND_DROP_TYPE_UID_LIST: /* import a list of uids from another evo folder */ em_utils_selection_get_uidlist ( m->selection, m->session, folder, m->move, - m->base.cancellable, &m->base.error); - m->moved = m->move && (m->base.error == NULL); + cancellable, error); + m->moved = m->move && (error == NULL); break; case DND_DROP_TYPE_MESSAGE_RFC822: /* import a message/rfc822 stream */ diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c index 82f3de6fcf..d457e90ecc 100644 --- a/mail/em-folder-utils.c +++ b/mail/em-folder-utils.c @@ -93,18 +93,23 @@ emft_copy_folders__desc (struct _EMCopyFolders *m, gint complete) } static void -emft_copy_folders__exec (struct _EMCopyFolders *m) +emft_copy_folders__exec (struct _EMCopyFolders *m, + GCancellable *cancellable, + GError **error) { - guint32 flags = CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; + guint32 flags; GList *pending = NULL, *deleting = NULL, *l; GString *fromname, *toname; CamelFolderInfo *fi; const gchar *tmp; gint fromlen; + flags = CAMEL_STORE_FOLDER_INFO_FAST | + CAMEL_STORE_FOLDER_INFO_RECURSIVE | + CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; + fi = camel_store_get_folder_info_sync ( - m->fromstore, m->frombase, flags, - m->base.cancellable, &m->base.error); + m->fromstore, m->frombase, flags, cancellable, error); if (fi == NULL) return; @@ -147,8 +152,8 @@ emft_copy_folders__exec (struct _EMCopyFolders *m) if (m->tostore == m->fromstore && m->delete) { camel_store_rename_folder_sync ( m->fromstore, info->full_name, toname->str, - m->base.cancellable, &m->base.error); - if (m->base.error != NULL) + cancellable, error); + if (error != NULL) goto exception; /* this folder no longer exists, unsubscribe it */ @@ -160,15 +165,14 @@ emft_copy_folders__exec (struct _EMCopyFolders *m) } else { fromfolder = camel_store_get_folder_sync ( m->fromstore, info->full_name, 0, - m->base.cancellable, &m->base.error); + cancellable, error); if (fromfolder == NULL) goto exception; tofolder = camel_store_get_folder_sync ( m->tostore, toname->str, CAMEL_STORE_FOLDER_CREATE, - m->base.cancellable, - &m->base.error); + cancellable, error); if (tofolder == NULL) { g_object_unref (fromfolder); goto exception; @@ -178,11 +182,10 @@ emft_copy_folders__exec (struct _EMCopyFolders *m) camel_folder_transfer_messages_to_sync ( fromfolder, uids, tofolder, m->delete, NULL, - m->base.cancellable, - &m->base.error); + cancellable, error); camel_folder_free_uids (fromfolder, uids); - if (m->delete && m->base.error == NULL) + if (m->delete && error == NULL) camel_folder_synchronize_sync ( fromfolder, TRUE, NULL, NULL); @@ -192,7 +195,7 @@ emft_copy_folders__exec (struct _EMCopyFolders *m) } } - if (m->base.error != NULL) + if (error != NULL) goto exception; else if (m->delete && !deleted) deleting = g_list_prepend (deleting, info); @@ -569,18 +572,17 @@ emfu_create_folder__desc (struct _EMCreateFolder *m) } static void -emfu_create_folder__exec (struct _EMCreateFolder *m) +emfu_create_folder__exec (struct _EMCreateFolder *m, + GCancellable *cancellable, + GError **error) { - d(printf ("creating folder parent='%s' name='%s' full_name='%s'\n", m->parent, m->name, m->full_name)); - if ((m->fi = camel_store_create_folder_sync ( - m->store, m->parent, m->name, - m->base.cancellable, &m->base.error))) { + m->store, m->parent, m->name, cancellable, error))) { if (camel_store_supports_subscriptions (m->store)) camel_store_subscribe_folder_sync ( m->store, m->full_name, - m->base.cancellable, &m->base.error); + cancellable, error); } } @@ -766,7 +768,9 @@ emfu_unsubscribe_folder__desc (struct _folder_unsub_t *msg) } static void -emfu_unsubscribe_folder__exec (struct _folder_unsub_t *msg) +emfu_unsubscribe_folder__exec (struct _folder_unsub_t *msg, + GCancellable *cancellable, + GError **error) { CamelStore *store; CamelURL *url; @@ -775,7 +779,7 @@ emfu_unsubscribe_folder__exec (struct _folder_unsub_t *msg) store = camel_session_get_store ( CAMEL_SESSION (msg->session), - msg->folder_uri, &msg->base.error); + msg->folder_uri, error); if (store == NULL) return; @@ -789,8 +793,7 @@ emfu_unsubscribe_folder__exec (struct _folder_unsub_t *msg) if (path != NULL) camel_store_unsubscribe_folder_sync ( - store, path, msg->base.cancellable, - &msg->base.error); + store, path, cancellable, error); camel_url_free (url); } diff --git a/mail/em-format-html.c b/mail/em-format-html.c index 1e3c6b9abd..de8c0b5961 100644 --- a/mail/em-format-html.c +++ b/mail/em-format-html.c @@ -166,7 +166,9 @@ efh_format_desc (struct _format_msg *m) } static void -efh_format_exec (struct _format_msg *m) +efh_format_exec (struct _format_msg *m, + GCancellable *cancellable, + GError **error) { EMFormat *format; struct _EMFormatHTMLJob *job; @@ -195,7 +197,7 @@ efh_format_exec (struct _format_msg *m) if (format->mode == EM_FORMAT_MODE_SOURCE) { em_format_format_source ( format, (CamelStream *) m->estream, - (CamelMimePart *) m->message, m->base.cancellable); + (CamelMimePart *) m->message, cancellable); } else { const EMFormatHandler *handle; const gchar *mime_type; @@ -207,7 +209,7 @@ efh_format_exec (struct _format_msg *m) handle->handler ( format, CAMEL_STREAM (m->estream), CAMEL_MIME_PART (m->message), handle, - m->base.cancellable, FALSE); + cancellable, FALSE); mime_type = "x-evolution/message/rfc822"; handle = em_format_find_handler (format, mime_type); @@ -216,10 +218,10 @@ efh_format_exec (struct _format_msg *m) handle->handler ( format, CAMEL_STREAM (m->estream), CAMEL_MIME_PART (m->message), handle, - m->base.cancellable, FALSE); + cancellable, FALSE); } - camel_stream_flush ((CamelStream *)m->estream, m->base.cancellable, NULL); + camel_stream_flush ((CamelStream *)m->estream, cancellable, NULL); puri_level = format->pending_uri_level; base = format->base; @@ -232,13 +234,13 @@ efh_format_exec (struct _format_msg *m) /* This is an implicit check to see if the gtkhtml has been destroyed */ if (m->format->priv->web_view == NULL) - g_cancellable_cancel (m->base.cancellable); + g_cancellable_cancel (cancellable); /* call jobs even if cancelled, so they can clean up resources */ format->pending_uri_level = job->puri_level; if (job->base) format->base = job->base; - job->callback (job, m->base.cancellable); + job->callback (job, cancellable); format->base = base; /* clean up the job */ @@ -257,8 +259,8 @@ efh_format_exec (struct _format_msg *m) d(printf("out of jobs, closing root stream\n")); camel_stream_write_string ( (CamelStream *) m->estream, - "</body>\n</html>\n", m->base.cancellable, NULL); - camel_stream_close ((CamelStream *)m->estream, m->base.cancellable, NULL); + "</body>\n</html>\n", cancellable, NULL); + camel_stream_close ((CamelStream *)m->estream, cancellable, NULL); g_object_unref (m->estream); m->estream = NULL; } @@ -287,7 +289,7 @@ efh_format_free (struct _format_msg *m) d(printf("formatter freed\n")); g_object_unref (m->format); if (m->estream) { - camel_stream_close ((CamelStream *)m->estream, m->base.cancellable, NULL); + camel_stream_close ((CamelStream *)m->estream, NULL, NULL); g_object_unref (m->estream); } if (m->folder) diff --git a/mail/importers/elm-importer.c b/mail/importers/elm-importer.c index 18548fc21b..292d7c3ffe 100644 --- a/mail/importers/elm-importer.c +++ b/mail/importers/elm-importer.c @@ -184,7 +184,9 @@ static MailImporterSpecial elm_special_folders[] = { }; static void -elm_import_exec (struct _elm_import_msg *m) +elm_import_exec (struct _elm_import_msg *m, + GCancellable *cancellable, + GError **error) { EShell *shell; EShellBackend *shell_backend; diff --git a/mail/importers/mail-importer.c b/mail/importers/mail-importer.c index b4fb3c0431..7eaed4759e 100644 --- a/mail/importers/mail-importer.c +++ b/mail/importers/mail-importer.c @@ -107,7 +107,9 @@ decode_mozilla_status (const gchar *tmp) } static void -import_mbox_exec (struct _import_mbox_msg *m) +import_mbox_exec (struct _import_mbox_msg *m, + GCancellable *cancellable, + GError **error) { CamelFolder *folder; CamelMimeParser *mp = NULL; @@ -125,7 +127,7 @@ import_mbox_exec (struct _import_mbox_msg *m) else folder = e_mail_session_uri_to_folder_sync ( m->session, m->uri, CAMEL_STORE_FOLDER_CREATE, - m->base.cancellable, &m->base.error); + cancellable, error); if (folder == NULL) return; @@ -144,7 +146,7 @@ import_mbox_exec (struct _import_mbox_msg *m) } camel_operation_push_message ( - m->base.cancellable, _("Importing '%s'"), + cancellable, _("Importing '%s'"), camel_folder_get_full_name (folder)); camel_folder_freeze (folder); while (camel_mime_parser_step (mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM) { @@ -155,7 +157,7 @@ import_mbox_exec (struct _import_mbox_msg *m) if (st.st_size > 0) pc = (gint)(100.0 * ((double)camel_mime_parser_tell (mp) / (double)st.st_size)); - camel_operation_progress (m->base.cancellable, pc); + camel_operation_progress (cancellable, pc); msg = camel_mime_message_new (); if (!camel_mime_part_construct_from_parser_sync ( @@ -180,11 +182,11 @@ import_mbox_exec (struct _import_mbox_msg *m) camel_message_info_set_flags (info, flags, ~0); camel_folder_append_message_sync ( folder, msg, info, NULL, - m->base.cancellable, &m->base.error); + cancellable, error); camel_message_info_free (info); g_object_unref (msg); - if (m->base.error != NULL) + if (error != NULL) break; camel_mime_parser_step (mp, NULL, NULL); @@ -192,7 +194,7 @@ import_mbox_exec (struct _import_mbox_msg *m) /* FIXME Not passing a GCancellable or GError here. */ camel_folder_synchronize_sync (folder, FALSE, NULL, NULL); camel_folder_thaw (folder); - camel_operation_pop_message (m->base.cancellable); + camel_operation_pop_message (cancellable); /* TODO: these api's are a bit weird, registering the old is the same as deregistering */ fail2: g_object_unref (mp); @@ -267,9 +269,11 @@ mail_importer_import_mbox_sync (EMailSession *session, m->path = g_strdup (path); m->uri = g_strdup (folderuri); if (cancellable) - m->cancellable = g_object_ref (cancellable); + e_activity_set_cancellable (m->base.activity, cancellable); + + cancellable = e_activity_get_cancellable (m->base.activity); - import_mbox_exec (m); + import_mbox_exec (m, cancellable, &m->base.error); import_mbox_done (m); mail_msg_unref (m); } diff --git a/mail/importers/pine-importer.c b/mail/importers/pine-importer.c index 26a37b853e..e7ace0b1b5 100644 --- a/mail/importers/pine-importer.c +++ b/mail/importers/pine-importer.c @@ -230,7 +230,9 @@ static MailImporterSpecial pine_special_folders[] = { }; static void -pine_import_exec (struct _pine_import_msg *m) +pine_import_exec (struct _pine_import_msg *m, + GCancellable *cancellable, + GError **error) { EShell *shell; EShellBackend *shell_backend; diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c index 85b60ad364..8b19da4879 100644 --- a/mail/mail-folder-cache.c +++ b/mail/mail-folder-cache.c @@ -795,7 +795,9 @@ ping_store_desc (struct _ping_store_msg *m) } static void -ping_store_exec (struct _ping_store_msg *m) +ping_store_exec (struct _ping_store_msg *m, + GCancellable *cancellable, + GError **error) { gboolean online = FALSE; @@ -810,8 +812,7 @@ ping_store_exec (struct _ping_store_msg *m) online = TRUE; } if (online) - camel_store_noop_sync ( - m->store, m->base.cancellable, &m->base.error); + camel_store_noop_sync (m->store, cancellable, error); } static void diff --git a/mail/mail-mt.c b/mail/mail-mt.c index 907d57938a..8e507e46fc 100644 --- a/mail/mail-mt.c +++ b/mail/mail-mt.c @@ -38,11 +38,6 @@ * to rework or get rid of the functions that use this. */ const gchar *shell_builtin_backend = "mail"; -/* background operation status stuff */ -struct _MailMsgPrivate { - EActivity *activity; -}; - static guint mail_msg_seq; /* sequence number of each message */ /* Table of active messages. Must hold mail_msg_lock to access. */ @@ -76,6 +71,7 @@ gpointer mail_msg_new (MailMsgInfo *info) { MailMsg *msg; + GCancellable *cancellable; g_mutex_lock (mail_msg_lock); @@ -83,22 +79,20 @@ mail_msg_new (MailMsgInfo *info) msg->info = info; msg->ref_count = 1; msg->seq = mail_msg_seq++; - msg->cancellable = camel_operation_new (); - - msg->priv = g_slice_new0 (MailMsgPrivate); - msg->priv->activity = e_activity_new (); + msg->activity = e_activity_new (); - e_activity_set_percent (msg->priv->activity, 0.0); + cancellable = camel_operation_new (); - e_activity_set_cancellable ( - msg->priv->activity, - G_CANCELLABLE (msg->cancellable)); + e_activity_set_percent (msg->activity, 0.0); + e_activity_set_cancellable (msg->activity, cancellable); g_signal_connect ( - msg->cancellable, "cancelled", + cancellable, "cancelled", G_CALLBACK (mail_msg_cancelled), GINT_TO_POINTER (msg->seq)); + g_object_unref (cancellable); + g_hash_table_insert ( mail_msg_active_table, GINT_TO_POINTER (msg->seq), msg); @@ -145,18 +139,12 @@ mail_msg_free (MailMsg *mail_msg) shell_backend = e_shell_get_backend_by_name ( shell, shell_builtin_backend); - if (mail_msg->priv->activity != NULL) { - e_activity_complete (mail_msg->priv->activity); - g_object_unref (mail_msg->priv->activity); - } - - if (mail_msg->cancellable != NULL) - g_object_unref (mail_msg->cancellable); + if (mail_msg->activity != NULL) + g_object_unref (mail_msg->activity); if (mail_msg->error != NULL) g_error_free (mail_msg->error); - g_slice_free (MailMsgPrivate, mail_msg->priv); g_slice_free1 (mail_msg->info->size, mail_msg); return FALSE; @@ -226,9 +214,21 @@ mail_msg_check_error (gpointer msg) checkmem (m->priv); #endif - if (m->error == NULL - || g_error_matches (m->error, G_IO_ERROR, G_IO_ERROR_CANCELLED) - || g_error_matches (m->error, CAMEL_FOLDER_ERROR, CAMEL_FOLDER_ERROR_INVALID_UID)) + if (g_error_matches (m->error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + e_activity_set_state (m->activity, E_ACTIVITY_CANCELLED); + return; + } + + e_activity_set_state (m->activity, E_ACTIVITY_COMPLETED); + + if (m->error == NULL) + return; + + /* XXX Hmm, no explanation of why this is needed. It looks like + * a lame hack and will be removed at some point, if only to + * reintroduce whatever issue made this necessary so we can + * document it the source code this time. */ + if (g_error_matches (m->error, CAMEL_FOLDER_ERROR, CAMEL_FOLDER_ERROR_INVALID_UID)) return; shell = e_shell_get_default (); @@ -250,8 +250,7 @@ mail_msg_check_error (gpointer msg) shell_window, shell_builtin_backend); shell_content = e_shell_view_get_shell_content (shell_view); - if (m->info->desc - && (what = m->info->desc (m))) { + if (m->info->desc && (what = m->info->desc (m))) { e_alert_submit ( GTK_WIDGET (shell_content), "mail:async-error", what, @@ -277,8 +276,13 @@ mail_msg_cancel (guint msgid) /* Hold a reference to the GCancellable so it doesn't finalize * itself on us between unlocking the mutex and cancelling. */ - if (msg != NULL && !g_cancellable_is_cancelled (msg->cancellable)) - cancellable = g_object_ref (msg->cancellable); + if (msg != NULL) { + cancellable = e_activity_get_cancellable (msg->activity); + if (g_cancellable_is_cancelled (cancellable)) + cancellable = NULL; + else + g_object_ref (cancellable); + } g_mutex_unlock (mail_msg_lock); @@ -368,13 +372,17 @@ 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) { + GCancellable *cancellable; + + cancellable = e_activity_get_cancellable (msg->activity); + g_idle_add_full ( G_PRIORITY_DEFAULT, (GSourceFunc) mail_msg_submit, - g_object_ref (msg->priv->activity), + g_object_ref (msg->activity), (GDestroyNotify) g_object_unref); if (msg->info->exec != NULL) - msg->info->exec (msg); + msg->info->exec (msg, cancellable, &msg->error); if (msg->info->done != NULL) msg->info->done (msg); mail_msg_unref (msg); @@ -393,23 +401,27 @@ mail_msg_idle_cb (void) static void mail_msg_proxy (MailMsg *msg) { + GCancellable *cancellable; + + cancellable = e_activity_get_cancellable (msg->activity); + if (msg->info->desc != NULL) { gchar *text = msg->info->desc (msg); - camel_operation_push_message (msg->cancellable, "%s", text); + camel_operation_push_message (cancellable, "%s", text); g_free (text); } g_idle_add_full ( G_PRIORITY_DEFAULT, (GSourceFunc) mail_msg_submit, - g_object_ref (msg->priv->activity), + g_object_ref (msg->activity), (GDestroyNotify) g_object_unref); if (msg->info->exec != NULL) - msg->info->exec (msg); + msg->info->exec (msg, cancellable, &msg->error); if (msg->info->desc != NULL) - camel_operation_pop_message (msg->cancellable); + camel_operation_pop_message (cancellable); g_async_queue_push (msg_reply_queue, msg); @@ -522,7 +534,9 @@ struct _call_msg { }; static void -do_call (struct _call_msg *m) +do_call (struct _call_msg *m, + GCancellable *cancellable, + GError **error) { gpointer p1, *p2, *p3, *p4, *p5; gint i1; @@ -572,6 +586,11 @@ do_call (struct _call_msg *m) break; } + e_activity_set_state ( + m->base.activity, + g_cancellable_is_cancelled (cancellable) ? + E_ACTIVITY_CANCELLED : E_ACTIVITY_COMPLETED); + if (m->done != NULL) e_flag_set (m->done); } @@ -587,6 +606,7 @@ static MailMsgInfo mail_call_info = { gpointer mail_call_main (mail_call_t type, MailMainFunc func, ...) { + GCancellable *cancellable; struct _call_msg *m; gpointer ret; va_list ap; @@ -598,8 +618,10 @@ mail_call_main (mail_call_t type, MailMainFunc func, ...) m->func = func; G_VA_COPY (m->ap, ap); + cancellable = e_activity_get_cancellable (m->base.activity); + if (mail_in_main_thread ()) - do_call (m); + do_call (m, cancellable, &m->base.error); else { mail_msg_ref (m); m->done = e_flag_new (); diff --git a/mail/mail-mt.h b/mail/mail-mt.h index 122519162b..0b595072b6 100644 --- a/mail/mail-mt.h +++ b/mail/mail-mt.h @@ -24,25 +24,26 @@ #define _MAIL_MT #include <camel/camel.h> +#include <e-util/e-activity.h> typedef struct _MailMsg MailMsg; typedef struct _MailMsgInfo MailMsgInfo; -typedef struct _MailMsgPrivate MailMsgPrivate; -typedef gchar * (*MailMsgDescFunc) (MailMsg *msg); -typedef void (*MailMsgExecFunc) (MailMsg *msg); -typedef void (*MailMsgDoneFunc) (MailMsg *msg); -typedef void (*MailMsgFreeFunc) (MailMsg *msg); -typedef void (*MailMsgDispatchFunc) (gpointer msg); +typedef gchar * (*MailMsgDescFunc) (MailMsg *msg); +typedef void (*MailMsgExecFunc) (MailMsg *msg, + GCancellable *cancellable, + GError **error); +typedef void (*MailMsgDoneFunc) (MailMsg *msg); +typedef void (*MailMsgFreeFunc) (MailMsg *msg); +typedef void (*MailMsgDispatchFunc) (gpointer msg); struct _MailMsg { MailMsgInfo *info; volatile gint ref_count; guint seq; /* seq number for synchronisation */ gint priority; /* priority (default = 0) */ - GCancellable *cancellable; /* a cancellation/status handle */ + EActivity *activity; GError *error; /* up to the caller to use this */ - MailMsgPrivate *priv; }; struct _MailMsgInfo { diff --git a/mail/mail-ops.c b/mail/mail-ops.c index 2cdce4c598..ce219ed372 100644 --- a/mail/mail-ops.c +++ b/mail/mail-ops.c @@ -88,7 +88,9 @@ em_filter_folder_element_desc (struct _filter_mail_msg *m) /* filter a folder, or a subset thereof, uses source_folder/source_uids */ /* this is shared with fetch_mail */ static void -em_filter_folder_element_exec (struct _filter_mail_msg *m) +em_filter_folder_element_exec (struct _filter_mail_msg *m, + GCancellable *cancellable, + GError **error) { CamelFolder *folder; GPtrArray *uids, *folder_uids = NULL; @@ -112,8 +114,8 @@ em_filter_folder_element_exec (struct _filter_mail_msg *m) camel_filter_driver_filter_folder ( m->driver, folder, m->cache, uids, m->delete, - m->base.cancellable, &m->base.error); - camel_filter_driver_flush (m->driver, &m->base.error); + cancellable, error); + camel_filter_driver_flush (m->driver, error); if (folder_uids) camel_folder_free_uids (folder, folder_uids); @@ -121,7 +123,7 @@ em_filter_folder_element_exec (struct _filter_mail_msg *m) /* sync our source folder */ if (!m->cache) camel_folder_synchronize_sync ( - folder, FALSE, m->base.cancellable, &m->base.error); + folder, FALSE, cancellable, error); camel_folder_thaw (folder); if (m->destination) @@ -225,7 +227,9 @@ fetch_mail_desc (struct _fetch_mail_msg *m) } static void -fetch_mail_exec (struct _fetch_mail_msg *m) +fetch_mail_exec (struct _fetch_mail_msg *m, + GCancellable *cancellable, + GError **error) { struct _filter_mail_msg *fm = (struct _filter_mail_msg *)m; gint i; @@ -238,18 +242,18 @@ fetch_mail_exec (struct _fetch_mail_msg *m) /* FIXME: this should support keep_on_server too, which would then perform a spool access thingy, right? problem is matching raw messages to uid's etc. */ if (!strncmp (m->source_uri, "mbox:", 5)) { - gchar *path = mail_tool_do_movemail (m->source_uri, &fm->base.error); + gchar *path = mail_tool_do_movemail (m->source_uri, error); - if (path && fm->base.error == NULL) { + if (path && error == NULL) { camel_folder_freeze (fm->destination); camel_filter_driver_set_default_folder ( fm->driver, fm->destination); camel_filter_driver_filter_mbox ( fm->driver, path, m->source_uri, - fm->base.cancellable, &fm->base.error); + cancellable, error); camel_folder_thaw (fm->destination); - if (fm->base.error == NULL) + if (error == NULL) g_unlink (path); } g_free (path); @@ -259,7 +263,7 @@ fetch_mail_exec (struct _fetch_mail_msg *m) folder = fm->source_folder = e_mail_session_get_inbox_sync ( fm->session, m->source_uri, - fm->base.cancellable, &fm->base.error); + cancellable, error); if (folder) { /* this handles 'keep on server' stuff, if we have any new uid's to copy @@ -287,7 +291,7 @@ fetch_mail_exec (struct _fetch_mail_msg *m) camel_uid_cache_free_uids (cache_uids); fm->cache = cache; - em_filter_folder_element_exec (fm); + em_filter_folder_element_exec (fm, cancellable, error); /* need to uncancel so writes/etc. don't fail */ if (g_cancellable_is_cancelled (m->cancellable)) @@ -297,7 +301,7 @@ fetch_mail_exec (struct _fetch_mail_msg *m) camel_uid_cache_save (cache); } - if (fm->delete && fm->base.error == NULL) { + if (fm->delete && error == NULL) { /* not keep on server - just delete all the actual messages on the server */ for (i=0;i<folder_uids->len;i++) { d(printf("force delete uid '%s'\n", (gchar *)folder_uids->pdata[i])); @@ -305,7 +309,7 @@ fetch_mail_exec (struct _fetch_mail_msg *m) } } - if ((fm->delete || cache_uids) && fm->base.error == NULL) { + if ((fm->delete || cache_uids) && error == NULL) { /* expunge messages (downloaded so far) */ /* FIXME Not passing a GCancellable or GError here. */ camel_folder_synchronize_sync ( @@ -315,7 +319,7 @@ fetch_mail_exec (struct _fetch_mail_msg *m) camel_uid_cache_destroy (cache); camel_folder_free_uids (folder, folder_uids); } else { - em_filter_folder_element_exec (fm); + em_filter_folder_element_exec (fm, cancellable, error); } /* we unref the source folder here since we @@ -444,7 +448,6 @@ struct _send_queue_msg { gchar *destination; CamelFilterDriver *driver; - GCancellable *cancellable; /* we use camelfilterstatusfunc, even though its not the filter doing it */ CamelFilterStatusFunc *status; @@ -732,7 +735,9 @@ report_status (struct _send_queue_msg *m, enum camel_filter_status_t status, gin } static void -send_queue_exec (struct _send_queue_msg *m) +send_queue_exec (struct _send_queue_msg *m, + GCancellable *cancellable, + GError **error) { CamelFolder *sent_folder; GPtrArray *uids, *send_uids = NULL; @@ -766,7 +771,7 @@ send_queue_exec (struct _send_queue_msg *m) return; } - camel_operation_push_message (m->cancellable, _("Sending message")); + camel_operation_push_message (cancellable, _("Sending message")); /* NB: This code somewhat abuses the 'exception' stuff. Apart from * fatal problems, it is also used as a mechanism to accumualte @@ -780,13 +785,12 @@ send_queue_exec (struct _send_queue_msg *m) _("Sending message %d of %d"), i+1, send_uids->len); - if (!m->cancellable) - camel_operation_progress ( - m->cancellable, (i+1) * 100 / send_uids->len); + camel_operation_progress ( + cancellable, (i+1) * 100 / send_uids->len); mail_send_message ( m, m->queue, send_uids->pdata[i], m->destination, - m->driver, m->base.cancellable, &local_error); + m->driver, cancellable, &local_error); if (local_error != NULL) { if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { /* merge exceptions into one */ @@ -846,7 +850,7 @@ send_queue_exec (struct _send_queue_msg *m) if (sent_folder) camel_folder_synchronize_sync (sent_folder, FALSE, NULL, NULL); - camel_operation_pop_message (m->cancellable); + camel_operation_pop_message (cancellable); } static void @@ -871,8 +875,6 @@ send_queue_free (struct _send_queue_msg *m) g_object_unref (m->driver); g_object_unref (m->queue); g_free (m->destination); - if (m->cancellable) - g_object_unref (m->cancellable); } static MailMsgInfo send_queue_info = { @@ -903,11 +905,8 @@ mail_send_queue (EMailSession *session, m->session = g_object_ref (session); m->queue = g_object_ref (queue); m->destination = g_strdup (destination); - if (G_IS_CANCELLABLE (cancellable)) { - m->cancellable = g_object_ref (cancellable); - g_object_unref (m->base.cancellable); - m->base.cancellable = NULL; - } + if (G_IS_CANCELLABLE (cancellable)) + e_activity_set_cancellable (m->base.activity, cancellable); m->status = status; m->status_data = status_data; m->done = done; @@ -941,7 +940,9 @@ append_mail_desc (struct _append_msg *m) } static void -append_mail_exec (struct _append_msg *m) +append_mail_exec (struct _append_msg *m, + GCancellable *cancellable, + GError **error) { camel_mime_message_set_date ( m->message, CAMEL_MESSAGE_DATE_CURRENT, 0); @@ -949,7 +950,7 @@ append_mail_exec (struct _append_msg *m) camel_folder_append_message_sync ( m->folder, m->message, m->info, &m->appended_uid, - m->base.cancellable, &m->base.error); + cancellable, error); } static void @@ -1029,13 +1030,15 @@ transfer_messages_desc (struct _transfer_msg *m) } static void -transfer_messages_exec (struct _transfer_msg *m) +transfer_messages_exec (struct _transfer_msg *m, + GCancellable *cancellable, + GError **error) { CamelFolder *dest; dest = e_mail_session_uri_to_folder_sync ( m->session, m->dest_uri, m->dest_flags, - m->base.cancellable, &m->base.error); + cancellable, error); if (dest == NULL) return; @@ -1050,7 +1053,7 @@ transfer_messages_exec (struct _transfer_msg *m) camel_folder_transfer_messages_to_sync ( m->source, m->uids, dest, m->delete, NULL, - m->base.cancellable, &m->base.error); + cancellable, error); /* make sure all deleted messages are marked as seen */ @@ -1148,13 +1151,19 @@ get_folderinfo_desc (struct _get_folderinfo_msg *m) } static void -get_folderinfo_exec (struct _get_folderinfo_msg *m) +get_folderinfo_exec (struct _get_folderinfo_msg *m, + GCancellable *cancellable, + GError **error) { - guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; + guint32 flags; + + flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE | + CAMEL_STORE_FOLDER_INFO_FAST | + CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; m->info = camel_store_get_folder_info_sync ( m->store, NULL, flags, - m->base.cancellable, &m->base.error); + cancellable, error); } static void @@ -1201,10 +1210,8 @@ mail_get_folderinfo (CamelStore *store, gint id; m = mail_msg_new (&get_folderinfo_info); - if (G_IS_CANCELLABLE (cancellable)) { - g_object_unref (m->base.cancellable); - m->base.cancellable = g_object_ref (cancellable); - } + if (G_IS_CANCELLABLE (cancellable)) + e_activity_set_cancellable (m->base.activity, cancellable); m->store = store; g_object_ref (store); m->done = done; @@ -1300,11 +1307,13 @@ get_folder_desc (struct _get_folder_msg *m) } static void -get_folder_exec (struct _get_folder_msg *m) +get_folder_exec (struct _get_folder_msg *m, + GCancellable *cancellable, + GError **error) { m->folder = e_mail_session_uri_to_folder_sync ( m->session, m->uri, m->flags, - m->base.cancellable, &m->base.error); + cancellable, error); } static void @@ -1373,7 +1382,9 @@ get_quota_desc (struct _get_quota_msg *m) } static void -get_quota_exec (struct _get_quota_msg *m) +get_quota_exec (struct _get_quota_msg *m, + GCancellable *cancellable, + GError **error) { m->quota = camel_folder_get_quota_info (m->folder); } @@ -1446,13 +1457,15 @@ get_store_desc (struct _get_store_msg *m) } static void -get_store_exec (struct _get_store_msg *m) +get_store_exec (struct _get_store_msg *m, + GCancellable *cancellable, + GError **error) { /*camel_session_get_store connects us, which we don't want to do on startup. */ m->store = (CamelStore *) camel_session_get_service ( CAMEL_SESSION (m->session), m->uri, - CAMEL_PROVIDER_STORE, &m->base.error); + CAMEL_PROVIDER_STORE, error); } static void @@ -1490,10 +1503,8 @@ mail_get_store (EMailSession *session, gint id; m = mail_msg_new (&get_store_info); - if (G_IS_CANCELLABLE (cancellable)) { - g_object_unref (m->base.cancellable); - m->base.cancellable = g_object_ref (cancellable); - } + if (G_IS_CANCELLABLE (cancellable)) + e_activity_set_cancellable (m->base.activity, cancellable); m->session = g_object_ref (session); m->uri = g_strdup (uri); m->data = data; @@ -1579,7 +1590,9 @@ remove_folder_rec (CamelStore *store, } static void -remove_folder_exec (struct _remove_folder_msg *m) +remove_folder_exec (struct _remove_folder_msg *m, + GCancellable *cancellable, + GError **error) { CamelFolderInfo *fi; CamelStore *parent_store; @@ -1595,13 +1608,12 @@ remove_folder_exec (struct _remove_folder_msg *m) CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, - m->base.cancellable, - &m->base.error); + cancellable, error); if (fi == NULL) return; m->removed = remove_folder_rec ( - parent_store, fi, m->base.cancellable, &m->base.error); + parent_store, fi, cancellable, error); camel_store_free_folder_info (parent_store, fi); } @@ -1660,10 +1672,12 @@ sync_folder_desc (struct _sync_folder_msg *m) } static void -sync_folder_exec (struct _sync_folder_msg *m) +sync_folder_exec (struct _sync_folder_msg *m, + GCancellable *cancellable, + GError **error) { camel_folder_synchronize_sync ( - m->folder, FALSE, m->base.cancellable, &m->base.error); + m->folder, FALSE, cancellable, error); } static void @@ -1728,11 +1742,13 @@ sync_store_desc (struct _sync_store_msg *m) } static void -sync_store_exec (struct _sync_store_msg *m) +sync_store_exec (struct _sync_store_msg *m, + GCancellable *cancellable, + GError **error) { camel_store_synchronize_sync ( m->store, m->expunge, - m->base.cancellable, &m->base.error); + cancellable, error); } static void @@ -1780,10 +1796,12 @@ refresh_folder_desc (struct _sync_folder_msg *m) } static void -refresh_folder_exec (struct _sync_folder_msg *m) +refresh_folder_exec (struct _sync_folder_msg *m, + GCancellable *cancellable, + GError **error) { camel_folder_refresh_info_sync ( - m->folder, m->base.cancellable, &m->base.error); + m->folder, cancellable, error); } /* we just use the sync stuff where we can, since it would be the same */ @@ -1818,10 +1836,11 @@ expunge_folder_desc (struct _sync_folder_msg *m) } static void -expunge_folder_exec (struct _sync_folder_msg *m) +expunge_folder_exec (struct _sync_folder_msg *m, + GCancellable *cancellable, + GError **error) { - camel_folder_expunge_sync ( - m->folder, m->base.cancellable, &m->base.error); + camel_folder_expunge_sync (m->folder, cancellable, error); } /* we just use the sync stuff where we can, since it would be the same */ @@ -1866,28 +1885,28 @@ empty_trash_desc (struct _empty_trash_msg *m) } static void -empty_trash_exec (struct _empty_trash_msg *m) +empty_trash_exec (struct _empty_trash_msg *m, + GCancellable *cancellable, + GError **error) { - const gchar *data_dir; CamelFolder *trash; + const gchar *data_dir; gchar *uri; if (m->account) { trash = e_mail_session_get_trash_sync ( m->session, m->account->source->url, - m->base.cancellable, &m->base.error); + cancellable, error); } else { data_dir = mail_session_get_data_dir (); uri = g_strdup_printf ("mbox:%s/local", data_dir); trash = e_mail_session_get_trash_sync ( - m->session, uri, - m->base.cancellable, &m->base.error); + m->session, uri, cancellable, error); g_free (uri); } if (trash) { - camel_folder_expunge_sync ( - trash, m->base.cancellable, &m->base.error); + camel_folder_expunge_sync (trash, cancellable, error); g_object_unref (trash); } } @@ -1955,14 +1974,15 @@ get_message_desc (struct _get_message_msg *m) } static void -get_message_exec (struct _get_message_msg *m) +get_message_exec (struct _get_message_msg *m, + GCancellable *cancellable, + GError **error) { - if (g_cancellable_is_cancelled (m->base.cancellable)) + if (g_cancellable_is_cancelled (cancellable)) m->message = NULL; else m->message = camel_folder_get_message_sync ( - m->folder, m->uid, - m->base.cancellable, &m->base.error); + m->folder, m->uid, cancellable, error); } static void @@ -2090,7 +2110,9 @@ get_messages_desc (struct _get_messages_msg *m) } static void -get_messages_exec (struct _get_messages_msg *m) +get_messages_exec (struct _get_messages_msg *m, + GCancellable *cancellable, + GError **error) { gint i; CamelMimeMessage *message; @@ -2100,9 +2122,8 @@ get_messages_exec (struct _get_messages_msg *m) message = camel_folder_get_message_sync ( m->folder, m->uids->pdata[i], - m->base.cancellable, &m->base.error); - camel_operation_progress ( - m->base.cancellable, pc); + cancellable, error); + camel_operation_progress (cancellable, pc); if (message == NULL) break; @@ -2214,7 +2235,9 @@ save_prepare_part (CamelMimePart *mime_part) } static void -save_messages_exec (struct _save_messages_msg *m) +save_messages_exec (struct _save_messages_msg *m, + GCancellable *cancellable, + GError **error) { CamelStream *filtered_stream; CamelMimeFilter *from_filter; @@ -2243,9 +2266,8 @@ save_messages_exec (struct _save_messages_msg *m) message = camel_folder_get_message_sync ( m->folder, m->uids->pdata[i], - m->base.cancellable, &m->base.error); - camel_operation_progress ( - m->base.cancellable, pc); + cancellable, error); + camel_operation_progress (cancellable, pc); if (message == NULL) break; @@ -2255,24 +2277,23 @@ save_messages_exec (struct _save_messages_msg *m) from = camel_mime_message_build_mbox_from (message); if (camel_stream_write_string ( stream, from, - m->base.cancellable, &m->base.error) == -1 + cancellable, error) == -1 || camel_stream_flush ( - stream, m->base.cancellable, &m->base.error) == -1 + stream, cancellable, error) == -1 || camel_data_wrapper_write_to_stream_sync ( (CamelDataWrapper *) message, (CamelStream *)filtered_stream, - m->base.cancellable, &m->base.error) == -1 + cancellable, error) == -1 || camel_stream_flush ( (CamelStream *)filtered_stream, - m->base.cancellable, &m->base.error) == -1 + cancellable, error) == -1 || camel_stream_write_string ( stream, "\n", - m->base.cancellable, &m->base.error) == -1 + cancellable, error) == -1 || camel_stream_flush (stream, - m->base.cancellable, &m->base.error) == -1) { + cancellable, error) == -1) { g_prefix_error ( - &m->base.error, - _("Error saving messages to: %s:\n"), + error, _("Error saving messages to: %s:\n"), m->path); g_free (from); g_object_unref ((CamelObject *)message); @@ -2343,22 +2364,24 @@ struct _prep_offline_msg { }; static void -prep_offline_exec (struct _prep_offline_msg *m) +prep_offline_exec (struct _prep_offline_msg *m, + GCancellable *cancellable, + GError **error) { CamelFolder *folder; folder = e_mail_session_uri_to_folder_sync ( m->session, m->uri, 0, - m->base.cancellable, &m->base.error); + cancellable, error); if (folder) { if (CAMEL_IS_DISCO_FOLDER (folder)) { camel_disco_folder_prepare_for_offline ( CAMEL_DISCO_FOLDER (folder), - "(match-all)", m->cancel, &m->base.error); + "(match-all)", m->cancel, error); } else if (CAMEL_IS_OFFLINE_FOLDER (folder)) { camel_offline_folder_downsync_sync ( CAMEL_OFFLINE_FOLDER (folder), - "(match-all)", m->cancel, &m->base.error); + "(match-all)", m->cancel, error); } /* prepare_for_offline should do this? */ /* of course it should all be atomic, but ... */ @@ -2436,35 +2459,34 @@ set_offline_desc (struct _set_offline_msg *m) } static void -set_offline_exec (struct _set_offline_msg *m) +set_offline_exec (struct _set_offline_msg *m, + GCancellable *cancellable, + GError **error) { if (CAMEL_IS_DISCO_STORE (m->store)) { if (!m->offline) { camel_disco_store_set_status ( CAMEL_DISCO_STORE (m->store), CAMEL_DISCO_STORE_ONLINE, - m->base.cancellable, - &m->base.error); + cancellable, error); return; } else if (camel_disco_store_can_work_offline (CAMEL_DISCO_STORE (m->store))) { camel_disco_store_set_status ( CAMEL_DISCO_STORE (m->store), CAMEL_DISCO_STORE_OFFLINE, - m->base.cancellable, - &m->base.error); + cancellable, error); return; } } else if (CAMEL_IS_OFFLINE_STORE (m->store)) { camel_offline_store_set_online_sync ( CAMEL_OFFLINE_STORE (m->store), - !m->offline, m->base.cancellable, - &m->base.error); + !m->offline, cancellable, error); return; } if (m->offline) camel_service_disconnect_sync ( - CAMEL_SERVICE (m->store), TRUE, &m->base.error); + CAMEL_SERVICE (m->store), TRUE, error); } static void @@ -2530,16 +2552,18 @@ prepare_offline_desc (struct _set_offline_msg *m) } static void -prepare_offline_exec (struct _set_offline_msg *m) +prepare_offline_exec (struct _set_offline_msg *m, + GCancellable *cancellable, + GError **error) { if (CAMEL_IS_DISCO_STORE (m->store)) { camel_disco_store_prepare_for_offline ( CAMEL_DISCO_STORE (m->store), - m->base.cancellable, &m->base.error); + cancellable, error); } else if (CAMEL_IS_OFFLINE_STORE (m->store)) { camel_offline_store_prepare_for_offline_sync ( CAMEL_OFFLINE_STORE (m->store), - m->base.cancellable, &m->base.error); + cancellable, error); } } @@ -2616,18 +2640,19 @@ check_service_desc (struct _check_msg *m) } static void -check_service_exec (struct _check_msg *m) +check_service_exec (struct _check_msg *m, + GCancellable *cancellable, + GError **error) { CamelService *service; service = camel_session_get_service ( - CAMEL_SESSION (m->session), m->url, - m->type, &m->base.error); + CAMEL_SESSION (m->session), m->url, m->type, error); if (!service) return; m->authtypes = camel_service_query_auth_types_sync ( - service, m->base.cancellable, &m->base.error); + service, cancellable, error); g_object_unref (service); } diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c index 3d303873cf..63cc28312c 100644 --- a/mail/mail-send-recv.c +++ b/mail/mail-send-recv.c @@ -903,10 +903,12 @@ refresh_folders_desc (struct _refresh_folders_msg *m) } static void -refresh_folders_exec (struct _refresh_folders_msg *m) +refresh_folders_exec (struct _refresh_folders_msg *m, + GCancellable *cancellable, + GError **error) { - gint i; CamelFolder *folder; + gint i; GError *local_error = NULL; get_folders (m->store, m->folders, m->finfo); @@ -915,7 +917,7 @@ refresh_folders_exec (struct _refresh_folders_msg *m) folder = e_mail_session_uri_to_folder_sync ( m->info->session, m->folders->pdata[i], 0, - m->base.cancellable, &local_error); + cancellable, &local_error); if (folder) { /* FIXME Not passing a GCancellable or GError here. */ camel_folder_synchronize_sync ( diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c index eb447ea888..6ed6a61d90 100644 --- a/mail/mail-vfolder.c +++ b/mail/mail-vfolder.c @@ -88,7 +88,9 @@ vfolder_setup_desc (struct _setup_msg *m) } static void -vfolder_setup_exec (struct _setup_msg *m) +vfolder_setup_exec (struct _setup_msg *m, + GCancellable *cancellable, + GError **error) { GList *l, *list = NULL; CamelFolder *folder; @@ -243,7 +245,9 @@ vfolder_adduri_desc (struct _adduri_msg *m) } static void -vfolder_adduri_exec (struct _adduri_msg *m) +vfolder_adduri_exec (struct _adduri_msg *m, + GCancellable *cancellable, + GError **error) { GList *l; CamelFolder *folder = NULL; @@ -252,8 +256,6 @@ vfolder_adduri_exec (struct _adduri_msg *m) if (vfolder_shutdown) return; - d(printf("%s uri to vfolder: %s\n", m->remove?"Removing":"Adding", m->uri)); - folder_cache = e_mail_session_get_folder_cache (m->session); /* we dont try lookup the cache if we are removing it, its no longer there */ @@ -266,8 +268,7 @@ vfolder_adduri_exec (struct _adduri_msg *m) if (folder == NULL) folder = e_mail_session_uri_to_folder_sync ( - m->session, m->uri, 0, - m->base.cancellable, &m->base.error); + m->session, m->uri, 0, cancellable, error); if (folder != NULL) { l = m->folders; diff --git a/mail/message-list.c b/mail/message-list.c index 974eb1c295..68e05fc998 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -2218,7 +2218,9 @@ ml_drop_async_desc (struct _drop_msg *m) } static void -ml_drop_async_exec (struct _drop_msg *m) +ml_drop_async_exec (struct _drop_msg *m, + GCancellable *cancellable, + GError **error) { EMailBackend *backend; EMailSession *session; @@ -2231,8 +2233,7 @@ ml_drop_async_exec (struct _drop_msg *m) em_utils_selection_get_uidlist ( m->selection, session, m->folder, m->action == GDK_ACTION_MOVE, - m->base.cancellable, - &m->base.error); + cancellable, error); break; case DND_MESSAGE_RFC822: em_utils_selection_get_message (m->selection, m->folder); @@ -4461,7 +4462,9 @@ regen_list_desc (struct _regen_list_msg *m) } static void -regen_list_exec (struct _regen_list_msg *m) +regen_list_exec (struct _regen_list_msg *m, + GCancellable *cancellable, + GError **error) { GPtrArray *uids, *searchuids = NULL; CamelMessageInfo *info; @@ -4469,6 +4472,7 @@ regen_list_exec (struct _regen_list_msg *m) ETree *tree; gint i; gchar *expr = NULL; + GError *local_error = NULL; if (m->folder != m->ml->folder) return; @@ -4516,7 +4520,7 @@ regen_list_exec (struct _regen_list_msg *m) gboolean store_has_vjunk = folder_store_supports_vjunk_folder (m->folder); searchuids = uids = camel_folder_search_by_expression ( - m->folder, expr, &m->base.error); + m->folder, expr, &local_error); /* If m->changes is not NULL, then it means we are called from folder_changed event, thus we will keep the selected message to be sure it doesn't disappear because it no longer belong to our search filter. */ @@ -4554,13 +4558,15 @@ regen_list_exec (struct _regen_list_msg *m) } } - if (m->base.error != NULL) + if (local_error != NULL) { + g_propagate_error (error, local_error); return; + } e_profile_event_emit("list.threaduids", m->folder->full_name, 0); /* camel_folder_summary_prepare_fetch_all (m->folder->summary, NULL); */ - if (!g_cancellable_is_cancelled (m->base.cancellable)) { + if (!g_cancellable_is_cancelled (cancellable)) { /* update/build a new tree */ if (m->dotree) { ml_sort_uids_by_tree (m->ml, uids); @@ -4596,6 +4602,9 @@ static void regen_list_done (struct _regen_list_msg *m) { ETree *tree; + GCancellable *cancellable; + + cancellable = e_activity_get_cancellable (m->base.activity); if (m->ml->priv->destroyed) return; @@ -4603,7 +4612,7 @@ regen_list_done (struct _regen_list_msg *m) if (!m->complete) return; - if (g_cancellable_is_cancelled (m->base.cancellable)) + if (g_cancellable_is_cancelled (cancellable)) return; if (m->ml->folder != m->folder) @@ -4789,10 +4798,12 @@ mail_regen_cancel (MessageList *ml) l = ml->regen; while (l) { MailMsg *mm = l->data; + GCancellable *cancellable; - if (mm->cancellable) + cancellable = e_activity_get_cancellable (mm->activity); + if (CAMEL_IS_OPERATION (cancellable)) camel_operation_cancel ( - CAMEL_OPERATION (mm->cancellable)); + CAMEL_OPERATION (cancellable)); l = l->next; } diff --git a/modules/calendar/e-cal-shell-view-memopad.c b/modules/calendar/e-cal-shell-view-memopad.c index e88aa3a546..11e1bcd3dc 100644 --- a/modules/calendar/e-cal-shell-view-memopad.c +++ b/modules/calendar/e-cal-shell-view-memopad.c @@ -429,7 +429,7 @@ e_cal_shell_view_memopad_set_status_message (ECalShellView *cal_shell_view, if (status_message == NULL || *status_message == '\0') { if (activity != NULL) { - e_activity_complete (activity); + e_activity_set_state (activity, E_ACTIVITY_COMPLETED); g_object_unref (activity); activity = NULL; } @@ -437,12 +437,12 @@ e_cal_shell_view_memopad_set_status_message (ECalShellView *cal_shell_view, } else if (activity == NULL) { activity = e_activity_new (); e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); + e_activity_set_text (activity, status_message); e_shell_backend_add_activity (shell_backend, activity); } else { e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); + e_activity_set_text (activity, status_message); } cal_shell_view->priv->memopad_activity = activity; diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c index 29c7d1e528..2dd1fdc3bb 100644 --- a/modules/calendar/e-cal-shell-view-private.c +++ b/modules/calendar/e-cal-shell-view-private.c @@ -705,21 +705,24 @@ e_cal_shell_view_private_dispose (ECalShellView *cal_shell_view) if (priv->calendar_activity != NULL) { /* XXX Activity is not cancellable. */ - e_activity_complete (priv->calendar_activity); + e_activity_set_state ( + priv->calendar_activity, E_ACTIVITY_COMPLETED); g_object_unref (priv->calendar_activity); priv->calendar_activity = NULL; } if (priv->memopad_activity != NULL) { /* XXX Activity is not cancellable. */ - e_activity_complete (priv->memopad_activity); + e_activity_set_state ( + priv->memopad_activity, E_ACTIVITY_COMPLETED); g_object_unref (priv->memopad_activity); priv->memopad_activity = NULL; } if (priv->taskpad_activity != NULL) { /* XXX Activity is not cancellable. */ - e_activity_complete (priv->taskpad_activity); + e_activity_set_state ( + priv->taskpad_activity, E_ACTIVITY_COMPLETED); g_object_unref (priv->taskpad_activity); priv->taskpad_activity = NULL; } @@ -808,18 +811,18 @@ e_cal_shell_view_set_status_message (ECalShellView *cal_shell_view, if (status_message == NULL || *status_message == '\0') { if (activity != NULL) { - e_activity_complete (activity); + e_activity_set_state (activity, E_ACTIVITY_COMPLETED); g_object_unref (activity); activity = NULL; } } else if (activity == NULL) { activity = e_activity_new (); e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); + e_activity_set_text (activity, status_message); e_shell_backend_add_activity (shell_backend, activity); } else { e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); + e_activity_set_text (activity, status_message); } cal_shell_view->priv->calendar_activity = activity; diff --git a/modules/calendar/e-cal-shell-view-taskpad.c b/modules/calendar/e-cal-shell-view-taskpad.c index b1eb390616..6dae14465d 100644 --- a/modules/calendar/e-cal-shell-view-taskpad.c +++ b/modules/calendar/e-cal-shell-view-taskpad.c @@ -556,7 +556,7 @@ e_cal_shell_view_taskpad_set_status_message (ECalShellView *cal_shell_view, if (status_message == NULL || *status_message == '\0') { if (activity != NULL) { - e_activity_complete (activity); + e_activity_set_state (activity, E_ACTIVITY_COMPLETED); g_object_unref (activity); activity = NULL; } @@ -564,12 +564,12 @@ e_cal_shell_view_taskpad_set_status_message (ECalShellView *cal_shell_view, } else if (activity == NULL) { activity = e_activity_new (); e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); + e_activity_set_text (activity, status_message); e_shell_backend_add_activity (shell_backend, activity); } else { e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); + e_activity_set_text (activity, status_message); } cal_shell_view->priv->taskpad_activity = activity; diff --git a/modules/calendar/e-memo-shell-view-private.c b/modules/calendar/e-memo-shell-view-private.c index 8c83619564..4fe6a259e2 100644 --- a/modules/calendar/e-memo-shell-view-private.c +++ b/modules/calendar/e-memo-shell-view-private.c @@ -296,7 +296,9 @@ e_memo_shell_view_private_dispose (EMemoShellView *memo_shell_view) if (memo_shell_view->priv->activity != NULL) { /* XXX Activity is not cancellable. */ - e_activity_complete (memo_shell_view->priv->activity); + e_activity_set_state ( + memo_shell_view->priv->activity, + E_ACTIVITY_COMPLETED); g_object_unref (memo_shell_view->priv->activity); memo_shell_view->priv->activity = NULL; } @@ -370,7 +372,7 @@ e_memo_shell_view_set_status_message (EMemoShellView *memo_shell_view, if (status_message == NULL || *status_message == '\0') { if (activity != NULL) { - e_activity_complete (activity); + e_activity_set_state (activity, E_ACTIVITY_COMPLETED); g_object_unref (activity); activity = NULL; } @@ -378,12 +380,12 @@ e_memo_shell_view_set_status_message (EMemoShellView *memo_shell_view, } else if (activity == NULL) { activity = e_activity_new (); e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); + e_activity_set_text (activity, status_message); e_shell_backend_add_activity (shell_backend, activity); } else { e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); + e_activity_set_text (activity, status_message); } memo_shell_view->priv->activity = activity; diff --git a/modules/calendar/e-task-shell-view-private.c b/modules/calendar/e-task-shell-view-private.c index f0e8cbff2f..9f833e9542 100644 --- a/modules/calendar/e-task-shell-view-private.c +++ b/modules/calendar/e-task-shell-view-private.c @@ -377,7 +377,9 @@ e_task_shell_view_private_dispose (ETaskShellView *task_shell_view) if (task_shell_view->priv->activity != NULL) { /* XXX Activity is not cancellable. */ - e_activity_complete (task_shell_view->priv->activity); + e_activity_set_state ( + task_shell_view->priv->activity, + E_ACTIVITY_COMPLETED); g_object_unref (task_shell_view->priv->activity); task_shell_view->priv->activity = NULL; } @@ -521,7 +523,7 @@ e_task_shell_view_set_status_message (ETaskShellView *task_shell_view, if (status_message == NULL || *status_message == '\0') { if (activity != NULL) { - e_activity_complete (activity); + e_activity_set_state (activity, E_ACTIVITY_COMPLETED); g_object_unref (activity); activity = NULL; } @@ -529,12 +531,12 @@ e_task_shell_view_set_status_message (ETaskShellView *task_shell_view, } else if (activity == NULL) { activity = e_activity_new (); e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); + e_activity_set_text (activity, status_message); e_shell_backend_add_activity (shell_backend, activity); } else { e_activity_set_percent (activity, percent); - e_activity_set_primary_text (activity, status_message); + e_activity_set_text (activity, status_message); } task_shell_view->priv->activity = activity; diff --git a/modules/mail/e-mail-shell-view.c b/modules/mail/e-mail-shell-view.c index 557d206c36..8d5a568b8f 100644 --- a/modules/mail/e-mail-shell-view.c +++ b/modules/mail/e-mail-shell-view.c @@ -55,7 +55,9 @@ search_results_desc (SearchResultsMsg *msg) } static void -search_results_exec (SearchResultsMsg *msg) +search_results_exec (SearchResultsMsg *msg, + GCancellable *cancellable, + GError **error) { GList *copied_list; diff --git a/plugins/dbx-import/dbx-importer.c b/plugins/dbx-import/dbx-importer.c index 28db6b175f..0105dfe236 100644 --- a/plugins/dbx-import/dbx-importer.c +++ b/plugins/dbx-import/dbx-importer.c @@ -546,6 +546,7 @@ dbx_import_file (DbxImporter *m) EShell *shell; EShellBackend *shell_backend; EMailSession *session; + GCancellable *cancellable; gchar *filename; CamelFolder *folder; gint tmpfile; @@ -555,6 +556,8 @@ dbx_import_file (DbxImporter *m) filename = g_filename_from_uri (((EImportTargetURI *)m->target)->uri_src, NULL, NULL); m->parent_uri = g_strdup (((EImportTargetURI *)m->target)->uri_dest); /* Destination folder, was set in our widget */ + cancellable = e_activity_get_cancellable (m->base.activity); + /* XXX Dig up the EMailSession from the default EShell. * Since the EImport framework doesn't allow for user * data, I don't see how else to get to it. */ @@ -565,7 +568,7 @@ dbx_import_file (DbxImporter *m) camel_operation_push_message (NULL, _("Importing '%s'"), filename); folder = e_mail_session_uri_to_folder_sync ( session, m->parent_uri, CAMEL_STORE_FOLDER_CREATE, - m->base.cancellable, &m->base.error); + cancellable, &m->base.error); if (!folder) return; d(printf("importing to %s\n", camel_folder_get_full_name(folder))); @@ -603,7 +606,7 @@ dbx_import_file (DbxImporter *m) gboolean success; camel_operation_progress (NULL, 100 * i / m->index_count); - camel_operation_progress (m->cancellable, 100 * i / m->index_count); + camel_operation_progress (cancellable, 100 * i / m->index_count); if (!dbx_read_email (m, m->indices[i], tmpfile, &dbx_flags)) { d(printf("Cannot read email index %d at %x\n", @@ -638,7 +641,7 @@ dbx_import_file (DbxImporter *m) camel_message_info_set_flags (info, flags, ~0); success = camel_folder_append_message_sync ( folder, msg, info, NULL, - m->base.cancellable, &m->base.error); + cancellable, &m->base.error); camel_message_info_free (info); g_object_unref (msg); @@ -667,7 +670,9 @@ dbx_import_file (DbxImporter *m) } static void -dbx_import_import (DbxImporter *m) +dbx_import_import (DbxImporter *m, + GCancellable *cancellable, + GError **error) { dbx_import_file (m); } diff --git a/plugins/groupwise-features/share-folder-common.c b/plugins/groupwise-features/share-folder-common.c index 61cace9565..4a4e57aa11 100644 --- a/plugins/groupwise-features/share-folder-common.c +++ b/plugins/groupwise-features/share-folder-common.c @@ -139,18 +139,19 @@ create_folder_desc (struct _EMCreateFolder *m) } static void -create_folder_exec (struct _EMCreateFolder *m) +create_folder_exec (struct _EMCreateFolder *m, + GCancellable *cancellable, + GError **error) { d(printf ("creating folder parent='%s' name='%s' full_name='%s'\n", m->parent, m->name, m->full_name)); if ((m->fi = camel_store_create_folder_sync ( - m->store, m->parent, m->name, - m->base.cancellable, &m->base.error))) { + m->store, m->parent, m->name, cancellable, error))) { if (camel_store_supports_subscriptions (m->store)) camel_store_subscribe_folder_sync ( m->store, m->full_name, - m->base.cancellable, &m->base.error); + cancellable, error); } } diff --git a/plugins/itip-formatter/itip-formatter.c b/plugins/itip-formatter/itip-formatter.c index d8ff9b95f6..79d0bd14b4 100644 --- a/plugins/itip-formatter/itip-formatter.c +++ b/plugins/itip-formatter/itip-formatter.c @@ -1943,7 +1943,9 @@ open_calendar__desc (struct _opencal_msg *m, gint complete) } static void -open_calendar__exec (struct _opencal_msg *m) +open_calendar__exec (struct _opencal_msg *m, + GCancellable *cancellable, + GError **error) { if (!g_spawn_command_line_async (m->command, NULL)) { g_warning ("Could not launch %s", m->command); diff --git a/plugins/pst-import/pst-importer.c b/plugins/pst-import/pst-importer.c index 2e994f78e4..d0a69ddece 100644 --- a/plugins/pst-import/pst-importer.c +++ b/plugins/pst-import/pst-importer.c @@ -121,7 +121,6 @@ struct _PstImporter { pst_file pst; - GCancellable *cancellable; CamelFolder *folder; gchar *parent_uri; gchar *folder_name; @@ -394,7 +393,9 @@ open_ecal (ECalSourceType type, const gchar *name) } static void -pst_import_import (PstImporter *m) +pst_import_import (PstImporter *m, + GCancellable *cancellable, + GError **error) { if (GPOINTER_TO_INT (g_datalist_get_data (&m->target->data, "pst-do-addr"))) { /* Hack - grab the first address book we can find @@ -456,11 +457,14 @@ pst_import_file (PstImporter *m) EShell *shell; EShellBackend *shell_backend; EMailSession *session; + GCancellable *cancellable; gint ret; gchar *filename; pst_item *item = NULL; pst_desc_tree *d_ptr; + cancellable = e_activity_get_cancellable (m->base.activity); + /* XXX Dig up the EMailSession from the default EShell. * Since the EImport framework doesn't allow for user * data, I don't see how else to get to it. */ @@ -476,7 +480,7 @@ pst_import_file (PstImporter *m) if (GPOINTER_TO_INT (g_datalist_get_data (&m->target->data, "pst-do-mail"))) { e_mail_session_uri_to_folder_sync ( session, m->parent_uri, CAMEL_STORE_FOLDER_CREATE, - m->base.cancellable, &m->base.error); + cancellable, &m->base.error); } ret = pst_init (&m->pst, filename); @@ -710,10 +714,13 @@ pst_create_folder (PstImporter *m) EShell *shell; EShellBackend *shell_backend; EMailSession *session; + GCancellable *cancellable; const gchar *parent; gchar *dest, *dest_end, *pos; gint dest_len; + cancellable = e_activity_get_cancellable (m->base.activity); + /* XXX Dig up the EMailSession from the default EShell. * Since the EImport framework doesn't allow for user * data, I don't see how else to get to it. */ @@ -740,7 +747,7 @@ pst_create_folder (PstImporter *m) folder = e_mail_session_uri_to_folder_sync ( session, dest, CAMEL_STORE_FOLDER_CREATE, - m->base.cancellable, &m->base.error); + cancellable, &m->base.error); g_object_unref (folder); *pos = '/'; } @@ -754,7 +761,7 @@ pst_create_folder (PstImporter *m) m->folder = e_mail_session_uri_to_folder_sync ( session, m->folder_uri, CAMEL_STORE_FOLDER_CREATE, - m->base.cancellable, &m->base.error); + cancellable, &m->base.error); } /** @@ -1659,7 +1666,6 @@ pst_import (EImport *ei, EImportTarget *target) m->status_timeout_id = g_timeout_add (100, pst_status_timeout, m); /*m->status_timeout_id = NULL;*/ m->status_lock = g_mutex_new (); - m->cancellable = camel_operation_new (); g_signal_connect ( m->status, "status", diff --git a/shell/e-shell-backend.c b/shell/e-shell-backend.c index 0d7ff020c7..c2abb470a2 100644 --- a/shell/e-shell-backend.c +++ b/shell/e-shell-backend.c @@ -398,19 +398,30 @@ void e_shell_backend_add_activity (EShellBackend *shell_backend, EActivity *activity) { - GCancellable *cancellable; + EActivityState state; g_return_if_fail (E_IS_SHELL_BACKEND (shell_backend)); g_return_if_fail (E_IS_ACTIVITY (activity)); - cancellable = e_activity_get_cancellable (activity); + state = e_activity_get_state (activity); - /* Skip cancelled activities. */ - if (g_cancellable_is_cancelled (cancellable)) + /* Disregard cancelled or completed activities. */ + + if (state == E_ACTIVITY_CANCELLED) + return; + + if (state == E_ACTIVITY_COMPLETED) return; g_queue_push_tail (shell_backend->priv->activities, activity); + /* Emit the "activity-added" signal before adding a weak reference + * to the EActivity because EShellTaskbar's signal handler also adds + * a weak reference to the EActivity, and we want its GWeakNotify + * to run before ours, since ours may destroy the EShellTaskbar + * during application shutdown. */ + g_signal_emit (shell_backend, signals[ACTIVITY_ADDED], 0, activity); + /* We reference the backend on every activity to * guarantee the backend outlives the activity. */ g_object_weak_ref ( @@ -418,8 +429,6 @@ e_shell_backend_add_activity (EShellBackend *shell_backend, shell_backend_activity_finalized_cb, g_object_ref (shell_backend)); - g_signal_emit (shell_backend, signals[ACTIVITY_ADDED], 0, activity); - /* Only emit "notify::busy" when switching from idle to busy. */ if (g_queue_get_length (shell_backend->priv->activities) == 1) g_object_notify (G_OBJECT (shell_backend), "busy"); diff --git a/shell/e-shell-taskbar.c b/shell/e-shell-taskbar.c index 47f900ae3e..9be7c1564e 100644 --- a/shell/e-shell-taskbar.c +++ b/shell/e-shell-taskbar.c @@ -64,8 +64,8 @@ G_DEFINE_TYPE_WITH_CODE ( E_TYPE_EXTENSIBLE, NULL)) static void -shell_taskbar_activity_remove (EShellTaskbar *shell_taskbar, - EActivity *activity) +shell_taskbar_weak_notify_cb (EShellTaskbar *shell_taskbar, + GObject *where_the_activity_was) { GtkWidget *proxy; GtkContainer *container; @@ -73,11 +73,10 @@ shell_taskbar_activity_remove (EShellTaskbar *shell_taskbar, GList *children; proxy_table = shell_taskbar->priv->proxy_table; - proxy = g_hash_table_lookup (proxy_table, activity); + proxy = g_hash_table_lookup (proxy_table, where_the_activity_was); + g_hash_table_remove (proxy_table, where_the_activity_was); g_return_if_fail (proxy != NULL); - g_hash_table_remove (proxy_table, activity); - container = GTK_CONTAINER (shell_taskbar->priv->hbox); gtk_container_remove (container, proxy); @@ -95,6 +94,17 @@ shell_taskbar_activity_add (EShellTaskbar *shell_taskbar, { GtkBox *box; GtkWidget *proxy; + EActivityState state; + GHashTable *proxy_table; + + /* Sanity check the activity state. */ + state = e_activity_get_state (activity); + g_return_if_fail (state == E_ACTIVITY_RUNNING); + + /* Make sure it hasn't already been added. */ + proxy_table = shell_taskbar->priv->proxy_table; + proxy = g_hash_table_lookup (proxy_table, activity); + g_return_if_fail (proxy == NULL); /* Proxy widgets manage their own visibility. * Don't call gtk_widget_show() on it here. */ @@ -104,17 +114,28 @@ shell_taskbar_activity_add (EShellTaskbar *shell_taskbar, gtk_box_reorder_child (box, proxy, 0); gtk_widget_show (GTK_WIDGET (box)); - g_hash_table_insert ( - shell_taskbar->priv->proxy_table, - g_object_ref (activity), g_object_ref (proxy)); + /* The proxy widget also holds a weak reference to the activity, + * so the activity should get finalized in the normal course of + * operation. When that happens we remove the corresponding + * proxy widget from the taskbar. */ - g_signal_connect_swapped ( - activity, "cancelled", - G_CALLBACK (shell_taskbar_activity_remove), shell_taskbar); + g_object_weak_ref ( + G_OBJECT (activity), (GWeakNotify) + shell_taskbar_weak_notify_cb, shell_taskbar); - g_signal_connect_swapped ( - activity, "completed", - G_CALLBACK (shell_taskbar_activity_remove), shell_taskbar); + g_hash_table_insert (proxy_table, activity, proxy); +} + +static gboolean +shell_taskbar_weak_unref (EActivity *activity, + EActivityProxy *proxy, + EShellTaskbar *shell_taskbar) +{ + g_object_weak_unref ( + G_OBJECT (activity), (GWeakNotify) + shell_taskbar_weak_notify_cb, shell_taskbar); + + return TRUE; } static void @@ -176,18 +197,6 @@ shell_taskbar_get_property (GObject *object, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } -static gboolean -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); - - return TRUE; -} - static void shell_taskbar_dispose (GObject *object) { @@ -195,6 +204,10 @@ shell_taskbar_dispose (GObject *object) priv = E_SHELL_TASKBAR_GET_PRIVATE (object); + g_hash_table_foreach_remove ( + priv->proxy_table, (GHRFunc) + shell_taskbar_weak_unref, object); + if (priv->shell_view != NULL) { g_object_remove_weak_pointer ( G_OBJECT (priv->shell_view), &priv->shell_view); @@ -219,9 +232,6 @@ shell_taskbar_dispose (GObject *object) priv->hbox = NULL; } - 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); } @@ -315,16 +325,10 @@ static void e_shell_taskbar_init (EShellTaskbar *shell_taskbar) { GtkWidget *widget; - GHashTable *proxy_table; gint height; - proxy_table = g_hash_table_new_full ( - g_direct_hash, g_direct_equal, - (GDestroyNotify) g_object_unref, - (GDestroyNotify) g_object_unref); - shell_taskbar->priv = E_SHELL_TASKBAR_GET_PRIVATE (shell_taskbar); - shell_taskbar->priv->proxy_table = proxy_table; + shell_taskbar->priv->proxy_table = g_hash_table_new (NULL, NULL); gtk_box_set_spacing (GTK_BOX (shell_taskbar), 12); diff --git a/shell/e-shell-view.c b/shell/e-shell-view.c index 18300c4672..e07b76213a 100644 --- a/shell/e-shell-view.c +++ b/shell/e-shell-view.c @@ -293,7 +293,7 @@ shell_view_save_state (EShellView *shell_view) FALSE, G_FILE_CREATE_PRIVATE, (GAsyncReadyCallback) shell_view_save_state_done_cb, data); - e_activity_set_primary_text ( + e_activity_set_text ( activity, (_("Saving user interface state"))); e_shell_backend_add_activity (shell_backend, activity); diff --git a/shell/e-shell.c b/shell/e-shell.c index 62cae09cfc..b983b18403 100644 --- a/shell/e-shell.c +++ b/shell/e-shell.c @@ -221,7 +221,7 @@ shell_ready_for_offline (EShell *shell, * a signal without triggering the toggle reference. */ g_object_ref (activity); - e_activity_complete (activity); + e_activity_set_state (activity, E_ACTIVITY_COMPLETED); g_object_remove_toggle_ref ( G_OBJECT (activity), (GToggleNotify) @@ -243,7 +243,7 @@ shell_prepare_for_offline (EShell *shell) shell->priv->preparing_for_line_change = e_activity_new (); - e_activity_set_primary_text ( + e_activity_set_text ( shell->priv->preparing_for_line_change, _("Preparing to go offline...")); @@ -274,7 +274,7 @@ shell_ready_for_online (EShell *shell, * a signal without triggering the toggle reference. */ g_object_ref (activity); - e_activity_complete (activity); + e_activity_set_state (activity, E_ACTIVITY_COMPLETED); g_object_remove_toggle_ref ( G_OBJECT (activity), (GToggleNotify) @@ -296,7 +296,7 @@ shell_prepare_for_online (EShell *shell) shell->priv->preparing_for_line_change = e_activity_new (); - e_activity_set_primary_text ( + e_activity_set_text ( shell->priv->preparing_for_line_change, _("Preparing to go online...")); @@ -329,7 +329,7 @@ shell_ready_for_quit (EShell *shell, * a signal without triggering the toggle reference. */ g_object_ref (activity); - e_activity_complete (activity); + e_activity_set_state (activity, E_ACTIVITY_COMPLETED); g_object_remove_toggle_ref ( G_OBJECT (activity), (GToggleNotify) @@ -358,7 +358,7 @@ shell_prepare_for_quit (EShell *shell) shell->priv->preparing_for_quit = e_activity_new (); - e_activity_set_primary_text ( + e_activity_set_text ( shell->priv->preparing_for_quit, _("Preparing to quit...")); diff --git a/shell/test/e-test-shell-view.c b/shell/test/e-test-shell-view.c index 4ecda3035c..924f9891f4 100644 --- a/shell/test/e-test-shell-view.c +++ b/shell/test/e-test-shell-view.c @@ -98,7 +98,7 @@ test_shell_view_constructed (GObject *object) activity = e_activity_new (); cancellable = g_cancellable_new (); e_activity_set_cancellable (activity, cancellable); - e_activity_set_primary_text (activity, "Test Activity"); + e_activity_set_text (activity, "Test Activity"); e_shell_backend_add_activity (shell_backend, activity); g_object_unref (cancellable); priv->activity = activity; diff --git a/widgets/misc/e-activity-bar.c b/widgets/misc/e-activity-bar.c index 0337822adc..a86e37cbdf 100644 --- a/widgets/misc/e-activity-bar.c +++ b/widgets/misc/e-activity-bar.c @@ -23,12 +23,14 @@ ((obj), E_TYPE_ACTIVITY_BAR, EActivityBarPrivate)) #define FEEDBACK_PERIOD 1 /* seconds */ +#define COMPLETED_ICON_NAME "emblem-default" struct _EActivityBarPrivate { EActivity *activity; /* weak reference */ GtkWidget *image; /* not referenced */ GtkWidget *label; /* not referenced */ GtkWidget *cancel; /* not referenced */ + GtkWidget *spinner; /* not referenced */ /* If the user clicks the Cancel button, keep the cancelled * EActivity object alive for a short duration so the user @@ -47,13 +49,35 @@ G_DEFINE_TYPE ( GTK_TYPE_INFO_BAR) static void +activity_bar_feedback (EActivityBar *bar) +{ + EActivity *activity; + EActivityState state; + + activity = e_activity_bar_get_activity (bar); + g_return_if_fail (E_IS_ACTIVITY (activity)); + + state = e_activity_get_state (activity); + if (state != E_ACTIVITY_CANCELLED && state != E_ACTIVITY_COMPLETED) + return; + + if (bar->priv->timeout_id > 0) + g_source_remove (bar->priv->timeout_id); + + /* Hold a reference on the EActivity for a short + * period so the activity bar stays visible. */ + bar->priv->timeout_id = g_timeout_add_seconds_full ( + G_PRIORITY_LOW, FEEDBACK_PERIOD, (GSourceFunc) gtk_false, + g_object_ref (activity), (GDestroyNotify) g_object_unref); +} + +static void activity_bar_update (EActivityBar *bar) { EActivity *activity; + EActivityState state; GCancellable *cancellable; const gchar *icon_name; - gboolean cancelled; - gboolean completed; gboolean sensitive; gboolean visible; gchar *description; @@ -66,14 +90,13 @@ activity_bar_update (EActivityBar *bar) } cancellable = e_activity_get_cancellable (activity); - cancelled = g_cancellable_is_cancelled (cancellable); - completed = e_activity_is_completed (activity); icon_name = e_activity_get_icon_name (activity); + state = e_activity_get_state (activity); description = e_activity_describe (activity); gtk_label_set_text (GTK_LABEL (bar->priv->label), description); - if (cancelled) { + if (state == E_ACTIVITY_CANCELLED) { PangoAttribute *attr; PangoAttrList *attr_list; @@ -90,25 +113,27 @@ activity_bar_update (EActivityBar *bar) gtk_label_set_attributes ( GTK_LABEL (bar->priv->label), NULL); - if (cancelled) + if (state == E_ACTIVITY_COMPLETED) + icon_name = COMPLETED_ICON_NAME; + + if (state == E_ACTIVITY_CANCELLED) { gtk_image_set_from_stock ( GTK_IMAGE (bar->priv->image), GTK_STOCK_CANCEL, GTK_ICON_SIZE_BUTTON); - else { - if (completed) - icon_name = "emblem-default"; + gtk_widget_show (bar->priv->image); + } else if (icon_name != NULL) { gtk_image_set_from_icon_name ( GTK_IMAGE (bar->priv->image), icon_name, GTK_ICON_SIZE_BUTTON); + gtk_widget_show (bar->priv->image); + } else { + gtk_widget_hide (bar->priv->image); } - visible = (icon_name != NULL); - gtk_widget_set_visible (bar->priv->image, visible); - visible = (cancellable != NULL); gtk_widget_set_visible (bar->priv->cancel, visible); - sensitive = !cancelled && !completed; + sensitive = (state == E_ACTIVITY_RUNNING); gtk_widget_set_sensitive (bar->priv->cancel, sensitive); visible = (description != NULL && *description != '\0'); @@ -128,30 +153,16 @@ activity_bar_cancel (EActivityBar *bar) cancellable = e_activity_get_cancellable (activity); g_cancellable_cancel (cancellable); -} - -static void -activity_bar_feedback (EActivityBar *bar) -{ - EActivity *activity; - - activity = e_activity_bar_get_activity (bar); - g_return_if_fail (E_IS_ACTIVITY (activity)); - if (bar->priv->timeout_id > 0) - g_source_remove (bar->priv->timeout_id); - - /* Hold a reference on the EActivity for a short - * period so the activity bar stays visible. */ - bar->priv->timeout_id = g_timeout_add_seconds_full ( - G_PRIORITY_LOW, FEEDBACK_PERIOD, (GSourceFunc) gtk_false, - g_object_ref (activity), (GDestroyNotify) g_object_unref); + activity_bar_update (bar); } static void activity_bar_weak_notify_cb (EActivityBar *bar, GObject *where_the_object_was) { + g_return_if_fail (E_IS_ACTIVITY_BAR (bar)); + bar->priv->activity = NULL; e_activity_bar_set_activity (bar, NULL); } @@ -259,7 +270,19 @@ e_activity_bar_init (EActivityBar *bar) widget = gtk_image_new (); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); bar->priv->image = widget; - gtk_widget_show (widget); + + widget = gtk_spinner_new (); + gtk_spinner_start (GTK_SPINNER (widget)); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + bar->priv->spinner = widget; + + /* The spinner is only visible when the image is not. */ + g_object_bind_property ( + bar->priv->image, "visible", + bar->priv->spinner, "visible", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE | + G_BINDING_INVERT_BOOLEAN); widget = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); @@ -300,12 +323,8 @@ e_activity_bar_set_activity (EActivityBar *bar, { g_return_if_fail (E_IS_ACTIVITY_BAR (bar)); - if (activity != NULL) { + if (activity != NULL) g_return_if_fail (E_IS_ACTIVITY (activity)); - g_object_weak_ref ( - G_OBJECT (activity), (GWeakNotify) - activity_bar_weak_notify_cb, bar); - } if (bar->priv->timeout_id > 0) { g_source_remove (bar->priv->timeout_id); @@ -324,23 +343,15 @@ e_activity_bar_set_activity (EActivityBar *bar, bar->priv->activity = activity; if (activity != NULL) { - g_signal_connect_swapped ( - activity, "cancelled", - G_CALLBACK (activity_bar_feedback), bar); + g_object_weak_ref ( + G_OBJECT (activity), (GWeakNotify) + activity_bar_weak_notify_cb, bar); g_signal_connect_swapped ( - activity, "completed", + activity, "notify::state", G_CALLBACK (activity_bar_feedback), bar); g_signal_connect_swapped ( - activity, "cancelled", - G_CALLBACK (activity_bar_update), bar); - - g_signal_connect_swapped ( - activity, "completed", - G_CALLBACK (activity_bar_update), bar); - - g_signal_connect_swapped ( activity, "notify", G_CALLBACK (activity_bar_update), bar); } diff --git a/widgets/misc/e-activity-proxy.c b/widgets/misc/e-activity-proxy.c index 26d5d30ba0..aea025d9a7 100644 --- a/widgets/misc/e-activity-proxy.c +++ b/widgets/misc/e-activity-proxy.c @@ -27,13 +27,20 @@ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_ACTIVITY_PROXY, EActivityProxyPrivate)) +#define FEEDBACK_PERIOD 1 /* seconds */ +#define COMPLETED_ICON_NAME "emblem-default" + struct _EActivityProxyPrivate { - EActivity *activity; - GtkWidget *button; - GtkWidget *image; - GtkWidget *label; - GtkWidget *cancel; - GtkWidget *spinner; + EActivity *activity; /* weak reference */ + GtkWidget *image; /* not referenced */ + GtkWidget *label; /* not referenced */ + GtkWidget *cancel; /* not referenced */ + GtkWidget *spinner; /* not referenced */ + + /* If the user clicks the Cancel button, keep the cancelled + * EActivity object alive for a short duration so the user + * gets some visual feedback that cancellation worked. */ + guint timeout_id; }; enum { @@ -47,82 +54,123 @@ G_DEFINE_TYPE ( GTK_TYPE_EVENT_BOX) static void -activity_proxy_cancel (EActivity *activity) +activity_proxy_feedback (EActivityProxy *proxy) { - GCancellable *cancellable; + EActivity *activity; + EActivityState state; - /* 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. */ + activity = e_activity_proxy_get_activity (proxy); + g_return_if_fail (E_IS_ACTIVITY (activity)); - cancellable = e_activity_get_cancellable (activity); - g_cancellable_cancel (cancellable); + state = e_activity_get_state (activity); + if (state != E_ACTIVITY_CANCELLED) + return; + + if (proxy->priv->timeout_id > 0) + g_source_remove (proxy->priv->timeout_id); + + /* Hold a reference on the EActivity for a short + * period so the activity proxy stays visible. */ + proxy->priv->timeout_id = g_timeout_add_seconds_full ( + G_PRIORITY_LOW, FEEDBACK_PERIOD, (GSourceFunc) gtk_false, + g_object_ref (activity), (GDestroyNotify) g_object_unref); } static void activity_proxy_update (EActivityProxy *proxy) { EActivity *activity; + EActivityState state; GCancellable *cancellable; const gchar *icon_name; - gboolean cancelled; - gboolean clickable; - gboolean completed; gboolean sensitive; gboolean visible; gchar *description; - activity = proxy->priv->activity; + activity = e_activity_proxy_get_activity (proxy); + + if (activity == NULL) { + gtk_widget_hide (GTK_WIDGET (proxy)); + return; + } + 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); + state = e_activity_get_state (activity); 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 - * be clickable. We don't support spinner buttons. */ - if (icon_name != NULL) { + if (state == E_ACTIVITY_CANCELLED) { + PangoAttribute *attr; + PangoAttrList *attr_list; + + attr_list = pango_attr_list_new (); + + attr = pango_attr_strikethrough_new (TRUE); + pango_attr_list_insert (attr_list, attr); + + gtk_label_set_attributes ( + GTK_LABEL (proxy->priv->label), attr_list); + + pango_attr_list_unref (attr_list); + } else + gtk_label_set_attributes ( + GTK_LABEL (proxy->priv->label), NULL); + + if (state == E_ACTIVITY_COMPLETED) + icon_name = COMPLETED_ICON_NAME; + + if (state == E_ACTIVITY_CANCELLED) { + gtk_image_set_from_stock ( + GTK_IMAGE (proxy->priv->image), + GTK_STOCK_CANCEL, GTK_ICON_SIZE_BUTTON); + gtk_widget_show (proxy->priv->image); + } else if (icon_name != NULL) { gtk_image_set_from_icon_name ( GTK_IMAGE (proxy->priv->image), icon_name, GTK_ICON_SIZE_MENU); - gtk_button_set_image ( - GTK_BUTTON (proxy->priv->button), - gtk_image_new_from_icon_name ( - icon_name, GTK_ICON_SIZE_MENU)); - gtk_widget_hide (proxy->priv->spinner); - if (clickable) { - gtk_widget_show (proxy->priv->button); - gtk_widget_hide (proxy->priv->image); - } else { - gtk_widget_hide (proxy->priv->button); - gtk_widget_show (proxy->priv->image); - } + gtk_widget_show (proxy->priv->image); } else { - gtk_widget_show (proxy->priv->spinner); - gtk_widget_hide (proxy->priv->button); gtk_widget_hide (proxy->priv->image); } visible = (cancellable != NULL); gtk_widget_set_visible (proxy->priv->cancel, visible); - sensitive = !(cancelled || completed); + sensitive = (state == E_ACTIVITY_RUNNING); gtk_widget_set_sensitive (proxy->priv->cancel, sensitive); + + visible = (description != NULL && *description != '\0'); + gtk_widget_set_visible (GTK_WIDGET (proxy), visible); + + g_free (description); } static void -activity_proxy_set_activity (EActivityProxy *proxy, - EActivity *activity) +activity_proxy_cancel (EActivityProxy *proxy) { - g_return_if_fail (proxy->priv->activity == NULL); + EActivity *activity; + GCancellable *cancellable; + + activity = e_activity_proxy_get_activity (proxy); + g_return_if_fail (E_IS_ACTIVITY (activity)); + + cancellable = e_activity_get_cancellable (activity); + g_cancellable_cancel (cancellable); + + activity_proxy_update (proxy); +} + +static void +activity_proxy_weak_notify_cb (EActivityProxy *proxy, + GObject *where_the_object_was) +{ + g_return_if_fail (E_IS_ACTIVITY_PROXY (proxy)); - proxy->priv->activity = g_object_ref (activity); + proxy->priv->activity = NULL; + e_activity_proxy_set_activity (proxy, NULL); } static void @@ -133,7 +181,7 @@ activity_proxy_set_property (GObject *object, { switch (property_id) { case PROP_ACTIVITY: - activity_proxy_set_activity ( + e_activity_proxy_set_activity ( E_ACTIVITY_PROXY (object), g_value_get_object (value)); return; @@ -166,74 +214,26 @@ activity_proxy_dispose (GObject *object) priv = E_ACTIVITY_PROXY_GET_PRIVATE (object); + if (priv->timeout_id > 0) { + g_source_remove (priv->timeout_id); + priv->timeout_id = 0; + } + if (priv->activity != NULL) { g_signal_handlers_disconnect_matched ( - priv->activity, G_SIGNAL_MATCH_FUNC, 0, 0, - NULL, activity_proxy_update, NULL); - g_object_unref (priv->activity); + priv->activity, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_weak_unref ( + G_OBJECT (priv->activity), (GWeakNotify) + activity_proxy_weak_notify_cb, object); priv->activity = NULL; } - if (priv->button != NULL) { - g_object_unref (priv->button); - priv->button = NULL; - } - - if (priv->image != NULL) { - g_object_unref (priv->image); - priv->image = NULL; - } - - if (priv->label != NULL) { - g_object_unref (priv->label); - priv->label = NULL; - } - - if (priv->cancel != NULL) { - g_object_unref (priv->cancel); - priv->cancel = NULL; - } - - if (priv->spinner != NULL) { - g_object_unref (priv->spinner); - priv->spinner = NULL; - } - /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_activity_proxy_parent_class)->dispose (object); } static void -activity_proxy_constructed (GObject *object) -{ - EActivityProxy *proxy; - - proxy = E_ACTIVITY_PROXY (object); - - g_signal_connect_swapped ( - proxy->priv->button, "clicked", - G_CALLBACK (e_activity_clicked), proxy->priv->activity); - - g_signal_connect_swapped ( - proxy->priv->cancel, "clicked", - G_CALLBACK (activity_proxy_cancel), proxy->priv->activity); - - g_signal_connect_swapped ( - proxy->priv->activity, "cancelled", - G_CALLBACK (activity_proxy_update), proxy); - - g_signal_connect_swapped ( - proxy->priv->activity, "completed", - G_CALLBACK (activity_proxy_update), proxy); - - g_signal_connect_swapped ( - proxy->priv->activity, "notify", - G_CALLBACK (activity_proxy_update), proxy); - - activity_proxy_update (proxy); -} - -static void e_activity_proxy_class_init (EActivityProxyClass *class) { GObjectClass *object_class; @@ -244,7 +244,6 @@ e_activity_proxy_class_init (EActivityProxyClass *class) object_class->set_property = activity_proxy_set_property; object_class->get_property = activity_proxy_get_property; object_class->dispose = activity_proxy_dispose; - object_class->constructed = activity_proxy_constructed; g_object_class_install_property ( object_class, @@ -255,7 +254,7 @@ e_activity_proxy_class_init (EActivityProxyClass *class) NULL, E_TYPE_ACTIVITY, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_CONSTRUCT)); } static void @@ -283,37 +282,42 @@ e_activity_proxy_init (EActivityProxy *proxy) widget = gtk_image_new (); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - proxy->priv->image = g_object_ref (widget); - gtk_widget_hide (widget); - - widget = gtk_button_new (); - gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - proxy->priv->button = g_object_ref (widget); - gtk_widget_hide (widget); + proxy->priv->image = widget; widget = gtk_spinner_new (); gtk_spinner_start (GTK_SPINNER (widget)); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 3); - proxy->priv->spinner = g_object_ref (widget); - gtk_widget_show (widget); + proxy->priv->spinner = widget; + + /* The spinner is only visible when the image is not. */ + g_object_bind_property ( + proxy->priv->image, "visible", + proxy->priv->spinner, "visible", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE | + G_BINDING_INVERT_BOOLEAN); widget = gtk_label_new (NULL); - gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); - proxy->priv->label = g_object_ref (widget); + proxy->priv->label = widget; gtk_widget_show (widget); + /* This is only shown if the EActivity has a GCancellable. */ widget = gtk_button_new (); gtk_button_set_image ( GTK_BUTTON (widget), gtk_image_new_from_stock ( - GTK_STOCK_STOP, GTK_ICON_SIZE_MENU)); + GTK_STOCK_CANCEL, GTK_ICON_SIZE_MENU)); gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); gtk_widget_set_tooltip_text (widget, _("Cancel")); - proxy->priv->cancel = g_object_ref (widget); + proxy->priv->cancel = widget; gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (activity_proxy_cancel), proxy); } GtkWidget * @@ -322,8 +326,7 @@ e_activity_proxy_new (EActivity *activity) g_return_val_if_fail (E_IS_ACTIVITY (activity), NULL); return g_object_new ( - E_TYPE_ACTIVITY_PROXY, - "activity", activity, NULL); + E_TYPE_ACTIVITY_PROXY, "activity", activity, NULL); } EActivity * @@ -333,3 +336,47 @@ e_activity_proxy_get_activity (EActivityProxy *proxy) return proxy->priv->activity; } + +void +e_activity_proxy_set_activity (EActivityProxy *proxy, + EActivity *activity) +{ + g_return_if_fail (E_IS_ACTIVITY_PROXY (proxy)); + + if (activity != NULL) + g_return_if_fail (E_IS_ACTIVITY (activity)); + + if (proxy->priv->timeout_id > 0) { + g_source_remove (proxy->priv->timeout_id); + proxy->priv->timeout_id = 0; + } + + if (proxy->priv->activity != NULL) { + g_signal_handlers_disconnect_matched ( + proxy->priv->activity, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, proxy); + g_object_weak_unref ( + G_OBJECT (proxy->priv->activity), + (GWeakNotify) activity_proxy_weak_notify_cb, proxy); + } + + proxy->priv->activity = activity; + + if (activity != NULL) { + g_object_weak_ref ( + G_OBJECT (activity), (GWeakNotify) + activity_proxy_weak_notify_cb, proxy); + + g_signal_connect_swapped ( + activity, "notify::state", + G_CALLBACK (activity_proxy_feedback), proxy); + + g_signal_connect_swapped ( + activity, "notify", + G_CALLBACK (activity_proxy_update), proxy); + } + + activity_proxy_update (proxy); + + g_object_notify (G_OBJECT (proxy), "activity"); +} diff --git a/widgets/misc/e-activity-proxy.h b/widgets/misc/e-activity-proxy.h index 8844988e3d..cb44d6b025 100644 --- a/widgets/misc/e-activity-proxy.h +++ b/widgets/misc/e-activity-proxy.h @@ -62,6 +62,8 @@ struct _EActivityProxyClass { GType e_activity_proxy_get_type (void); GtkWidget * e_activity_proxy_new (EActivity *activity); EActivity * e_activity_proxy_get_activity (EActivityProxy *proxy); +void e_activity_proxy_set_activity (EActivityProxy *proxy, + EActivity *activity); G_END_DECLS |