diff options
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 |