diff options
Diffstat (limited to 'e-util')
-rw-r--r-- | e-util/Makefile.am | 2 | ||||
-rw-r--r-- | e-util/e-alert-activity.c | 17 | ||||
-rw-r--r-- | e-util/e-alert-dialog.c | 107 | ||||
-rw-r--r-- | e-util/e-alert-sink.c | 92 | ||||
-rw-r--r-- | e-util/e-alert-sink.h | 62 | ||||
-rw-r--r-- | e-util/e-alert.c | 595 | ||||
-rw-r--r-- | e-util/e-alert.h | 31 |
7 files changed, 592 insertions, 314 deletions
diff --git a/e-util/Makefile.am b/e-util/Makefile.am index f1c6131965..4b08698896 100644 --- a/e-util/Makefile.am +++ b/e-util/Makefile.am @@ -14,6 +14,7 @@ eutilinclude_HEADERS = \ e-alert.h \ e-alert-activity.h \ e-alert-dialog.h \ + e-alert-sink.h \ e-binding.h \ e-bit-array.h \ e-categories-config.h \ @@ -93,6 +94,7 @@ libeutil_la_SOURCES = \ e-alert.c \ e-alert-activity.c \ e-alert-dialog.c \ + e-alert-sink.c \ e-binding.c \ e-bit-array.c \ e-categories-config.c \ diff --git a/e-util/e-alert-activity.c b/e-util/e-alert-activity.c index 8e6a6f78e5..3a97a4eab4 100644 --- a/e-util/e-alert-activity.c +++ b/e-util/e-alert-activity.c @@ -109,23 +109,22 @@ alert_activity_constructed (GObject *object) EAlertActivity *alert_activity; EAlert *alert; GtkWidget *message_dialog; - gchar *primary_text; - gchar *secondary_text; + const gchar *primary_text; + const gchar *secondary_text; + activity = E_ACTIVITY (object); alert_activity = E_ALERT_ACTIVITY (object); - message_dialog = e_alert_activity_get_message_dialog (alert_activity); + message_dialog = e_alert_activity_get_message_dialog (alert_activity); alert = e_alert_dialog_get_alert (E_ALERT_DIALOG (message_dialog)); - primary_text = e_alert_get_primary_text (alert, FALSE); - secondary_text = e_alert_get_secondary_text (alert, FALSE); - g_object_unref (alert); - activity = E_ACTIVITY (alert_activity); + primary_text = e_alert_get_primary_text (alert); e_activity_set_primary_text (activity, primary_text); + + secondary_text = e_alert_get_secondary_text (alert); e_activity_set_secondary_text (activity, secondary_text); - g_free (primary_text); - g_free (secondary_text); + g_object_unref (alert); /* This is a constructor property, so can't do it in init(). * XXX What we really want to do is override the property's diff --git a/e-util/e-alert-dialog.c b/e-util/e-alert-dialog.c index 1aa238cdcc..0057ed91aa 100644 --- a/e-util/e-alert-dialog.c +++ b/e-util/e-alert-dialog.c @@ -113,17 +113,21 @@ e_alert_dialog_constructed (GObject *obj) EAlertDialog *self = (EAlertDialog*) obj; EAlert *alert; struct _e_alert_button *b; - GtkWidget *hbox, *w, *scroll=NULL; GtkWidget *action_area; GtkWidget *content_area; - GString *out; - gchar *title, *primary, *secondary; + GtkWidget *container; + GtkWidget *widget; + PangoAttribute *attr; + PangoAttrList *list; + const gchar *primary, *secondary; g_return_if_fail (self != NULL); self->priv = ALERT_DIALOG_PRIVATE (self); alert = self->priv->alert; + gtk_window_set_title (GTK_WINDOW (self), " "); + action_area = gtk_dialog_get_action_area ((GtkDialog*) self); content_area = gtk_dialog_get_content_area ((GtkDialog*) self); @@ -142,8 +146,6 @@ e_alert_dialog_constructed (GObject *obj) "Something called %s() with a NULL parent window. " "This is no longer legal, please fix it.", G_STRFUNC); - if (e_alert_get_flags (alert) & GTK_DIALOG_MODAL) - gtk_window_set_modal ((GtkWindow *)self, TRUE); gtk_window_set_destroy_with_parent ((GtkWindow *)self, TRUE); b = e_alert_peek_buttons (alert); @@ -174,56 +176,51 @@ e_alert_dialog_constructed (GObject *obj) gtk_dialog_set_default_response ((GtkDialog*) self, e_alert_get_default_response (alert)); - hbox = gtk_hbox_new (FALSE, 0); - gtk_container_set_border_width ((GtkContainer *)hbox, 12); - - w = gtk_image_new_from_stock - (e_alert_peek_stock_image (alert), GTK_ICON_SIZE_DIALOG); - gtk_misc_set_alignment ((GtkMisc *)w, 0.0, 0.0); - gtk_box_pack_start ((GtkBox *)hbox, w, FALSE, FALSE, 12); - - title = e_alert_get_title (alert, FALSE); - gtk_window_set_title ((GtkWindow *)self, title); - - out = g_string_new (""); - primary = e_alert_get_primary_text (alert, TRUE); - if (primary) { - g_string_append_printf (out, - "<span weight=\"bold\" size=\"larger\">%s</span>\n\n", - primary); - } - - secondary = e_alert_get_secondary_text (alert, TRUE); - if (secondary) { - g_string_append (out, secondary); - } - - g_free (secondary); - g_free (title); - g_free (primary); - - if (e_alert_get_scroll (alert)) { - scroll = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy ( - GTK_SCROLLED_WINDOW (scroll), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - } - w = gtk_label_new (NULL); - gtk_label_set_selectable ((GtkLabel *)w, TRUE); - gtk_label_set_line_wrap ((GtkLabel *)w, TRUE); - gtk_label_set_markup ((GtkLabel *)w, out->str); - gtk_widget_set_can_focus (w, FALSE); - g_string_free (out, TRUE); - if (e_alert_get_scroll (alert)) { - gtk_scrolled_window_add_with_viewport ((GtkScrolledWindow *)scroll, w); - gtk_box_pack_start ((GtkBox *)hbox, scroll, FALSE, FALSE, 0); - gtk_window_set_default_size ((GtkWindow *)self, 360, 180); - } else - gtk_box_pack_start ((GtkBox *)hbox, w, TRUE, TRUE, 0); - - gtk_widget_show_all (hbox); - - gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0); + widget = gtk_hbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (widget), 12); + gtk_box_pack_start (GTK_BOX (content_area), widget, TRUE, TRUE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = e_alert_create_image (alert, GTK_ICON_SIZE_DIALOG); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + widget = gtk_vbox_new (FALSE, 12); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + primary = e_alert_get_primary_text (alert); + secondary = e_alert_get_secondary_text (alert); + + list = pango_attr_list_new (); + attr = pango_attr_scale_new (PANGO_SCALE_LARGE); + pango_attr_list_insert (list, attr); + attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); + pango_attr_list_insert (list, attr); + + widget = gtk_label_new (primary); + gtk_label_set_attributes (GTK_LABEL (widget), list); + gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE); + gtk_label_set_selectable (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_set_can_focus (widget, FALSE); + gtk_widget_show (widget); + + widget = gtk_label_new (secondary); + gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE); + gtk_label_set_selectable (GTK_LABEL (widget), TRUE); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_set_can_focus (widget, FALSE); + gtk_widget_show (widget); + + pango_attr_list_unref (list); } static void diff --git a/e-util/e-alert-sink.c b/e-util/e-alert-sink.c new file mode 100644 index 0000000000..de676ea778 --- /dev/null +++ b/e-util/e-alert-sink.c @@ -0,0 +1,92 @@ +/* + * e-alert-sink.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/> + * + */ + +/** + * SECTION: e-alert-sink + * @short_description: an interface to handle alerts + * @include: e-util/e-alert-sink.h + * + * A widget that implements #EAlertSink means it can handle #EAlerts, + * usually by displaying them to the user. + **/ + +#include "e-alert-sink.h" + +#include "e-alert-dialog.h" + +G_DEFINE_INTERFACE ( + EAlertSink, + e_alert_sink, + GTK_TYPE_WIDGET) + +static void +alert_sink_submit_alert (EAlertSink *alert_sink, + EAlert *alert) +{ + GtkWidget *dialog; + gpointer parent; + + /* This is just a lame fallback handler. Implementors + * are strongly encouraged to override this method. */ + + parent = gtk_widget_get_toplevel (GTK_WIDGET (alert_sink)); + parent = gtk_widget_is_toplevel (parent) ? parent : NULL; + + dialog = e_alert_dialog_new (parent, alert); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); +} + +static void +e_alert_sink_default_init (EAlertSinkInterface *interface) +{ + interface->submit_alert = alert_sink_submit_alert; +} + +/** + * e_alert_sink_submit_alert: + * @widget: a #GtkWidget, either itself an #EAlertSink or a child of one + * @alert: an #EAlert + * + * This function is a place to pass #EAlert objects. Beyond that it has no + * well-defined behavior. It's up to the widget implementing the #EAlertSink + * interface to decide what to do with them. + * + * Either @widget or one of its parents must implement #EAlertSink. + * + * The default behavior is to display the @alert in a dialog. + **/ +void +e_alert_sink_submit_alert (GtkWidget *widget, + EAlert *alert) +{ + EAlertSinkInterface *interface; + + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (E_IS_ALERT (alert)); + + while (widget != NULL && !E_IS_ALERT_SINK (widget)) + widget = gtk_widget_get_parent (widget); + + g_return_if_fail (E_IS_ALERT_SINK (widget)); + + interface = E_ALERT_SINK_GET_INTERFACE (widget); + g_return_if_fail (interface->submit_alert != NULL); + + interface->submit_alert (E_ALERT_SINK (widget), alert); +} diff --git a/e-util/e-alert-sink.h b/e-util/e-alert-sink.h new file mode 100644 index 0000000000..35c56f95b1 --- /dev/null +++ b/e-util/e-alert-sink.h @@ -0,0 +1,62 @@ +/* + * e-alert-sink.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_ALERT_SINK_H +#define E_ALERT_SINK_H + +#include <gtk/gtk.h> +#include <e-util/e-alert.h> + +/* Standard GObject macros */ +#define E_TYPE_ALERT_SINK \ + (e_alert_sink_get_type ()) +#define E_ALERT_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ALERT_SINK, EAlertSink)) +#define E_ALERT_SINK_INTERFACE(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ALERT_SINK, EAlertSinkInterface)) +#define E_IS_ALERT_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ALERT_SINK)) +#define E_IS_ALERT_SINK_INTERFACE(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_ALERT_SINK)) +#define E_ALERT_SINK_GET_INTERFACE(obj) \ + (G_TYPE_INSTANCE_GET_INTERFACE \ + ((obj), E_TYPE_ALERT_SINK, EAlertSinkInterface)) + +G_BEGIN_DECLS + +typedef struct _EAlertSink EAlertSink; +typedef struct _EAlertSinkInterface EAlertSinkInterface; + +struct _EAlertSinkInterface { + GTypeInterface parent_interface; + + void (*submit_alert) (EAlertSink *alert_sink, + EAlert *alert); +}; + +GType e_alert_sink_get_type (void); +void e_alert_sink_submit_alert (GtkWidget *widget, + EAlert *alert); + +G_END_DECLS + +#endif /* E_ALERT_SINK_H */ diff --git a/e-util/e-alert.c b/e-util/e-alert.c index 49ba6af36b..65ab57bd8f 100644 --- a/e-util/e-alert.c +++ b/e-util/e-alert.c @@ -38,6 +38,7 @@ #include "e-util.h" #include "e-util-private.h" #include "e-alert.h" +#include "e-alert-sink.h" #define d(x) @@ -46,14 +47,11 @@ ((obj), E_TYPE_ALERT, EAlertPrivate)) struct _e_alert { - guint32 flags; const gchar *id; - gint type; + GtkMessageType message_type; gint default_response; - const gchar *title; - const gchar *primary; - const gchar *secondary; - gboolean scroll; + const gchar *primary_text; + const gchar *secondary_text; struct _e_alert_button *buttons; }; @@ -72,12 +70,10 @@ static struct _e_alert_button default_ok_button = { }; static struct _e_alert default_alerts[] = { - { GTK_DIALOG_MODAL, "error", 3, GTK_RESPONSE_OK, - N_("Evolution Error"), "{0}", "{1}", FALSE, - &default_ok_button }, - { GTK_DIALOG_MODAL, "warning", 1, GTK_RESPONSE_OK, - N_("Evolution Warning"), "{0}", "{1}", FALSE, - &default_ok_button } + { "error", GTK_MESSAGE_ERROR, GTK_RESPONSE_OK, + "{0}", "{1}", &default_ok_button }, + { "warning", GTK_MESSAGE_WARNING, GTK_RESPONSE_OK, + "{0}", "{1}", &default_ok_button } }; /* ********************************************************************** */ @@ -109,28 +105,16 @@ map_response (const gchar *name) return 0; } -static struct { - const gchar *name; - const gchar *icon; -} type_map[] = { - { "info", GTK_STOCK_DIALOG_INFO }, - { "warning", GTK_STOCK_DIALOG_WARNING }, - { "question", GTK_STOCK_DIALOG_QUESTION }, - { "error", GTK_STOCK_DIALOG_ERROR }, -}; - -static gint -map_type (const gchar *name) +static GtkMessageType +map_type (const gchar *nick) { - gint i; + GEnumClass *class; + GEnumValue *value; - if (name) { - for (i = 0; i < G_N_ELEMENTS (type_map); i++) - if (!strcmp (name, type_map[i].name)) - return i; - } + class = g_type_class_peek (GTK_TYPE_MESSAGE_TYPE); + value = g_enum_get_value_by_nick (class, nick); - return 3; + return (value != NULL) ? value->value : GTK_MESSAGE_ERROR; } G_DEFINE_TYPE ( @@ -140,22 +124,28 @@ G_DEFINE_TYPE ( enum { PROP_0, + PROP_ARGS, PROP_TAG, - PROP_ARGS + PROP_MESSAGE_TYPE, + PROP_PRIMARY_TEXT, + PROP_SECONDARY_TEXT }; struct _EAlertPrivate { gchar *tag; GPtrArray *args; + gchar *primary_text; + gchar *secondary_text; struct _e_alert *definition; + GtkMessageType message_type; + gint default_response; }; /* XML format: <error id="error-id" type="info|warning|question|error"? - response="default_response"? modal="true"? > - <title>Window Title</title>? + response="default_response"? > <primary>Primary error text.</primary>? <secondary>Secondary error text.</secondary>? <button stock="stock-button-id"? label="button label"? @@ -225,20 +215,12 @@ e_alert_load (const gchar *path) e = g_malloc0 (sizeof (*e)); e->id = g_strdup (tmp); - e->scroll = FALSE; xmlFree (tmp); lastbutton = (struct _e_alert_button *)&e->buttons; - tmp = (gchar *)xmlGetProp(error, (const guchar *)"modal"); - if (tmp) { - if (!strcmp(tmp, "true")) - e->flags |= GTK_DIALOG_MODAL; - xmlFree (tmp); - } - tmp = (gchar *)xmlGetProp(error, (const guchar *)"type"); - e->type = map_type (tmp); + e->message_type = map_type (tmp); if (tmp) xmlFree (tmp); @@ -248,27 +230,15 @@ e_alert_load (const gchar *path) xmlFree (tmp); } - tmp = (gchar *)xmlGetProp(error, (const guchar *)"scroll"); - if (tmp) { - if (!strcmp(tmp, "yes")) - e->scroll = TRUE; - xmlFree (tmp); - } - for (scan = error->children;scan;scan=scan->next) { if (!strcmp((gchar *)scan->name, "primary")) { if ((tmp = (gchar *)xmlNodeGetContent (scan))) { - e->primary = g_strdup (dgettext (table->translation_domain, tmp)); + e->primary_text = g_strdup (dgettext (table->translation_domain, tmp)); xmlFree (tmp); } } else if (!strcmp((gchar *)scan->name, "secondary")) { if ((tmp = (gchar *)xmlNodeGetContent (scan))) { - e->secondary = g_strdup (dgettext (table->translation_domain, tmp)); - xmlFree (tmp); - } - } else if (!strcmp((gchar *)scan->name, "title")) { - if ((tmp = (gchar *)xmlNodeGetContent (scan))) { - e->title = g_strdup (dgettext (table->translation_domain, tmp)); + e->secondary_text = g_strdup (dgettext (table->translation_domain, tmp)); xmlFree (tmp); } } else if (!strcmp((gchar *)scan->name, "button")) { @@ -361,120 +331,232 @@ e_alert_load_tables (void) g_free (base); } +static gchar * +alert_format_string (const gchar *format, + GPtrArray *args) +{ + GString *string; + const gchar *end, *newstart; + gint id; + + string = g_string_sized_new (strlen (format)); + + while (format + && (newstart = strchr (format, '{')) + && (end = strchr (newstart+1, '}'))) { + g_string_append_len (string, format, newstart - format); + id = atoi (newstart + 1); + if (id < args->len) { + g_string_append (string, args->pdata[id]); + } else + g_warning("Error references argument %d not supplied by caller", id); + format = end + 1; + } + + g_string_append (string, format); + + return g_string_free (string, FALSE); +} + static void -e_alert_get_property (GObject *object, guint property_id, - GValue *value, GParamSpec *pspec) +alert_set_tag (EAlert *alert, + const gchar *tag) { - EAlert *alert = (EAlert*) object; + struct _e_alert *definition; + struct _e_alert_table *table; + gchar *domain, *id; - switch (property_id) - { - case PROP_TAG: - g_value_set_string (value, alert->priv->tag); - break; - case PROP_ARGS: - g_value_set_boxed (value, alert->priv->args); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + alert->priv->tag = g_strdup (tag); + + g_return_if_fail (alert_table); + + domain = g_alloca (strlen (tag) + 1); + strcpy (domain, tag); + id = strchr (domain, ':'); + if (id) + *id++ = 0; + else { + g_warning ("Alert tag '%s' is missing a domain", tag); + return; } + + table = g_hash_table_lookup (alert_table, domain); + g_return_if_fail (table); + + definition = g_hash_table_lookup (table->alerts, id); + g_warn_if_fail (definition); + + alert->priv->definition = definition; + e_alert_set_message_type (alert, definition->message_type); + e_alert_set_default_response (alert, definition->default_response); } static void -e_alert_set_property (GObject *object, guint property_id, - const GValue *value, GParamSpec *pspec) +alert_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { EAlert *alert = (EAlert*) object; - switch (property_id) - { + switch (property_id) { case PROP_TAG: - alert->priv->tag = g_value_dup_string (value); - break; + alert_set_tag ( + E_ALERT (object), + g_value_get_string (value)); + return; + case PROP_ARGS: alert->priv->args = g_value_dup_boxed (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + return; + + case PROP_MESSAGE_TYPE: + e_alert_set_message_type ( + E_ALERT (object), + g_value_get_enum (value)); + return; + + case PROP_PRIMARY_TEXT: + e_alert_set_primary_text ( + E_ALERT (object), + g_value_get_string (value)); + return; + + case PROP_SECONDARY_TEXT: + e_alert_set_secondary_text ( + E_ALERT (object), + g_value_get_string (value)); + return; } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -e_alert_dispose (GObject *object) +alert_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { EAlert *alert = (EAlert*) object; - if (alert->priv->tag) { - g_free (alert->priv->tag); - alert->priv->tag = NULL; - } + switch (property_id) { + case PROP_TAG: + g_value_set_string (value, alert->priv->tag); + return; - if (alert->priv->args) { - /* arg strings will be freed automatically since we set a free func when - * creating the ptr array */ - g_boxed_free (G_TYPE_PTR_ARRAY, alert->priv->args); - alert->priv->args = NULL; + case PROP_ARGS: + g_value_set_boxed (value, alert->priv->args); + return; + + case PROP_MESSAGE_TYPE: + g_value_set_enum ( + value, e_alert_get_message_type ( + E_ALERT (object))); + return; + + case PROP_PRIMARY_TEXT: + g_value_set_string ( + value, e_alert_get_primary_text ( + E_ALERT (object))); + return; + + case PROP_SECONDARY_TEXT: + g_value_set_string ( + value, e_alert_get_secondary_text ( + E_ALERT (object))); + return; } - G_OBJECT_CLASS (e_alert_parent_class)->dispose (object); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -e_alert_constructed (GObject *obj) +alert_finalize (GObject *object) { - EAlert *alert = E_ALERT (obj); - - struct _e_alert_table *table; - gchar *domain, *id; - - g_return_if_fail (alert_table); - g_return_if_fail (alert->priv->tag); + EAlertPrivate *priv; - domain = g_alloca (strlen (alert->priv->tag)+1); - strcpy (domain, alert->priv->tag); - id = strchr (domain, ':'); - if (id) - *id++ = 0; - - table = g_hash_table_lookup (alert_table, domain); - g_return_if_fail (table); + priv = E_ALERT_GET_PRIVATE (object); - alert->priv->definition = g_hash_table_lookup (table->alerts, id); + g_free (priv->tag); + g_free (priv->primary_text); + g_free (priv->secondary_text); - g_warn_if_fail (alert->priv->definition); + g_ptr_array_free (priv->args, TRUE); + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_alert_parent_class)->finalize (object); } + static void -e_alert_class_init (EAlertClass *klass) +e_alert_class_init (EAlertClass *class) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (EAlertPrivate)); - - object_class->get_property = e_alert_get_property; - object_class->set_property = e_alert_set_property; - object_class->dispose = e_alert_dispose; - object_class->constructed = e_alert_constructed; - - g_object_class_install_property (object_class, - PROP_TAG, - g_param_spec_string ("tag", - "alert tag", - "A tag describing the alert", - "", - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (object_class, - PROP_ARGS, - g_param_spec_boxed ("args", - "Arguments", - "Arguments for formatting the alert", - G_TYPE_PTR_ARRAY, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); + GObjectClass *object_class = G_OBJECT_CLASS (class); + + g_type_class_add_private (class, sizeof (EAlertPrivate)); + + object_class->set_property = alert_set_property; + object_class->get_property = alert_get_property; + object_class->finalize = alert_finalize; + + g_object_class_install_property ( + object_class, + PROP_ARGS, + g_param_spec_boxed ( + "args", + "Arguments", + "Arguments for formatting the alert", + G_TYPE_PTR_ARRAY, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_TAG, + g_param_spec_string ( + "tag", + "alert tag", + "A tag describing the alert", + "", + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_MESSAGE_TYPE, + g_param_spec_enum ( + "message-type", + NULL, + NULL, + GTK_TYPE_MESSAGE_TYPE, + GTK_MESSAGE_ERROR, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_PRIMARY_TEXT, + g_param_spec_string ( + "primary-text", + NULL, + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_SECONDARY_TEXT, + g_param_spec_string ( + "secondary-text", + NULL, + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); e_alert_load_tables (); } @@ -502,17 +584,17 @@ EAlert * e_alert_new (const gchar *tag, ...) { EAlert *e; - va_list ap; + va_list va; - va_start (ap, tag); - e = e_alert_new_valist (tag, ap); - va_end (ap); + va_start (va, tag); + e = e_alert_new_valist (tag, va); + va_end (va); return e; } EAlert * -e_alert_new_valist (const gchar *tag, va_list ap) +e_alert_new_valist (const gchar *tag, va_list va) { EAlert *alert; GPtrArray *args; @@ -520,10 +602,10 @@ e_alert_new_valist (const gchar *tag, va_list ap) args = g_ptr_array_new_with_free_func (g_free); - tmp = va_arg (ap, gchar *); + tmp = va_arg (va, gchar *); while (tmp) { g_ptr_array_add (args, g_strdup (tmp)); - tmp = va_arg (ap, gchar *); + tmp = va_arg (va, gchar *); } alert = e_alert_new_array (tag, args); @@ -539,138 +621,114 @@ e_alert_new_array (const gchar *tag, GPtrArray *args) return g_object_new (E_TYPE_ALERT, "tag", tag, "args", args, NULL); } -/* unfortunately, gmarkup_escape doesn't expose its gstring based api :( */ -static void -e_alert_append_text_escaped (GString *out, const gchar *text) +gint +e_alert_get_default_response (EAlert *alert) { - gchar *markup; + g_return_val_if_fail (E_IS_ALERT (alert), 0); - markup = g_markup_escape_text (text, -1); - g_string_append (out, markup); - g_free (markup); + return alert->priv->default_response; } -static void -e_alert_format_string (GString *out, - const gchar *fmt, - GPtrArray *args, - gboolean escape_args) +void +e_alert_set_default_response (EAlert *alert, + gint response_id) { - const gchar *end, *newstart; - gint id; + g_return_if_fail (E_IS_ALERT (alert)); - while (fmt - && (newstart = strchr (fmt, '{')) - && (end = strchr (newstart+1, '}'))) { - g_string_append_len (out, fmt, newstart-fmt); - id = atoi (newstart+1); - if (id < args->len) { - if (escape_args) - e_alert_append_text_escaped (out, args->pdata[id]); - else - g_string_append (out, args->pdata[id]); - } else - g_warning("Error references argument %d not supplied by caller", id); - fmt = end+1; - } - - g_string_append (out, fmt); + alert->priv->default_response = response_id; } -guint32 -e_alert_get_flags (EAlert *alert) +GtkMessageType +e_alert_get_message_type (EAlert *alert) { - g_return_val_if_fail (alert && alert->priv && alert->priv->definition, 0); - return alert->priv->definition->flags; -} + g_return_val_if_fail (E_IS_ALERT (alert), GTK_MESSAGE_OTHER); -const gchar * -e_alert_peek_stock_image (EAlert *alert) -{ - g_return_val_if_fail (alert && alert->priv && alert->priv->definition, NULL); - return type_map[alert->priv->definition->type].icon; + return alert->priv->message_type; } -gint -e_alert_get_default_response (EAlert *alert) +void +e_alert_set_message_type (EAlert *alert, + GtkMessageType message_type) { - g_return_val_if_fail (alert && alert->priv && alert->priv->definition, 0); - return alert->priv->definition->default_response; + g_return_if_fail (E_IS_ALERT (alert)); + + alert->priv->message_type = message_type; + + g_object_notify (G_OBJECT (alert), "message-type"); } -gchar * -e_alert_get_title (EAlert *alert, - gboolean escaped) +const gchar * +e_alert_get_primary_text (EAlert *alert) { - GString *formatted; + g_return_val_if_fail (E_IS_ALERT (alert), NULL); - g_return_val_if_fail (alert && alert->priv && alert->priv->definition, NULL); - - formatted = g_string_new (""); + if (alert->priv->primary_text != NULL) + goto exit; - if (alert->priv->definition->title != NULL) - e_alert_format_string ( - formatted, alert->priv->definition->title, - alert->priv->args, escaped); + if (alert->priv->definition == NULL) + goto exit; - return g_string_free (formatted, FALSE); -} + if (alert->priv->definition->primary_text == NULL) + goto exit; -gchar * -e_alert_get_primary_text (EAlert *alert, - gboolean escaped) -{ - GString *formatted; + if (alert->priv->args == NULL) + goto exit; - g_return_val_if_fail (alert && alert->priv, NULL); + alert->priv->primary_text = alert_format_string ( + alert->priv->definition->primary_text, + alert->priv->args); - formatted = g_string_new (""); +exit: + return alert->priv->primary_text; +} - if (alert->priv->definition != NULL) - if (alert->priv->definition->primary != NULL) { - e_alert_format_string ( - formatted, alert->priv->definition->primary, - alert->priv->args, escaped); - } else { - gchar *title; +void +e_alert_set_primary_text (EAlert *alert, + const gchar *primary_text) +{ + g_return_if_fail (E_IS_ALERT (alert)); - title = e_alert_get_title (alert, escaped); - g_string_append (formatted, title); - g_free (title); - } - else { - g_string_append_printf ( - formatted, - _("Internal error, unknown error '%s' requested"), - alert->priv->tag); - } + g_free (alert->priv->primary_text); + alert->priv->primary_text = g_strdup (primary_text); - return g_string_free (formatted, FALSE); + g_object_notify (G_OBJECT (alert), "primary-text"); } -gchar * -e_alert_get_secondary_text (EAlert *alert, - gboolean escaped) +const gchar * +e_alert_get_secondary_text (EAlert *alert) { - GString *formatted; + g_return_val_if_fail (E_IS_ALERT (alert), NULL); - g_return_val_if_fail (alert && alert->priv && alert->priv->definition, NULL); + if (alert->priv->secondary_text != NULL) + goto exit; + + if (alert->priv->definition == NULL) + goto exit; + + if (alert->priv->definition->secondary_text == NULL) + goto exit; - formatted = g_string_new (""); + if (alert->priv->args == NULL) + goto exit; - if (alert->priv->definition->secondary != NULL) - e_alert_format_string ( - formatted, alert->priv->definition->secondary, - alert->priv->args, escaped); + alert->priv->secondary_text = alert_format_string ( + alert->priv->definition->secondary_text, + alert->priv->args); - return g_string_free (formatted, FALSE); +exit: + return alert->priv->secondary_text; } -gboolean -e_alert_get_scroll (EAlert *alert) +void +e_alert_set_secondary_text (EAlert *alert, + const gchar *secondary_text) { - g_return_val_if_fail (alert && alert->priv && alert->priv->definition, FALSE); - return alert->priv->definition->scroll; + g_return_if_fail (E_IS_ALERT (alert)); + + g_free (alert->priv->secondary_text); + alert->priv->secondary_text = g_strdup (secondary_text); + + g_object_notify (G_OBJECT (alert), "secondary-text"); } struct _e_alert_button * @@ -679,3 +737,60 @@ e_alert_peek_buttons (EAlert *alert) g_return_val_if_fail (alert && alert->priv && alert->priv->definition, NULL); return alert->priv->definition->buttons; } + +GtkWidget * +e_alert_create_image (EAlert *alert, + GtkIconSize size) +{ + const gchar *stock_id; + + g_return_val_if_fail (E_IS_ALERT (alert), NULL); + + switch (e_alert_get_message_type (alert)) { + case GTK_MESSAGE_INFO: + stock_id = GTK_STOCK_DIALOG_INFO; + break; + case GTK_MESSAGE_WARNING: + stock_id = GTK_STOCK_DIALOG_WARNING; + break; + case GTK_MESSAGE_QUESTION: + stock_id = GTK_STOCK_DIALOG_QUESTION; + break; + case GTK_MESSAGE_ERROR: + stock_id = GTK_STOCK_DIALOG_ERROR; + break; + default: + stock_id = GTK_STOCK_MISSING_IMAGE; + g_warn_if_reached (); + break; + } + + return gtk_image_new_from_stock (stock_id, size); +} + +void +e_alert_submit (GtkWidget *widget, + const gchar *tag, + ...) +{ + va_list va; + + va_start (va, tag); + e_alert_submit_valist (widget, tag, va); + va_end (va); +} + +void +e_alert_submit_valist (GtkWidget *widget, + const gchar *tag, + va_list va) +{ + EAlert *alert; + + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (tag != NULL); + + alert = e_alert_new_valist (tag, va); + e_alert_sink_submit_alert (widget, alert); + g_object_unref (alert); +} diff --git a/e-util/e-alert.h b/e-util/e-alert.h index 4c515b53f4..7b07970361 100644 --- a/e-util/e-alert.h +++ b/e-util/e-alert.h @@ -81,21 +81,32 @@ GType e_alert_get_type (void); EAlert * e_alert_new (const gchar *tag, ...) G_GNUC_NULL_TERMINATED; EAlert * e_alert_new_valist (const gchar *tag, - va_list ap); + va_list va); EAlert * e_alert_new_array (const gchar *tag, GPtrArray *args); -guint32 e_alert_get_flags (EAlert *alert); -const gchar * e_alert_peek_stock_image (EAlert *alert); gint e_alert_get_default_response (EAlert *alert); -gchar * e_alert_get_title (EAlert *alert, - gboolean escaped); -gchar * e_alert_get_primary_text (EAlert *alert, - gboolean escaped); -gchar * e_alert_get_secondary_text (EAlert *alert, - gboolean escaped); -gboolean e_alert_get_scroll (EAlert *alert); +void e_alert_set_default_response (EAlert *alert, + gint response_id); +GtkMessageType e_alert_get_message_type (EAlert *alert); +void e_alert_set_message_type (EAlert *alert, + GtkMessageType message_type); +const gchar * e_alert_get_primary_text (EAlert *alert); +void e_alert_set_primary_text (EAlert *alert, + const gchar *primary_text); +const gchar * e_alert_get_secondary_text (EAlert *alert); +void e_alert_set_secondary_text (EAlert *alert, + const gchar *secondary_text); struct _e_alert_button * e_alert_peek_buttons (EAlert *alert); +GtkWidget * e_alert_create_image (EAlert *alert, + GtkIconSize size); + +void e_alert_submit (GtkWidget *widget, + const gchar *tag, + ...) G_GNUC_NULL_TERMINATED; +void e_alert_submit_valist (GtkWidget *widget, + const gchar *tag, + va_list va); G_END_DECLS |