[evolution] Messin around with EAlerts.



commit 0e4c54eddced72c9639001849148fe1813c5dc4e
Author: Matthew Barnes <mbarnes redhat com>
Date:   Wed Sep 29 21:11:44 2010 -0400

    Messin around with EAlerts.
    
    Trying out a new interface called EAlertSink.  The idea is to centralize
    how errors are shown to the user.  A GtkWindow subclass would implement
    the EAlertSink interface, which consists of a single method:
    
        void  (*submit_alert)  (EAlertSink *alert_sink, EAlert *alert);
    
    The subclass has complete control over what to do with the EAlert,
    although I imagine we'll wind up implementing various alert-handling
    policies as standalone widgets such as EAlertDialog.  I'd like to try
    an EAlertInfoBar.
    
    Code that would otherwise display an error dialog itself would instead
    pass the EAlert to an appropriate EAlertSink and be done with it.
    
    Nothing is final yet.  Still hacking on EAlert trying to find an API
    that feels right for these use cases.

 calendar/gui/dialogs/comp-editor.c          |   15 +-
 composer/e-msg-composer.c                   |    2 +
 doc/reference/shell/eshell-sections.txt     |    6 -
 doc/reference/shell/tmpl/e-alert.sgml       |   42 --
 doc/reference/shell/tmpl/eshell-unused.sgml |   36 ++
 e-util/Makefile.am                          |    2 +
 e-util/e-alert-activity.c                   |   17 +-
 e-util/e-alert-dialog.c                     |  107 +++---
 e-util/e-alert-sink.c                       |   92 ++++
 e-util/e-alert-sink.h                       |   62 +++
 e-util/e-alert.c                            |  595 ++++++++++++++++-----------
 e-util/e-alert.h                            |   31 +-
 widgets/misc/e-signature-editor.c           |   18 +-
 13 files changed, 648 insertions(+), 377 deletions(-)
---
diff --git a/calendar/gui/dialogs/comp-editor.c b/calendar/gui/dialogs/comp-editor.c
index 2213d47..63196ab 100644
--- a/calendar/gui/dialogs/comp-editor.c
+++ b/calendar/gui/dialogs/comp-editor.c
@@ -37,6 +37,7 @@
 #include <gdk/gdkkeysyms.h>
 #include <e-util/e-util.h>
 #include <e-util/e-binding.h>
+#include <e-util/e-alert-sink.h>
 #include <e-util/e-dialog-utils.h>
 #include <e-util/e-util-private.h>
 #include <e-util/gconf-bridge.h>
@@ -193,7 +194,9 @@ static void	page_dates_changed_cb		(CompEditor *editor,
 static void obj_modified_cb (ECal *client, GList *objs, CompEditor *editor);
 static void obj_removed_cb (ECal *client, GList *uids, CompEditor *editor);
 
-G_DEFINE_TYPE (CompEditor, comp_editor, GTK_TYPE_WINDOW)
+G_DEFINE_TYPE_WITH_CODE (
+	CompEditor, comp_editor, GTK_TYPE_WINDOW,
+	G_IMPLEMENT_INTERFACE (E_TYPE_ALERT_SINK, NULL))
 
 enum {
 	OBJECT_CREATED,
@@ -831,9 +834,8 @@ action_save_cb (GtkAction *action,
 	}
 
 	if (!e_cal_is_read_only (priv->client, &read_only, NULL) || read_only) {
-		e_alert_run_dialog_for_args (
-			(GtkWindow *) gtk_widget_get_toplevel (
-				GTK_WIDGET (editor)),
+		e_alert_submit (
+			GTK_WIDGET (editor),
 			"calendar:prompt-read-only-cal-editor",
 			e_source_peek_name (
 				e_cal_get_source (priv->client)),
@@ -1878,9 +1880,8 @@ prompt_and_save_changes (CompEditor *editor, gboolean send)
 	switch (save_component_dialog (GTK_WINDOW (editor), priv->comp)) {
 	case GTK_RESPONSE_YES: /* Save */
 		if (!e_cal_is_read_only (priv->client, &read_only, NULL) || read_only) {
-			e_alert_run_dialog_for_args (
-				(GtkWindow *) gtk_widget_get_toplevel (
-					GTK_WIDGET (editor)),
+			e_alert_submit (
+				GTK_WIDGET (editor),
 				"calendar:prompt-read-only-cal-editor",
 				e_source_peek_name (
 					e_cal_get_source (priv->client)),
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index f5f4778..d4e45d4 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -47,6 +47,7 @@
 
 #include "e-util/e-account-utils.h"
 #include "e-util/e-alert-dialog.h"
+#include "e-util/e-alert-sink.h"
 #include "e-util/e-dialog-utils.h"
 #include "e-util/e-extensible.h"
 #include "e-util/e-plugin-ui.h"
@@ -124,6 +125,7 @@ G_DEFINE_TYPE_WITH_CODE (
 	EMsgComposer,
 	e_msg_composer,
 	GTKHTML_TYPE_EDITOR,
+	G_IMPLEMENT_INTERFACE (E_TYPE_ALERT_SINK, NULL)
 	G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL))
 
 /**
diff --git a/doc/reference/shell/eshell-sections.txt b/doc/reference/shell/eshell-sections.txt
index d8b8a5c..3dc6eb1 100644
--- a/doc/reference/shell/eshell-sections.txt
+++ b/doc/reference/shell/eshell-sections.txt
@@ -511,12 +511,6 @@ EActivityProxyPrivate
 <SECTION>
 <FILE>e-alert</FILE>
 <TITLE>User Alert Handling</TITLE>
-E_ALERT_INFO
-E_ALERT_INFO_PRIMARY
-E_ALERT_WARNING
-E_ALERT_WARNING_PRIMARY
-E_ALERT_ERROR
-E_ALERT_ERROR_PRIMARY
 E_ALERT_ASK_FILE_EXISTS_OVERWRITE
 E_ALERT_NO_SAVE_FILE
 E_ALERT_NO_LOAD_FILE
diff --git a/doc/reference/shell/tmpl/e-alert.sgml b/doc/reference/shell/tmpl/e-alert.sgml
index 3666408..46df813 100644
--- a/doc/reference/shell/tmpl/e-alert.sgml
+++ b/doc/reference/shell/tmpl/e-alert.sgml
@@ -20,48 +20,6 @@ User Alert Handling
 <!-- ##### SECTION Image ##### -->
 
 
-<!-- ##### MACRO E_ALERT_INFO ##### -->
-<para>
-
-</para>
-
-
-
-<!-- ##### MACRO E_ALERT_INFO_PRIMARY ##### -->
-<para>
-
-</para>
-
-
-
-<!-- ##### MACRO E_ALERT_WARNING ##### -->
-<para>
-
-</para>
-
-
-
-<!-- ##### MACRO E_ALERT_WARNING_PRIMARY ##### -->
-<para>
-
-</para>
-
-
-
-<!-- ##### MACRO E_ALERT_ERROR ##### -->
-<para>
-
-</para>
-
-
-
-<!-- ##### MACRO E_ALERT_ERROR_PRIMARY ##### -->
-<para>
-
-</para>
-
-
-
 <!-- ##### MACRO E_ALERT_ASK_FILE_EXISTS_OVERWRITE ##### -->
 <para>
 
diff --git a/doc/reference/shell/tmpl/eshell-unused.sgml b/doc/reference/shell/tmpl/eshell-unused.sgml
index 59aed5d..1488652 100644
--- a/doc/reference/shell/tmpl/eshell-unused.sgml
+++ b/doc/reference/shell/tmpl/eshell-unused.sgml
@@ -88,6 +88,42 @@ e-shell-window.sgml
 </para>
 
 
+<!-- ##### MACRO E_ALERT_ERROR ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO E_ALERT_ERROR_PRIMARY ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO E_ALERT_INFO ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO E_ALERT_INFO_PRIMARY ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO E_ALERT_WARNING ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO E_ALERT_WARNING_PRIMARY ##### -->
+<para>
+
+</para>
+
+
 <!-- ##### MACRO E_SHELL_WINDOW_ACTION_SYNC_OPTIONS ##### -->
 <para>
 
diff --git a/e-util/Makefile.am b/e-util/Makefile.am
index f1c6131..4b08698 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 8e6a6f7..3a97a4e 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 1aa238c..0057ed9 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 0000000..de676ea
--- /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 0000000..35c56f9
--- /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 49ba6af..65ab57b 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 4c515b5..7b07970 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
 
diff --git a/widgets/misc/e-signature-editor.c b/widgets/misc/e-signature-editor.c
index 28c5819..effbf8b 100644
--- a/widgets/misc/e-signature-editor.c
+++ b/widgets/misc/e-signature-editor.c
@@ -25,6 +25,7 @@
 #include <glib/gi18n.h>
 
 #include <e-util/e-alert-dialog.h>
+#include <e-util/e-alert-sink.h>
 #include <e-util/e-signature-utils.h>
 #include <misc/e-web-view.h>
 
@@ -64,10 +65,11 @@ static const gchar *ui =
 "  </toolbar>\n"
 "</ui>";
 
-G_DEFINE_TYPE (
+G_DEFINE_TYPE_WITH_CODE (
 	ESignatureEditor,
 	e_signature_editor,
-	GTKHTML_TYPE_EDITOR)
+	GTKHTML_TYPE_EDITOR,
+	G_IMPLEMENT_INTERFACE (E_TYPE_ALERT_SINK, NULL))
 
 static void
 handle_error (GError **error)
@@ -150,8 +152,8 @@ action_save_and_close_cb (GtkAction *action,
 	gtkhtml_editor_save (GTKHTML_EDITOR (editor), filename, html, &error);
 
 	if (error != NULL) {
-		e_alert_run_dialog_for_args (
-			GTK_WINDOW (editor),
+		e_alert_submit (
+			GTK_WIDGET (editor),
 			"mail:no-save-signature",
 			error->message, NULL);
 		g_clear_error (&error);
@@ -165,8 +167,8 @@ action_save_and_close_cb (GtkAction *action,
 
 	/* Make sure the signature name is not blank. */
 	if (*signature_name == '\0') {
-		e_alert_run_dialog_for_args (
-			GTK_WINDOW (editor),
+		e_alert_submit (
+			GTK_WIDGET (editor),
 			"mail:blank-signature", NULL);
 		gtk_widget_grab_focus (entry);
 		g_free (signature_name);
@@ -178,8 +180,8 @@ action_save_and_close_cb (GtkAction *action,
 	same_name = (ESignature *) e_signature_list_find (
 		signature_list, E_SIGNATURE_FIND_NAME, signature_name);
 	if (same_name != NULL && !e_signature_is_equal (signature, same_name)) {
-		e_alert_run_dialog_for_args (
-			GTK_WINDOW (editor),
+		e_alert_submit (
+			GTK_WIDGET (editor),
 			"mail:signature-already-exists",
 			signature_name, NULL);
 		gtk_widget_grab_focus (entry);



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