From 54b80a7271e8ce1b2f3ccc68bb553940a24b80e2 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Fri, 17 Oct 2008 03:48:03 +0000 Subject: Get the mail folder tree compiling, though I'm not yet sure why it's not showing anything. Probably something stupid. Also enabled the composer. svn path=/branches/kill-bonobo/; revision=36623 --- widgets/misc/e-activity-proxy.c | 59 ++++++--- widgets/misc/e-activity.c | 264 +++++++++++++++++++++++++++++++++++++++- widgets/misc/e-activity.h | 18 ++- 3 files changed, 320 insertions(+), 21 deletions(-) (limited to 'widgets') diff --git a/widgets/misc/e-activity-proxy.c b/widgets/misc/e-activity-proxy.c index 56b8ed33d4..6ce89016cd 100644 --- a/widgets/misc/e-activity-proxy.c +++ b/widgets/misc/e-activity-proxy.c @@ -30,9 +30,10 @@ struct _EActivityProxyPrivate { EActivity *activity; + GtkWidget *button; GtkWidget *image; GtkWidget *label; - GtkWidget *button; + GtkWidget *cancel; GtkWidget *spinner; }; @@ -50,12 +51,14 @@ activity_proxy_update (EActivityProxy *proxy) const gchar *icon_name; gboolean cancellable; gboolean cancelled; + gboolean clickable; gboolean completed; gboolean sensitive; gchar *description; cancellable = e_activity_get_cancellable (activity); cancelled = e_activity_is_cancelled (activity); + clickable = e_activity_get_clickable (activity); completed = e_activity_is_completed (activity); icon_name = e_activity_get_icon_name (activity); @@ -64,26 +67,39 @@ activity_proxy_update (EActivityProxy *proxy) gtk_label_set_text (GTK_LABEL (proxy->priv->label), description); 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) { 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)); e_spinner_stop (E_SPINNER (proxy->priv->spinner)); - gtk_widget_show (proxy->priv->image); 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); + } } else { e_spinner_start (E_SPINNER (proxy->priv->spinner)); gtk_widget_show (proxy->priv->spinner); + gtk_widget_hide (proxy->priv->button); gtk_widget_hide (proxy->priv->image); } if (cancellable) - gtk_widget_show (proxy->priv->button); + gtk_widget_show (proxy->priv->cancel); else - gtk_widget_hide (proxy->priv->button); + gtk_widget_hide (proxy->priv->cancel); sensitive = !(cancelled || completed); - gtk_widget_set_sensitive (proxy->priv->button, sensitive); + gtk_widget_set_sensitive (proxy->priv->cancel, sensitive); } static void @@ -141,6 +157,11 @@ activity_proxy_dispose (GObject *object) priv->activity = NULL; } + if (priv->button != NULL) { + g_object_unref (priv->button); + priv->image = NULL; + } + if (priv->image != NULL) { g_object_unref (priv->image); priv->image = NULL; @@ -151,9 +172,9 @@ activity_proxy_dispose (GObject *object) priv->label = NULL; } - if (priv->button != NULL) { - g_object_unref (priv->button); - priv->button = NULL; + if (priv->cancel != NULL) { + g_object_unref (priv->cancel); + priv->cancel = NULL; } if (priv->spinner != NULL) { @@ -174,6 +195,10 @@ activity_proxy_constructed (GObject *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 (e_activity_cancel), proxy->priv->activity); g_signal_connect_swapped ( @@ -240,18 +265,24 @@ activity_proxy_init (EActivityProxy *proxy) container = widget; + 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_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + proxy->priv->button = g_object_ref (widget); + gtk_widget_hide (widget); + widget = e_spinner_new (); e_spinner_set_size (E_SPINNER (widget), GTK_ICON_SIZE_MENU); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); proxy->priv->spinner = g_object_ref (widget); gtk_widget_show (widget); - 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_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_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); proxy->priv->label = g_object_ref (widget); @@ -264,7 +295,7 @@ activity_proxy_init (EActivityProxy *proxy) 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->button = g_object_ref (widget); + proxy->priv->cancel = g_object_ref (widget); gtk_widget_show (widget); } diff --git a/widgets/misc/e-activity.c b/widgets/misc/e-activity.c index 434225a5a2..7905c4062f 100644 --- a/widgets/misc/e-activity.c +++ b/widgets/misc/e-activity.c @@ -32,14 +32,20 @@ struct _EActivityPrivate { gchar *primary_text; gchar *secondary_text; gdouble percent; - gboolean cancellable; - guint cancelled : 1; - guint completed : 1; + guint timeout_id; + + guint blocking : 1; + guint cancellable : 1; + guint cancelled : 1; + guint clickable : 1; + guint completed : 1; }; enum { PROP_0, + PROP_BLOCKING, PROP_CANCELLABLE, + PROP_CLICKABLE, PROP_ICON_NAME, PROP_PERCENT, PROP_PRIMARY_TEXT, @@ -48,13 +54,23 @@ enum { enum { CANCELLED, + CLICKED, COMPLETED, + TIMEOUT, LAST_SIGNAL }; static gpointer parent_class; static gulong signals[LAST_SIGNAL]; +static gboolean +activity_timeout_cb (EActivity *activity) +{ + g_signal_emit (activity, signals[TIMEOUT], 0); + + return FALSE; +} + static void activity_set_property (GObject *object, guint property_id, @@ -62,12 +78,24 @@ activity_set_property (GObject *object, GParamSpec *pspec) { switch (property_id) { + case PROP_BLOCKING: + e_activity_set_blocking ( + E_ACTIVITY (object), + g_value_get_boolean (value)); + return; + case PROP_CANCELLABLE: e_activity_set_cancellable ( E_ACTIVITY (object), g_value_get_boolean (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), @@ -103,12 +131,24 @@ activity_get_property (GObject *object, GParamSpec *pspec) { switch (property_id) { + case PROP_BLOCKING: + g_value_set_boolean ( + value, e_activity_get_blocking ( + E_ACTIVITY (object))); + return; + case PROP_CANCELLABLE: g_value_set_boolean ( value, e_activity_get_cancellable ( 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 ( @@ -148,6 +188,9 @@ activity_finalize (GObject *object) g_free (priv->primary_text); g_free (priv->secondary_text); + if (priv->timeout_id > 0) + g_source_remove (priv->timeout_id); + /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -165,6 +208,17 @@ activity_class_init (EActivityClass *class) object_class->get_property = activity_get_property; object_class->finalize = activity_finalize; + g_object_class_install_property ( + object_class, + PROP_BLOCKING, + g_param_spec_boolean ( + "blocking", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + g_object_class_install_property ( object_class, PROP_CANCELLABLE, @@ -176,6 +230,17 @@ activity_class_init (EActivityClass *class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + 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, @@ -225,7 +290,15 @@ activity_class_init (EActivityClass *class) signals[CANCELLED] = g_signal_new ( "cancelled", G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + 0, 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, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); @@ -233,7 +306,15 @@ activity_class_init (EActivityClass *class) signals[COMPLETED] = g_signal_new ( "completed", G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[TIMEOUT] = g_signal_new ( + "timeout", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); @@ -310,6 +391,14 @@ e_activity_complete (EActivity *activity) 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) { @@ -336,7 +425,7 @@ e_activity_describe (EActivity *activity) } else if (percent < 0.0) { /* Translators: This is an activity whose percent * complete is unknown. */ - g_string_printf (string, _("%s (...)"), text); + g_string_printf (string, _("%s..."), text); } else { /* Translators: This is an activity whose percent * complete is known. */ @@ -364,6 +453,48 @@ e_activity_is_completed (EActivity *activity) return activity->priv->completed; } +void +e_activity_add_timeout (EActivity *activity, + guint seconds) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + e_activity_cancel_timeout (activity); + + activity->priv->timeout_id = g_timeout_add_seconds ( + seconds, (GSourceFunc) activity_timeout_cb, activity); +} + +void +e_activity_cancel_timeout (EActivity *activity) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + if (activity->priv->timeout_id > 0) { + g_source_remove (activity->priv->timeout_id); + activity->priv->timeout_id = 0; + } +} + +gboolean +e_activity_get_blocking (EActivity *activity) +{ + g_return_val_if_fail (E_IS_ACTIVITY (activity), FALSE); + + return activity->priv->blocking; +} + +void +e_activity_set_blocking (EActivity *activity, + gboolean blocking) +{ + g_return_if_fail (E_IS_ACTIVITY (activity)); + + activity->priv->blocking = blocking; + + g_object_notify (G_OBJECT (activity), "blocking"); +} + gboolean e_activity_get_cancellable (EActivity *activity) { @@ -383,6 +514,25 @@ 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) { @@ -461,3 +611,105 @@ e_activity_set_secondary_text (EActivity *activity, g_object_notify (G_OBJECT (activity), "secondary-text"); } + +/************************* Error Dialog Integration **************************/ + +void +e_activity_error (EActivity *activity, + GtkWidget *error_dialog) +{ + GObject *object; + const gchar *primary_text; + const gchar *secondary_text; + + /* XXX Convert an activity to a clickable error message. + * Clicking on the activity completes it and displays + * the error dialog. Eventually I'd like to eliminate + * error dialogs altogether and show errors directly + * in the shell window. */ + + g_return_if_fail (E_IS_ACTIVITY (activity)); + g_return_if_fail (GTK_IS_DIALOG (error_dialog)); + + object = G_OBJECT (error_dialog); + primary_text = g_object_get_data (object, "primary"); + secondary_text = g_object_get_data (object, "secondary"); + + e_activity_set_primary_text (activity, primary_text); + e_activity_set_secondary_text (activity, secondary_text); + e_activity_set_icon_name (activity, "dialog-warning"); + e_activity_set_clickable (activity, TRUE); + + g_signal_connect ( + activity, "cancelled", + G_CALLBACK (e_activity_cancel_timeout), NULL); + + g_signal_connect ( + activity, "completed", + G_CALLBACK (e_activity_cancel_timeout), NULL); + + g_signal_connect ( + activity, "clicked", + G_CALLBACK (e_activity_complete), NULL); + + g_signal_connect_swapped ( + activity, "clicked", + G_CALLBACK (gtk_dialog_run), error_dialog); + + g_signal_connect ( + activity, "timeout", + G_CALLBACK (e_activity_complete), NULL); + + /* XXX Allow for a configurable timeout. */ + e_activity_add_timeout (activity, 60); +} + +void +e_activity_info (EActivity *activity, + GtkWidget *info_dialog) +{ + GObject *object; + const gchar *primary_text; + const gchar *secondary_text; + + /* XXX Convert an activity to a clickable info message. + * Clicking on the activity completes it and displays + * the info dialog. Eventually I'd like to eliminate + * info dialogs altogether and show errors directly + * in the shell window. */ + + g_return_if_fail (E_IS_ACTIVITY (activity)); + g_return_if_fail (GTK_IS_DIALOG (info_dialog)); + + object = G_OBJECT (info_dialog); + primary_text = g_object_get_data (object, "primary"); + secondary_text = g_object_get_data (object, "secondary"); + + e_activity_set_primary_text (activity, primary_text); + e_activity_set_secondary_text (activity, secondary_text); + e_activity_set_icon_name (activity, "dialog-warning"); + e_activity_set_clickable (activity, TRUE); + + g_signal_connect ( + activity, "cancelled", + G_CALLBACK (e_activity_cancel_timeout), NULL); + + g_signal_connect ( + activity, "completed", + G_CALLBACK (e_activity_cancel_timeout), NULL); + + g_signal_connect ( + activity, "clicked", + G_CALLBACK (e_activity_complete), NULL); + + g_signal_connect_swapped ( + activity, "clicked", + G_CALLBACK (gtk_dialog_run), info_dialog); + + g_signal_connect ( + activity, "timeout", + G_CALLBACK (e_activity_complete), NULL); + + /* XXX Allow for a configurable timeout. */ + e_activity_add_timeout (activity, 60); +} diff --git a/widgets/misc/e-activity.h b/widgets/misc/e-activity.h index 48a19ff91d..d949860333 100644 --- a/widgets/misc/e-activity.h +++ b/widgets/misc/e-activity.h @@ -22,7 +22,7 @@ #ifndef E_ACTIVITY_H #define E_ACTIVITY_H -#include +#include /* Standard GObject macros */ #define E_TYPE_ACTIVITY \ @@ -62,12 +62,22 @@ GType e_activity_get_type (void); EActivity * e_activity_new (const gchar *primary_text); void e_activity_cancel (EActivity *activity); void e_activity_complete (EActivity *activity); +void e_activity_clicked (EActivity *activity); gchar * e_activity_describe (EActivity *activity); gboolean e_activity_is_cancelled (EActivity *activity); gboolean e_activity_is_completed (EActivity *activity); +void e_activity_add_timeout (EActivity *activity, + guint seconds); +void e_activity_cancel_timeout (EActivity *activity); +gboolean e_activity_get_blocking (EActivity *activity); +void e_activity_set_blocking (EActivity *activity, + gboolean blocking); gboolean e_activity_get_cancellable (EActivity *activity); void e_activity_set_cancellable (EActivity *activity, gboolean 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); @@ -81,6 +91,12 @@ const gchar * e_activity_get_secondary_text (EActivity *activity); void e_activity_set_secondary_text (EActivity *activity, const gchar *secondary_text); +/* XXX Hacky integration with error dialogs. */ +void e_activity_error (EActivity *activity, + GtkWidget *error_dialog); +void e_activity_info (EActivity *activity, + GtkWidget *info_dialog); + G_END_DECLS #endif /* E_ACTIVITY_H */ -- cgit v1.2.3