From de169b4feeeaf2013aa256ddf70276bacbd6542a Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Tue, 10 Feb 2009 02:51:52 +0000 Subject: Rewrite the signature management UI from top to bottom. - Break the UI out of Glade and into small, manageable widgets: ESignatureEditor (moved from mail to widgets/misc) ESignatureManager ESignatureTreeView ESignatureScriptDialog - Move several signature utilities to e-util/e-signature-utils.c so they're accessible from widgets/misc without introducing circular dependences. - Have EMailShellModule listen for new GtkhtmlEditor windows (from which EMsgComposer and ESignatureEditor are derived) and configure the window with spelling and HTML editing user preferences. - Drastically simplifies em-composer-prefs.c. svn path=/branches/kill-bonobo/; revision=37239 --- composer/e-msg-composer.c | 126 +-- composer/e-msg-composer.h | 3 - configure.in | 2 +- e-util/e-signature-utils.c | 145 +++ e-util/e-signature-utils.h | 8 +- mail/Makefile.am | 2 - mail/e-mail-label-manager.c | 5 +- mail/e-mail-shell-module.c | 26 + mail/em-account-editor.c | 2 +- mail/em-composer-prefs.c | 467 +------- mail/em-composer-prefs.h | 13 - mail/mail-config.c | 60 - mail/mail-config.glade | 1750 ++++++++++++++---------------- mail/mail-config.h | 2 - mail/mail-signature-editor.c | 500 --------- mail/mail-signature-editor.h | 72 -- widgets/misc/Makefile.am | 8 + widgets/misc/e-signature-combo-box.c | 1 + widgets/misc/e-signature-combo-box.h | 1 + widgets/misc/e-signature-editor.c | 503 +++++++++ widgets/misc/e-signature-editor.h | 70 ++ widgets/misc/e-signature-manager.c | 746 +++++++++++++ widgets/misc/e-signature-manager.h | 100 ++ widgets/misc/e-signature-script-dialog.c | 463 ++++++++ widgets/misc/e-signature-script-dialog.h | 76 ++ widgets/misc/e-signature-tree-view.c | 405 +++++++ widgets/misc/e-signature-tree-view.h | 78 ++ 27 files changed, 3463 insertions(+), 2171 deletions(-) delete mode 100644 mail/mail-signature-editor.c delete mode 100644 mail/mail-signature-editor.h create mode 100644 widgets/misc/e-signature-editor.c create mode 100644 widgets/misc/e-signature-editor.h create mode 100644 widgets/misc/e-signature-manager.c create mode 100644 widgets/misc/e-signature-manager.h create mode 100644 widgets/misc/e-signature-script-dialog.c create mode 100644 widgets/misc/e-signature-script-dialog.h create mode 100644 widgets/misc/e-signature-tree-view.c create mode 100644 widgets/misc/e-signature-tree-view.h diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c index 8eb72649ac..0f91a34907 100644 --- a/composer/e-msg-composer.c +++ b/composer/e-msg-composer.c @@ -1068,103 +1068,6 @@ emcab_popup (EAttachmentBar *bar, GdkEventButton *event, int id) /* Signatures */ -static gchar * -get_file_content (EMsgComposer *composer, - const gchar *filename, - gboolean want_html, - guint flags, - gboolean warn) -{ - CamelStreamFilter *filtered_stream; - CamelStreamMem *memstream; - CamelMimeFilter *html, *charenc; - CamelStream *stream; - GByteArray *buffer; - gchar *charset; - gchar *content; - gint fd; - - fd = g_open (filename, O_RDONLY, 0); - if (fd == -1) { - if (warn) - e_error_run ((GtkWindow *)composer, "mail-composer:no-sig-file", - filename, g_strerror (errno), NULL); - return g_strdup (""); - } - - stream = camel_stream_fs_new_with_fd (fd); - - if (want_html) { - filtered_stream = camel_stream_filter_new_with_stream (stream); - camel_object_unref (stream); - - html = camel_mime_filter_tohtml_new (flags, 0); - camel_stream_filter_add (filtered_stream, html); - camel_object_unref (html); - - stream = (CamelStream *) filtered_stream; - } - - memstream = (CamelStreamMem *) camel_stream_mem_new (); - buffer = g_byte_array_new (); - camel_stream_mem_set_byte_array (memstream, buffer); - - camel_stream_write_to_stream (stream, (CamelStream *) memstream); - camel_object_unref (stream); - - /* The newer signature UI saves signatures in UTF-8, but we still need to check that - the signature is valid UTF-8 because it is possible that the user imported a - signature file that is in his/her locale charset. If it's not in UTF-8 and not in - the charset the composer is in (or their default mail charset) then fuck it, - there's nothing we can do. */ - if (buffer->len && !g_utf8_validate ((const gchar *)buffer->data, buffer->len, NULL)) { - stream = (CamelStream *) memstream; - memstream = (CamelStreamMem *) camel_stream_mem_new (); - camel_stream_mem_set_byte_array (memstream, g_byte_array_new ()); - - filtered_stream = camel_stream_filter_new_with_stream (stream); - camel_object_unref (stream); - - charset = composer && composer->priv->charset ? composer->priv->charset : NULL; - charset = charset ? g_strdup (charset) : e_composer_get_default_charset (); - if ((charenc = (CamelMimeFilter *) camel_mime_filter_charset_new_convert (charset, "UTF-8"))) { - camel_stream_filter_add (filtered_stream, charenc); - camel_object_unref (charenc); - } - - g_free (charset); - - camel_stream_write_to_stream ((CamelStream *) filtered_stream, (CamelStream *) memstream); - camel_object_unref (filtered_stream); - g_byte_array_free (buffer, TRUE); - - buffer = memstream->buffer; - } - - camel_object_unref (memstream); - - g_byte_array_append (buffer, (const guint8 *)"", 1); - content = (char*)buffer->data; - g_byte_array_free (buffer, FALSE); - - return content; -} - -gchar * -e_msg_composer_get_sig_file_content (const gchar *sigfile, gboolean in_html) -{ - if (!sigfile || !*sigfile) { - return NULL; - } - - return get_file_content (NULL, sigfile, !in_html, - CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT | - CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | - CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES | - CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES, - FALSE); -} - static gchar * encode_signature_name (const gchar *name) { @@ -1277,11 +1180,12 @@ get_signature_html (EMsgComposer *composer) format_html = signature->html; - if (signature->script) { - text = mail_config_signature_run_script (signature->filename); - } else { - text = e_msg_composer_get_sig_file_content (signature->filename, format_html); - } + if (signature->script) + text = mail_config_signature_run_script ( + signature->filename); + else + text = e_read_signature_file ( + signature, TRUE, NULL); } else { EAccountIdentity *id; gchar *organization; @@ -2029,7 +1933,6 @@ msg_composer_constructor (GType type, GObject *object; EMsgComposer *composer; GtkToggleAction *action; - GList *spell_languages; GArray *array; gboolean active; guint binding_id; @@ -2099,23 +2002,6 @@ msg_composer_constructor (GType type, shell_settings, "composer-request-receipt"); gtk_toggle_action_set_active (action, active); - spell_languages = e_load_spell_languages (); - gtkhtml_editor_set_spell_languages ( - GTKHTML_EDITOR (composer), spell_languages); - g_list_free (spell_languages); - - e_binding_new ( - G_OBJECT (shell_settings), "composer-inline-spelling", - G_OBJECT (composer), "inline-spelling"); - - e_binding_new ( - G_OBJECT (shell_settings), "composer-magic-links", - G_OBJECT (composer), "magic-links"); - - e_binding_new ( - G_OBJECT (shell_settings), "composer-magic-smileys", - G_OBJECT (composer), "magic-smileys"); - e_shell_watch_window (shell, GTK_WINDOW (object)); return object; diff --git a/composer/e-msg-composer.h b/composer/e-msg-composer.h index 5252f691e4..7e0851fb52 100644 --- a/composer/e-msg-composer.h +++ b/composer/e-msg-composer.h @@ -132,9 +132,6 @@ void e_msg_composer_set_enable_autosave (EMsgComposer *composer, gboolean enabled); -gchar * e_msg_composer_get_sig_file_content - (const gchar *sigfile, - gboolean in_html); void e_msg_composer_add_message_attachments (EMsgComposer *composer, CamelMimeMessage *message, diff --git a/configure.in b/configure.in index 69bab47bf7..69040f46f1 100644 --- a/configure.in +++ b/configure.in @@ -1547,7 +1547,7 @@ EVO_SET_COMPILE_FLAGS(TZDIALOG, libecal-$EDS_PACKAGE, $GNOME_PLATFORM_CFLAGS, $G AC_SUBST(TZDIALOG_CFLAGS) AC_SUBST(TZDIALOG_LIBS) -EVO_SET_COMPILE_FLAGS(E_WIDGETS, libbonoboui-2.0 gio-2.0 gconf-2.0 gobject-2.0 libgnomeui-2.0 libglade-2.0 libedataserverui-$EDS_PACKAGE libedataserver-$EDS_PACKAGE) +EVO_SET_COMPILE_FLAGS(E_WIDGETS, libbonoboui-2.0 gio-2.0 gconf-2.0 gobject-2.0 libgnomeui-2.0 libglade-2.0 libedataserverui-$EDS_PACKAGE libedataserver-$EDS_PACKAGE gtkhtml-editor) AC_SUBST(E_WIDGETS_CFLAGS) AC_SUBST(E_WIDGETS_LIBS) diff --git a/e-util/e-signature-utils.c b/e-util/e-signature-utils.c index 2a21a25b25..5565ef9faf 100644 --- a/e-util/e-signature-utils.c +++ b/e-util/e-signature-utils.c @@ -1,4 +1,6 @@ /* + * e-signature-utils.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 @@ -17,7 +19,17 @@ #include "e-signature-utils.h" +#include +#include #include +#include +#include +#include +#include +#include +#include + +#include "e-util/e-util.h" static ESignatureList *global_signature_list; @@ -70,3 +82,136 @@ e_get_signature_by_uid (const gchar *uid) /* XXX ESignatureList misuses const. */ return (ESignature *) signature; } + +gchar * +e_create_signature_file (GError **error) +{ + const gchar *data_dir; + gchar basename[32]; + gchar *filename; + gchar *pathname; + gint32 ii; + + data_dir = e_get_user_data_dir (); + pathname = g_build_filename (data_dir, "signatures", NULL); + filename = NULL; + + if (g_mkdir_with_parents (pathname, 0700) < 0) { + g_set_error ( + error, G_FILE_ERROR, + g_file_error_from_errno (errno), + "%s: %s", pathname, g_strerror (errno)); + g_free (pathname); + return NULL; + } + + for (ii = 0; ii < G_MAXINT32; ii++) { + + g_snprintf ( + basename, sizeof (basename), + "signature-%" G_GINT32_FORMAT, ii); + + g_free (filename); + filename = g_build_filename (pathname, basename, NULL); + + if (!g_file_test (filename, G_FILE_TEST_EXISTS)) { + gint fd; + + fd = g_creat (filename, 0600); + if (fd >= 0) { + close (fd); + break; + } + + /* If we failed once we're probably going + * to continue failing, so just give up. */ + g_set_error ( + error, G_FILE_ERROR, + g_file_error_from_errno (errno), + "%s: %s", filename, g_strerror (errno)); + g_free (filename); + filename = NULL; + break; + } + } + + /* If there are actually G_MAXINT32 signature files, the + * most recent signature file we be overwritten. Sorry. */ + + return filename; +} + +gchar * +e_read_signature_file (ESignature *signature, + gboolean convert_to_html, + GError **error) +{ + CamelStream *input_stream; + CamelStream *output_stream; + GByteArray *buffer; + gchar *content; + gsize length; + gint fd; + + g_return_val_if_fail (E_IS_SIGNATURE (signature), NULL); + + fd = g_open (signature->filename, O_RDONLY, 0); + if (fd < 0) { + g_set_error ( + error, G_FILE_ERROR, + g_file_error_from_errno (errno), + "%s: %s", signature->filename, + g_strerror (errno)); + return NULL; + } + + input_stream = camel_stream_fs_new_with_fd (fd); + + if (!signature->html && convert_to_html) { + CamelStreamFilter *filtered_stream; + CamelMimeFilter *filter; + gint32 flags; + + filtered_stream = + camel_stream_filter_new_with_stream (input_stream); + camel_object_unref (input_stream); + + flags = + CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT | + CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | + CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES | + CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES; + filter = camel_mime_filter_tohtml_new (flags, 0); + camel_stream_filter_add (filtered_stream, filter); + camel_object_unref (filter); + + input_stream = (CamelStream *) filtered_stream; + } + + buffer = g_byte_array_new (); + output_stream = camel_stream_mem_new (); + camel_stream_mem_set_byte_array ( + CAMEL_STREAM_MEM (output_stream), buffer); + camel_stream_write_to_stream (input_stream, output_stream); + camel_object_unref (output_stream); + camel_object_unref (input_stream); + + /* Make sure the buffer is nul-terminated. */ + length = (gsize) buffer->len; + g_byte_array_append (buffer, (guint8 *) "", 1); + content = (gchar *) g_byte_array_free (buffer, FALSE); + + /* Signatures are saved as UTF-8, but we still need to check that + * the signature is valid UTF-8 because the user may be opening + * a signature file that is in his/her locale character set. If + * it's not in UTF-8 then try converting from the current locale. */ + if (!g_utf8_validate (content, length, NULL)) { + gchar *utf8; + + utf8 = g_locale_to_utf8 (content, length, NULL, NULL, error); + g_free (content); + content = utf8; + } + + return content; +} diff --git a/e-util/e-signature-utils.h b/e-util/e-signature-utils.h index 961a6a6d26..d4fdfd97f4 100644 --- a/e-util/e-signature-utils.h +++ b/e-util/e-signature-utils.h @@ -1,4 +1,6 @@ /* + * e-signature-utils.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 @@ -18,7 +20,7 @@ #ifndef E_SIGNATURE_UTILS_H #define E_SIGNATURE_UTILS_H -#include +#include #include #include @@ -27,6 +29,10 @@ G_BEGIN_DECLS ESignatureList *e_get_signature_list (void); ESignature * e_get_signature_by_name (const gchar *name); ESignature * e_get_signature_by_uid (const gchar *uid); +gchar * e_create_signature_file (GError **error); +gchar * e_read_signature_file (ESignature *signature, + gboolean convert_to_html, + GError **error); G_END_DECLS diff --git a/mail/Makefile.am b/mail/Makefile.am index 5b493957b0..2f1e2d8446 100644 --- a/mail/Makefile.am +++ b/mail/Makefile.am @@ -163,8 +163,6 @@ libevolution_module_mail_la_SOURCES = \ mail-send-recv.h \ mail-session.c \ mail-session.h \ - mail-signature-editor.c \ - mail-signature-editor.h \ mail-tools.c \ mail-tools.h \ mail-vfolder.c \ diff --git a/mail/e-mail-label-manager.c b/mail/e-mail-label-manager.c index c4c34d0e6f..fc18da3e95 100644 --- a/mail/e-mail-label-manager.c +++ b/mail/e-mail-label-manager.c @@ -154,12 +154,13 @@ mail_label_manager_add_label (EMailLabelManager *manager) GtkTreeView *tree_view; GtkTreeModel *model; GtkWidget *dialog; - GtkWidget *parent; + gpointer parent; GdkColor label_color; const gchar *label_name; parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); - dialog = e_mail_label_dialog_new (GTK_WINDOW (parent)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + dialog = e_mail_label_dialog_new (parent); gtk_window_set_title (GTK_WINDOW (dialog), _("Add Label")); diff --git a/mail/e-mail-shell-module.c b/mail/e-mail-shell-module.c index 760eca6ab7..7c61663541 100644 --- a/mail/e-mail-shell-module.c +++ b/mail/e-mail-shell-module.c @@ -26,6 +26,7 @@ #include #include "e-util/e-account-utils.h" +#include "e-util/e-binding.h" #include "e-util/e-import.h" #include "e-util/e-util.h" #include "shell/e-shell.h" @@ -762,9 +763,34 @@ mail_shell_module_window_created_cb (EShell *shell, GtkWindow *window, EShellModule *shell_module) { + EShellSettings *shell_settings; static gboolean first_time = TRUE; const gchar *module_name; + shell_settings = e_shell_get_shell_settings (shell); + + /* This applies to both the composer and signature editor. */ + if (GTKHTML_IS_EDITOR (window)) { + GList *spell_languages; + + e_binding_new ( + G_OBJECT (shell_settings), "composer-inline-spelling", + G_OBJECT (window), "inline-spelling"); + + e_binding_new ( + G_OBJECT (shell_settings), "composer-magic-links", + G_OBJECT (window), "magic-links"); + + e_binding_new ( + G_OBJECT (shell_settings), "composer-magic-smileys", + G_OBJECT (window), "magic-smileys"); + + spell_languages = e_load_spell_languages (); + gtkhtml_editor_set_spell_languages ( + GTKHTML_EDITOR (window), spell_languages); + g_list_free (spell_languages); + } + if (E_IS_MSG_COMPOSER (window)) { /* Integrate the new composer into the mail module. */ em_configure_new_composer (E_MSG_COMPOSER (window)); diff --git a/mail/em-account-editor.c b/mail/em-account-editor.c index 0103242112..a5c5d59fd8 100644 --- a/mail/em-account-editor.c +++ b/mail/em-account-editor.c @@ -63,7 +63,7 @@ #include "em-account-editor.h" #include "mail-session.h" #include "mail-send-recv.h" -#include "mail-signature-editor.h" +#include "e-signature-editor.h" #include "em-utils.h" #include "em-composer-prefs.h" #include "mail-config.h" diff --git a/mail/em-composer-prefs.c b/mail/em-composer-prefs.c index 686b9c8da0..ef73c23355 100644 --- a/mail/em-composer-prefs.c +++ b/mail/em-composer-prefs.c @@ -43,17 +43,17 @@ #include #include -#include #include #include #include "misc/e-charset-picker.h" +#include "misc/e-signature-manager.h" #include "e-util/e-error.h" #include "e-util/e-util-private.h" #include "mail-config.h" -#include "mail-signature-editor.h" +#include "e-signature-editor.h" #include "em-config.h" static gpointer parent_class; @@ -160,36 +160,6 @@ transform_new_to_old_reply_style (const GValue *src_value, return success; } -static void -composer_prefs_dispose (GObject *object) -{ - EMComposerPrefs *prefs = (EMComposerPrefs *) object; - ESignatureList *signature_list; - - signature_list = e_get_signature_list (); - - if (prefs->sig_added_id != 0) { - g_signal_handler_disconnect ( - signature_list, prefs->sig_added_id); - prefs->sig_added_id = 0; - } - - if (prefs->sig_removed_id != 0) { - g_signal_handler_disconnect ( - signature_list, prefs->sig_removed_id); - prefs->sig_removed_id = 0; - } - - if (prefs->sig_changed_id != 0) { - g_signal_handler_disconnect ( - signature_list, prefs->sig_changed_id); - prefs->sig_changed_id = 0; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - static void composer_prefs_finalize (GObject *object) { @@ -197,8 +167,6 @@ composer_prefs_finalize (GObject *object) g_object_unref (prefs->gui); - g_hash_table_destroy (prefs->sig_hash); - /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -211,17 +179,12 @@ composer_prefs_class_init (EMComposerPrefsClass *class) parent_class = g_type_class_peek_parent (class); object_class = G_OBJECT_CLASS (class); - object_class->dispose = composer_prefs_dispose; object_class->finalize = composer_prefs_finalize; } static void composer_prefs_init (EMComposerPrefs *prefs) { - prefs->sig_hash = g_hash_table_new_full ( - g_direct_hash, g_direct_equal, - (GDestroyNotify) NULL, - (GDestroyNotify) gtk_tree_row_reference_free); } GType @@ -267,8 +230,8 @@ sig_load_preview (EMComposerPrefs *prefs, if (signature->script) str = mail_config_signature_run_script (signature->filename); else - str = e_msg_composer_get_sig_file_content ( - signature->filename, signature->html); + /* FIXME Show an error in the preview area. */ + str = e_read_signature_file (signature, FALSE, NULL); if (!str || !*str) { /* make html stream happy and write at least one character */ g_free (str); @@ -293,143 +256,6 @@ sig_load_preview (EMComposerPrefs *prefs, g_free (str); } -static void -signature_added (ESignatureList *signature_list, - ESignature *signature, - EMComposerPrefs *prefs) -{ - GtkTreeRowReference *row; - GtkTreeModel *model; - GtkTreePath *path; - GtkTreeIter iter; - - /* autogen signature is special */ - if (signature->autogen) - return; - - model = gtk_tree_view_get_model (prefs->sig_list); - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - gtk_list_store_set ( - GTK_LIST_STORE (model), &iter, - 0, signature->name, 1, signature, -1); - - path = gtk_tree_model_get_path (model, &iter); - row = gtk_tree_row_reference_new (model, path); - gtk_tree_path_free (path); - - g_hash_table_insert (prefs->sig_hash, signature, row); -} - -static void -signature_removed (ESignatureList *signature_list, - ESignature *signature, - EMComposerPrefs *prefs) -{ - GtkTreeRowReference *row; - GtkTreeModel *model; - GtkTreePath *path; - GtkTreeIter iter; - - if (!(row = g_hash_table_lookup (prefs->sig_hash, signature))) - return; - - model = gtk_tree_view_get_model (prefs->sig_list); - path = gtk_tree_row_reference_get_path (row); - g_hash_table_remove (prefs->sig_hash, signature); - - if (!gtk_tree_model_get_iter (model, &iter, path)) { - gtk_tree_path_free (path); - return; - } - - gtk_list_store_remove ((GtkListStore *) model, &iter); -} - -static void -signature_changed (ESignatureList *signature_list, - ESignature *signature, - EMComposerPrefs *prefs) -{ - GtkTreeSelection *selection; - GtkTreeRowReference *row; - GtkTreeModel *model; - GtkTreePath *path; - GtkTreeIter iter; - ESignature *cur; - - if (!(row = g_hash_table_lookup (prefs->sig_hash, signature))) - return; - - model = gtk_tree_view_get_model (prefs->sig_list); - path = gtk_tree_row_reference_get_path (row); - - if (!gtk_tree_model_get_iter (model, &iter, path)) { - gtk_tree_path_free (path); - return; - } - - gtk_tree_path_free (path); - - gtk_list_store_set ((GtkListStore *) model, &iter, 0, signature->name, -1); - - selection = gtk_tree_view_get_selection (prefs->sig_list); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - gtk_tree_model_get (model, &iter, 1, &cur, -1); - if (cur == signature) - sig_load_preview (prefs, signature); - } -} - -static void -sig_edit_cb (GtkWidget *widget, EMComposerPrefs *prefs) -{ - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkWidget *parent; - GtkTreeIter iter; - ESignature *signature; - - selection = gtk_tree_view_get_selection (prefs->sig_list); - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - return; - - gtk_tree_model_get (model, &iter, 1, &signature, -1); - - if (!signature->script) { - GtkWidget *editor; - - /* normal signature */ - if (!signature->filename || *signature->filename == '\0') { - g_free (signature->filename); - signature->filename = g_strdup (_("Unnamed")); - } - - editor = e_signature_editor_new (); - e_signature_editor_set_signature ( - E_SIGNATURE_EDITOR (editor), signature); - - parent = gtk_widget_get_toplevel ((GtkWidget *) prefs); - if (GTK_WIDGET_TOPLEVEL (parent)) - gtk_window_set_transient_for ( - GTK_WINDOW (editor), GTK_WINDOW (parent)); - - gtk_widget_show (editor); - } else { - /* signature script */ - GtkWidget *entry; - - entry = glade_xml_get_widget (prefs->sig_script_gui, "filechooserbutton_add_script"); - gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (entry), signature->filename); - - entry = glade_xml_get_widget (prefs->sig_script_gui, "entry_add_script_name"); - gtk_entry_set_text (GTK_ENTRY (entry), signature->name); - - g_object_set_data ((GObject *) entry, "sig", signature); - - gtk_window_present ((GtkWindow *) prefs->sig_script_dialog); - } -} - void em_composer_prefs_new_signature (GtkWindow *parent, gboolean html_mode) @@ -442,176 +268,22 @@ em_composer_prefs_new_signature (GtkWindow *parent, gtk_widget_show (editor); } -static void -sig_delete_cb (GtkWidget *widget, EMComposerPrefs *prefs) -{ - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - ESignature *signature; - ESignatureList *signature_list; - - signature_list = e_get_signature_list (); - selection = gtk_tree_view_get_selection (prefs->sig_list); - - if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - gtk_tree_model_get (model, &iter, 1, &signature, -1); - - if (signature->filename && !signature->script) - g_unlink (signature->filename); - - e_signature_list_remove (signature_list, signature); - e_signature_list_save (signature_list); - } - gtk_widget_grab_focus ((GtkWidget *)prefs->sig_list); -} - -static void -sig_add_cb (GtkWidget *widget, EMComposerPrefs *prefs) -{ - gboolean send_html; - GtkWidget *parent; - - send_html = gconf_client_get_bool ( - mail_config_get_gconf_client (), - "/apps/evolution/mail/composer/send_html", NULL); - - parent = gtk_widget_get_toplevel (GTK_WIDGET (prefs)); - parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; - - em_composer_prefs_new_signature (GTK_WINDOW (parent), send_html); - gtk_widget_grab_focus (GTK_WIDGET (prefs->sig_list)); -} - -static void -sig_add_script_response (GtkWidget *widget, int button, EMComposerPrefs *prefs) -{ - gchar *script, **argv = NULL; - GtkWidget *entry; - const gchar *name; - int argc; - - if (button == GTK_RESPONSE_ACCEPT) { - entry = glade_xml_get_widget (prefs->sig_script_gui, "filechooserbutton_add_script"); - script = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (entry)); - - entry = glade_xml_get_widget (prefs->sig_script_gui, "entry_add_script_name"); - name = gtk_entry_get_text (GTK_ENTRY (entry)); - if (script && *script && g_shell_parse_argv (script, &argc, &argv, NULL)) { - struct stat st; - - if (g_stat (argv[0], &st) == 0 && S_ISREG (st.st_mode) && g_access (argv[0], X_OK) == 0) { - ESignatureList *signature_list; - ESignature *signature; - - signature_list = e_get_signature_list (); - - if ((signature = g_object_get_data ((GObject *) entry, "sig"))) { - /* we're just editing an existing signature script */ - g_free (signature->name); - signature->name = g_strdup (name); - g_free(signature->filename); - signature->filename = g_strdup(script); - e_signature_list_change (signature_list, signature); - } else { - signature = mail_config_signature_new (script, TRUE, TRUE); - signature->name = g_strdup (name); - - e_signature_list_add (signature_list, signature); - g_object_unref (signature); - } - - e_signature_list_save (signature_list); - - gtk_widget_hide (prefs->sig_script_dialog); - g_strfreev (argv); - g_free (script); - - return; - } - } - - e_error_run((GtkWindow *)prefs->sig_script_dialog, "mail:signature-notscript", argv ? argv[0] : script, NULL); - g_strfreev (argv); - g_free (script); - return; - } - - gtk_widget_hide (widget); -} - -static void -sig_add_script_cb (GtkWidget *widget, EMComposerPrefs *prefs) -{ - GtkWidget *entry; - - entry = glade_xml_get_widget (prefs->sig_script_gui, "entry_add_script_name"); - gtk_entry_set_text (GTK_ENTRY (entry), _("Unnamed")); - - g_object_set_data ((GObject *) entry, "sig", NULL); - - gtk_window_present ((GtkWindow *) prefs->sig_script_dialog); -} - static void sig_selection_changed (GtkTreeSelection *selection, EMComposerPrefs *prefs) { ESignature *signature; - GtkTreeModel *model; - GtkTreeIter iter; - gboolean valid; - - valid = gtk_tree_selection_get_selected (selection, &model, &iter); - - if (valid) { - gtk_tree_model_get (model, &iter, 1, &signature, -1); - sig_load_preview (prefs, signature); - } else - sig_load_preview (prefs, NULL); + GtkTreeView *tree_view; - gtk_widget_set_sensitive (GTK_WIDGET (prefs->sig_delete), valid); - gtk_widget_set_sensitive (GTK_WIDGET (prefs->sig_edit), valid); -} - -static void -sig_fill_list (EMComposerPrefs *prefs) -{ - ESignatureList *signature_list; - GtkTreeModel *model; - EIterator *iterator; - - model = gtk_tree_view_get_model (prefs->sig_list); - gtk_list_store_clear (GTK_LIST_STORE (model)); - - signature_list = e_get_signature_list (); - iterator = e_list_get_iterator ((EList *) signature_list); - - while (e_iterator_is_valid (iterator)) { - ESignature *signature; - - signature = (ESignature *) e_iterator_get (iterator); - signature_added (signature_list, signature, prefs); + tree_view = gtk_tree_selection_get_tree_view (selection); - e_iterator_next (iterator); - } - - g_object_unref (iterator); - - gtk_widget_set_sensitive (GTK_WIDGET (prefs->sig_edit), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (prefs->sig_delete), FALSE); + signature = e_signature_tree_view_get_selected ( + E_SIGNATURE_TREE_VIEW (tree_view)); - prefs->sig_added_id = g_signal_connect ( - signature_list, "signature-added", - G_CALLBACK (signature_added), prefs); + sig_load_preview (prefs, signature); - prefs->sig_removed_id = g_signal_connect ( - signature_list, "signature-removed", - G_CALLBACK (signature_removed), prefs); - - prefs->sig_changed_id = g_signal_connect ( - signature_list, "signature-changed", - G_CALLBACK (signature_changed), prefs); + if (signature != NULL) + g_object_unref (signature); } static void @@ -824,40 +496,15 @@ emcp_free (EConfig *ec, GSList *items, gpointer data) g_slist_free (items); } -static gboolean -signature_key_press_cb (GtkTreeView *tree_view, - GdkEventKey *event, - EMComposerPrefs *prefs) -{ - /* No need to care about anything other than DEL key */ - if (event->keyval == GDK_Delete) { - sig_delete_cb (GTK_WIDGET (tree_view), prefs); - return TRUE; - } - - return FALSE; -} - -static gboolean -sig_tree_event_cb (GtkTreeView *tree_view, - GdkEvent *event, - EMComposerPrefs *prefs) -{ - if (event->type == GDK_2BUTTON_PRESS) { - sig_edit_cb (GTK_WIDGET (tree_view), prefs); - return TRUE; - } - - return FALSE; -} - static void em_composer_prefs_construct (EMComposerPrefs *prefs, EShell *shell) { GtkWidget *toplevel, *widget, *menu, *info_pixmap; + GtkWidget *container; EShellSettings *shell_settings; - GtkDialog *dialog; + ESignatureList *signature_list; + ESignatureTreeView *signature_tree_view; GladeXML *gui; GtkTreeView *view; GtkListStore *store; @@ -865,14 +512,12 @@ em_composer_prefs_construct (EMComposerPrefs *prefs, GtkCellRenderer *renderer; GConfBridge *bridge; GConfClient *client; - const gchar *key; gchar *buf; EMConfig *ec; EMConfigTargetPrefs *target; GSList *l; int i; gchar *gladefile; - gboolean sensitive; bridge = gconf_bridge_get (); client = mail_config_get_gconf_client (); @@ -883,7 +528,6 @@ em_composer_prefs_construct (EMComposerPrefs *prefs, NULL); gui = glade_xml_new (gladefile, "composer_toplevel", NULL); prefs->gui = gui; - prefs->sig_script_gui = glade_xml_new (gladefile, "vbox_add_script_signature", NULL); g_free (gladefile); /** @HookPoint-EMConfig: Mail Composer Preferences @@ -1015,72 +659,33 @@ em_composer_prefs_construct (EMComposerPrefs *prefs, NULL, NULL); /* Signatures */ - dialog = (GtkDialog *) gtk_dialog_new (); - - gtk_widget_realize ((GtkWidget *) dialog); - gtk_container_set_border_width ((GtkContainer *)dialog->action_area, 12); - gtk_container_set_border_width ((GtkContainer *)dialog->vbox, 0); - - prefs->sig_script_dialog = (GtkWidget *) dialog; - gtk_dialog_add_buttons (dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, - GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); - gtk_dialog_set_has_separator (dialog, FALSE); - gtk_window_set_title ((GtkWindow *) dialog, _("Add signature script")); - g_signal_connect (dialog, "response", G_CALLBACK (sig_add_script_response), prefs); - widget = glade_xml_get_widget (prefs->sig_script_gui, "vbox_add_script_signature"); - gtk_box_pack_start ((GtkBox *) dialog->vbox, widget, TRUE, TRUE, 0); - - key = "/apps/evolution/mail/signatures"; - sensitive = gconf_client_key_is_writable (client, key, NULL); - - widget = glade_xml_get_widget (gui, "cmdSignatureAdd"); - gtk_widget_set_sensitive (widget, sensitive); - g_signal_connect ( - widget, "clicked", - G_CALLBACK (sig_add_cb), prefs); - prefs->sig_add = GTK_BUTTON (widget); + signature_list = e_get_signature_list (); + container = glade_xml_get_widget (gui, "alignSignatures"); + widget = e_signature_manager_new (signature_list); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + /* The mail shell module responds to the "window-created" signal + * that this triggers and configures it with composer preferences. */ + g_signal_connect_swapped ( + widget, "editor-created", + G_CALLBACK (e_shell_watch_window), shell); + + e_binding_new ( + G_OBJECT (shell_settings), "composer-format-html", + G_OBJECT (widget), "prefer-html"); - widget = glade_xml_get_widget (gui, "cmdSignatureAddScript"); e_binding_new_with_negation ( G_OBJECT (shell_settings), "disable-command-line", - G_OBJECT (widget), "sensitive"); - g_signal_connect ( - widget, "clicked", - G_CALLBACK (sig_add_script_cb), prefs); - prefs->sig_add_script = GTK_BUTTON (widget); + G_OBJECT (widget), "allow-scripts"); - widget = glade_xml_get_widget (gui, "cmdSignatureEdit"); - gtk_widget_set_sensitive (widget, sensitive); - g_signal_connect ( - widget, "clicked", - G_CALLBACK (sig_edit_cb), prefs); - prefs->sig_edit = GTK_BUTTON (widget); - - widget = glade_xml_get_widget (gui, "cmdSignatureDelete"); - gtk_widget_set_sensitive (widget, sensitive); - g_signal_connect ( - widget, "clicked", - G_CALLBACK (sig_delete_cb), prefs); - prefs->sig_delete = GTK_BUTTON (widget); - - widget = glade_xml_get_widget (gui, "listSignatures"); - gtk_widget_set_sensitive (widget, sensitive); - prefs->sig_list = GTK_TREE_VIEW (widget); - store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER); - gtk_tree_view_set_model (prefs->sig_list, GTK_TREE_MODEL (store)); - gtk_tree_view_insert_column_with_attributes ( - prefs->sig_list, -1, _("Signature(s)"), - gtk_cell_renderer_text_new (), "text", 0, NULL); - selection = gtk_tree_view_get_selection (prefs->sig_list); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + signature_tree_view = e_signature_manager_get_tree_view ( + E_SIGNATURE_MANAGER (widget)); + selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (signature_tree_view)); g_signal_connect ( selection, "changed", G_CALLBACK (sig_selection_changed), prefs); - g_signal_connect ( - prefs->sig_list, "event", - G_CALLBACK (sig_tree_event_cb), prefs); - - sig_fill_list (prefs); /* preview GtkHTML widget */ widget = glade_xml_get_widget (gui, "scrolled-sig"); @@ -1098,10 +703,6 @@ em_composer_prefs_construct (EMComposerPrefs *prefs, e_config_set_target ((EConfig *)ec, (EConfigTarget *)target); toplevel = e_config_create_widget ((EConfig *)ec); gtk_container_add (GTK_CONTAINER (prefs), toplevel); - - g_signal_connect ( - prefs->sig_list, "key-press-event", - G_CALLBACK (signature_key_press_cb), prefs); } GtkWidget * diff --git a/mail/em-composer-prefs.h b/mail/em-composer-prefs.h index 0dc848743e..623fee0220 100644 --- a/mail/em-composer-prefs.h +++ b/mail/em-composer-prefs.h @@ -69,20 +69,7 @@ struct _EMComposerPrefs { GtkOptionMenu *shortcuts_type; /* Signatures */ - GtkTreeView *sig_list; - GHashTable *sig_hash; - GtkButton *sig_add; - GtkButton *sig_add_script; - GtkButton *sig_edit; - GtkButton *sig_delete; struct _GtkHTML *sig_preview; - - GladeXML *sig_script_gui; - GtkWidget *sig_script_dialog; - - guint sig_added_id; - guint sig_removed_id; - guint sig_changed_id; }; struct _EMComposerPrefsClass { diff --git a/mail/mail-config.c b/mail/mail-config.c index 2186ce0e21..a7e8bb908c 100644 --- a/mail/mail-config.c +++ b/mail/mail-config.c @@ -953,66 +953,6 @@ mail_config_folder_to_cachename (CamelFolder *folder, const char *prefix) return filename; } -static char * -get_new_signature_filename (void) -{ - const char *base_directory; - char *filename, *id; - struct stat st; - int i; - - base_directory = e_get_user_data_dir (); - filename = g_build_filename (base_directory, "signatures", NULL); - if (g_lstat (filename, &st)) { - if (errno == ENOENT) { - if (g_mkdir (filename, 0700)) - g_warning ("Fatal problem creating %s directory.", filename); - } else - g_warning ("Fatal problem with %s directory.", filename); - } - g_free (filename); - - filename = g_malloc (strlen (base_directory) + sizeof ("/signatures/signature-") + 12); - id = g_stpcpy (filename, base_directory); - id = g_stpcpy (id, "/signatures/signature-"); - - for (i = 0; i < (INT_MAX - 1); i++) { - sprintf (id, "%d", i); - if (g_lstat (filename, &st) == -1 && errno == ENOENT) { - int fd; - - fd = g_creat (filename, 0600); - if (fd >= 0) { - close (fd); - return filename; - } - } - } - - g_free (filename); - - return NULL; -} - - -ESignature * -mail_config_signature_new (const char *filename, gboolean script, gboolean html) -{ - ESignature *sig; - - sig = e_signature_new (); - sig->name = g_strdup (_("Unnamed")); - sig->script = script; - sig->html = html; - - if (filename == NULL) - sig->filename = get_new_signature_filename (); - else - sig->filename = g_strdup (filename); - - return sig; -} - void mail_config_reload_junk_headers (void) { diff --git a/mail/mail-config.glade b/mail/mail-config.glade index d2d8da8ea7..42c691fb82 100644 --- a/mail/mail-config.glade +++ b/mail/mail-config.glade @@ -300,64 +300,64 @@ For example: "Work" or "Personal" 12 6 - + True True * - + 1 2 + 1 + 2 - + True 0 - Full Nam_e: + Email _Address: True - identity_full_name + identity_address + 1 + 2 GTK_FILL - + True 0 - Email _Address: + Full Nam_e: True - identity_address + identity_full_name - 1 - 2 GTK_FILL - + True True * - + 1 2 - 1 - 2 @@ -417,51 +417,75 @@ For example: "Work" or "Personal" 12 6 - + True - True - _Make this my default account + 0 + Signat_ure: True - 0 - True + signature_dropdown - 2 + 3 + 4 GTK_FILL - GTK_FILL + - + True - 0 - Re_ply-To: - True - GTK_JUSTIFY_CENTER - identity_reply_to + 6 + + + True + em_account_editor_dropdown_new + + + False + False + + + + + True + True + Add Ne_w Signature... + True + 0 + + + + False + False + GTK_PACK_END + 1 + + - 1 - 2 + 1 + 2 + 3 + 4 GTK_FILL - + GTK_FILL - + True True * - + 1 2 - 1 - 2 + 2 + 3 @@ -481,76 +505,52 @@ For example: "Work" or "Personal" - + True True * - + 1 2 - 2 - 3 + 1 + 2 - + True - 6 - - - True - em_account_editor_dropdown_new - - - False - False - - - - - True - True - Add Ne_w Signature... - True - 0 - - - - False - False - GTK_PACK_END - 1 - - + 0 + Re_ply-To: + True + GTK_JUSTIFY_CENTER + identity_reply_to - 1 - 2 - 3 - 4 + 1 + 2 GTK_FILL - GTK_FILL + - + True - 0 - Signat_ure: + True + _Make this my default account True - signature_dropdown + 0 + True - 3 - 4 + 2 GTK_FILL - + GTK_FILL @@ -601,28 +601,28 @@ For example: "Work" or "Personal" 12 6 - + True - em_account_editor_dropdown_new + 0 + Server _Type: + True + GTK_JUSTIFY_RIGHT + source_type_dropdown - 1 - 3 GTK_FILL - + True 0 0 - description - True + Description: + GTK_JUSTIFY_CENTER - 1 - 3 1 2 GTK_FILL @@ -630,14 +630,16 @@ For example: "Work" or "Personal" - + True 0 0 - Description: - GTK_JUSTIFY_CENTER + description + True + 1 + 3 1 2 GTK_FILL @@ -645,15 +647,13 @@ For example: "Work" or "Personal" - + True - 0 - Server _Type: - True - GTK_JUSTIFY_RIGHT - source_type_dropdown + em_account_editor_dropdown_new + 1 + 3 GTK_FILL @@ -716,34 +716,35 @@ For example: "Work" or "Personal" 12 6 - + True - Mailbox location + 0 + _Server: + True + source_host - 1 - 2 - 2 - 3 + GTK_FILL - + True 0 - _Path: + User_name: True + source_user - 2 - 3 + 1 + 2 GTK_FILL - + True True * @@ -751,13 +752,11 @@ For example: "Work" or "Personal" 1 2 - 1 - 2 - + True True * @@ -765,34 +764,35 @@ For example: "Work" or "Personal" 1 2 + 1 + 2 - + True 0 - User_name: + _Path: True - source_user - 1 - 2 + 2 + 3 GTK_FILL - + True - 0 - _Server: - True - source_host + Mailbox location - GTK_FILL + 1 + 2 + 2 + 3 @@ -1068,59 +1068,59 @@ For example: "Work" or "Personal" 12 6 - + True 0 0 - description - True + Server _Type: + True + GTK_JUSTIFY_RIGHT + transport_type_dropdown - 1 - 3 - 1 - 2 GTK_FILL - + True - em_account_editor_dropdown_new + 0 + 0 + Description: + GTK_JUSTIFY_RIGHT - 1 - 3 + 1 + 2 GTK_FILL - - + True - 0 - 0 - Description: - GTK_JUSTIFY_RIGHT + em_account_editor_dropdown_new - 1 - 2 + 1 + 3 GTK_FILL + - + True 0 0 - Server _Type: - True - GTK_JUSTIFY_RIGHT - transport_type_dropdown + description + True + 1 + 3 + 1 + 2 GTK_FILL @@ -1184,18 +1184,6 @@ For example: "Work" or "Personal" 2 12 6 - - - True - True - * - - - 1 - 2 - - - True @@ -1210,6 +1198,18 @@ For example: "Work" or "Personal" + + + True + True + * + + + 1 + 2 + + + False @@ -1400,6 +1400,50 @@ For example: "Work" or "Personal" 2 12 6 + + + True + 0 + T_ype: + True + GTK_JUSTIFY_CENTER + transport_auth_dropdown + + + GTK_FILL + + + + + + True + 0 + User_name: + True + GTK_JUSTIFY_RIGHT + transport_user + + + 1 + 2 + GTK_FILL + + + + + + True + True + * + + + 1 + 2 + 1 + 2 + + + True @@ -1443,50 +1487,6 @@ For example: "Work" or "Personal" GTK_FILL - - - True - True - * - - - 1 - 2 - 1 - 2 - - - - - - True - 0 - User_name: - True - GTK_JUSTIFY_RIGHT - transport_user - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - T_ype: - True - GTK_JUSTIFY_CENTER - transport_auth_dropdown - - - GTK_FILL - - - False @@ -1607,57 +1607,45 @@ For example: "Work" or "Personal" - + True - - - True - True - gtk-revert-to-saved - True - 0 - - - False - False - - - - - True - - - 1 - - + 0 + Drafts _Folder: + True + drafts_button - 1 - 3 - 2 - 3 + GTK_FILL + - + True + 0 + Sent _Messages Folder: + True + sent_button - 2 - 3 1 2 GTK_FILL - GTK_FILL + - + True + em_account_editor_folder_selector_button_new + Select Sent Folder - 2 - 3 + 1 + 2 + 1 + 2 + GTK_FILL GTK_FILL @@ -1674,46 +1662,58 @@ For example: "Work" or "Personal" - + True - em_account_editor_folder_selector_button_new - Select Sent Folder - 1 - 2 - 1 - 2 - GTK_FILL + 2 + 3 GTK_FILL - + True - 0 - Sent _Messages Folder: - True - sent_button + 2 + 3 1 2 GTK_FILL - + GTK_FILL - + True - 0 - Drafts _Folder: - True - drafts_button + + + True + True + gtk-revert-to-saved + True + 0 + + + False + False + + + + + True + + + 1 + + - GTK_FILL - + 1 + 3 + 2 + 3 @@ -1777,14 +1777,14 @@ For example: "Work" or "Personal" 12 6 - + True 6 - + True True - Always _blind carbon-copy (bcc) to: + Alway_s carbon-copy (cc) to: True 0 True @@ -1795,10 +1795,10 @@ For example: "Work" or "Personal" - + True - + True 12 @@ -1808,16 +1808,16 @@ For example: "Work" or "Personal" - + True 6 2 - + True 6 - + True True * @@ -1836,20 +1836,16 @@ For example: "Work" or "Personal" - - 1 - 2 - - + True 6 - + True True - Alway_s carbon-copy (cc) to: + Always _blind carbon-copy (bcc) to: True 0 True @@ -1860,10 +1856,10 @@ For example: "Work" or "Personal" - + True - + True 12 @@ -1873,16 +1869,16 @@ For example: "Work" or "Personal" - + True 6 2 - + True 6 - + True True * @@ -1901,6 +1897,10 @@ For example: "Work" or "Personal" + + 1 + 2 + @@ -2202,25 +2202,145 @@ For example: "Work" or "Personal" 12 6 - + + True + True + * + + + 1 + 2 + 1 + 2 + + + + + + True + True + * + + + 1 + 2 + 5 + 6 + + + + + + True + True + Also encrypt to sel_f when sending encrypted messages + True + 0 + True + + + 3 + 4 + 5 + GTK_FILL + + + + + + True + True + Encrypt out_going messages (by default) + True + 0 + True + + + 3 + 3 + 4 + GTK_FILL + + + + + + True + True + Digitally sign o_utgoing messages (by default) + True + 0 + True + + + 3 + GTK_FILL + + + + + + True + + + 3 + 2 + 3 + GTK_FILL + GTK_FILL + 6 + + + + + True + 0 + Encry_ption certificate: + True + smime_encrypt_key + + + 5 + 6 + GTK_FILL + + + + + + True + 0 + Sig_ning certificate: + True + smime_sign_key + + + 1 + 2 + GTK_FILL + + + + + True 6 - + True True 0 - + True 0 0 - + True 2 - + True gtk-open @@ -2230,9 +2350,9 @@ For example: "Work" or "Personal" - + True - _Select... + S_elect... True @@ -2252,21 +2372,21 @@ For example: "Work" or "Personal" - + True True 0 - + True 0 0 - + True 2 - + True gtk-clear @@ -2276,9 +2396,9 @@ For example: "Work" or "Personal" - + True - Cle_ar + Clea_r True @@ -2302,32 +2422,32 @@ For example: "Work" or "Personal" 2 3 - 1 - 2 + 5 + 6 GTK_FILL GTK_FILL - + True 6 - + True True 0 - + True 0 0 - + True 2 - + True gtk-open @@ -2337,9 +2457,9 @@ For example: "Work" or "Personal" - + True - S_elect... + _Select... True @@ -2359,21 +2479,21 @@ For example: "Work" or "Personal" - + True True 0 - + True 0 0 - + True 2 - + True gtk-clear @@ -2383,9 +2503,9 @@ For example: "Work" or "Personal" - + True - Clea_r + Cle_ar True @@ -2409,130 +2529,10 @@ For example: "Work" or "Personal" 2 3 - 5 - 6 - GTK_FILL - GTK_FILL - - - - - True - 0 - Sig_ning certificate: - True - smime_sign_key - - 1 2 GTK_FILL - - - - - - True - 0 - Encry_ption certificate: - True - smime_encrypt_key - - - 5 - 6 - GTK_FILL - - - - - - True - - - 3 - 2 - 3 - GTK_FILL - GTK_FILL - 6 - - - - - True - True - Digitally sign o_utgoing messages (by default) - True - 0 - True - - - 3 - GTK_FILL - - - - - - True - True - Encrypt out_going messages (by default) - True - 0 - True - - - 3 - 3 - 4 - GTK_FILL - - - - - - True - True - Also encrypt to sel_f when sending encrypted messages - True - 0 - True - - - 3 - 4 - 5 - GTK_FILL - - - - - - True - True - * - - - 1 - 2 - 5 - 6 - - - - - - True - True - * - - - 1 - 2 - 1 - 2 - + GTK_FILL @@ -2764,63 +2764,63 @@ For example: "Work" or "Personal" 6 6 - + True 0 - Fix_ed width Font: + S_tandard Font: True GTK_JUSTIFY_RIGHT - FontFixed + FontVariable - 1 - 2 GTK_FILL - + True True 0 - Select HTML variable width font + Select HTML fixed width font 1 2 + 1 + 2 GTK_FILL - + True True 0 - Select HTML fixed width font + Select HTML variable width font 1 2 - 1 - 2 GTK_FILL - + True 0 - S_tandard Font: + Fix_ed width Font: True GTK_JUSTIFY_RIGHT - FontVariable + FontFixed + 1 + 2 GTK_FILL @@ -3797,22 +3797,26 @@ For example: "Work" or "Personal" 9 3 - + True 6 - + True - gtk-info + _Default junk plugin: + True + default_junk_plugin False + False + 6 - + True - Option is ignored if a match for custom junk headers is found. + create_combo_text_widget False @@ -3822,40 +3826,110 @@ For example: "Work" or "Personal" - 6 - 7 + 7 + 8 GTK_FILL - + True True - _Lookup in local address book only + Checks incoming mail messages to be Junk + Check incoming _messages for junk True 0 True - 5 - 6 GTK_FILL - 25 + 4 - + + True + 3 + + + True + gtk-info + + + False + False + + + + + True + True + + + False + False + 1 + + + + + 8 + 9 + GTK_FILL + 15 + + + + + True + 4 + + + True + True + Delete junk messages on e_xit + True + 0 + True + + + False + False + + + + + True + True + 0 + + + False + False + 1 + + + + + 1 + 2 + GTK_FILL + 4 + + + + True True - Do not mar_k messages as junk if sender is in my address book + Check cu_stom headers for junk True 0 True - 4 - 5 + 2 + 3 GTK_FILL 4 @@ -3921,130 +3995,56 @@ For example: "Work" or "Personal" - + True True - Check cu_stom headers for junk + Do not mar_k messages as junk if sender is in my address book True 0 True - 2 - 3 + 4 + 5 GTK_FILL 4 - + True - 4 + True + _Lookup in local address book only + True + 0 + True + + + 5 + 6 + GTK_FILL + + 25 + + + + + True + 6 - + True - True - Delete junk messages on e_xit - True - 0 - True + gtk-info False - False - + True - True - 0 - - - False - False - 1 - - - - - 1 - 2 - GTK_FILL - 4 - - - - - True - 3 - - - True - gtk-info - - - False - False - - - - - True - True - - - False - False - 1 - - - - - 8 - 9 - GTK_FILL - 15 - - - - - True - True - Checks incoming mail messages to be Junk - Check incoming _messages for junk - True - 0 - True - - - GTK_FILL - - 4 - - - - - True - 6 - - - True - _Default junk plugin: - True - default_junk_plugin - - - False - False - 6 - - - - - True - create_combo_text_widget + Option is ignored if a match for custom junk headers is found. False @@ -4054,8 +4054,8 @@ For example: "Work" or "Personal" - 7 - 8 + 6 + 7 GTK_FILL @@ -4231,40 +4231,29 @@ For example: "Work" or "Personal" 12 6 - + True - Attachment -Inline (Outlook style) -Quoted -Do Not Quote + 0 + _Reply style: + True + GTK_JUSTIFY_CENTER - 1 - 2 1 2 + GTK_FILL + - + True - Attachment -Inline -Quoted + True + 0 1 2 - - - - - True - C_haracter set: - True - omenuCharset1 - - 2 3 GTK_FILL @@ -4285,14 +4274,13 @@ Quoted - + True - True - 0 + C_haracter set: + True + omenuCharset1 - 1 - 2 2 3 GTK_FILL @@ -4300,18 +4288,30 @@ Quoted - + True - 0 - _Reply style: - True - GTK_JUSTIFY_CENTER + Attachment +Inline +Quoted + + + 1 + 2 + + + + + True + Attachment +Inline (Outlook style) +Quoted +Do Not Quote + 1 + 2 1 2 - GTK_FILL - @@ -4499,233 +4499,61 @@ Quoted - + True - 6 + 12 - - True - - - False - False - + + + + 1 + + + + + + + True + 6 + + + True + 0 + <b>Preview</b> + True + + + False + False + + + + + True + 12 - + True False False - 1 - + True False GTK_POLICY_AUTOMATIC GTK_POLICY_AUTOMATIC GTK_SHADOW_IN - - True - True - False - - Signatures Table - - + - 2 - - - - - True - 3 - - - True - 6 - GTK_BUTTONBOX_START - - - True - True - True - gtk-add - True - 0 - - - - - True - True - True - 0 - - - - True - 0 - 0 - - - True - 2 - - - True - gtk-execute - - - False - False - - - - - True - Add _Script - True - - - False - False - 1 - - - - - - - - - 1 - - - - - True - True - True - 0 - - - True - 0 - 0 - - - True - 2 - - - True - gtk-properties - - - False - False - - - - - True - _Edit - True - - - False - False - 1 - - - - - - - - - 2 - - - - - True - True - True - gtk-remove - True - 0 - - - 3 - - - - - - - False - False - 3 - - - - - 1 - - - - - - - True - 6 - - - True - 0 - <b>Preview</b> - True - - - False - False - - - - - True - 12 - - - True - - - False - False - - - - - True - False - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_SHADOW_IN - - - - - - 1 + 1 @@ -5045,31 +4873,29 @@ Quoted 12 6 - + True - True - 0 - Select HTML variable width font for printing - + 0 + V_ariable-width: + True + GTK_JUSTIFY_CENTER + print_variable - 1 - 2 GTK_FILL - + True - True - 0 - Select HTML fixed width font for printing - + 0 + Fi_xed-width: + True + GTK_JUSTIFY_CENTER + print_fixed - 1 - 2 1 2 GTK_FILL @@ -5077,15 +4903,16 @@ Quoted - + True - 0 - Fi_xed-width: - True - GTK_JUSTIFY_CENTER - print_fixed + True + 0 + Select HTML fixed width font for printing + + 1 + 2 1 2 GTK_FILL @@ -5093,15 +4920,16 @@ Quoted - + True - 0 - V_ariable-width: - True - GTK_JUSTIFY_CENTER - print_variable + True + 0 + Select HTML variable width font for printing + + 1 + 2 GTK_FILL @@ -5182,31 +5010,19 @@ for display purposes only. 6 6 - + True - + 0 + _Name: + True + GTK_JUSTIFY_CENTER + entry_add_script_name - 1 - 2 - 1 - 2 GTK_FILL - - - True - True - * - - - 1 - 2 - - - True @@ -5224,15 +5040,27 @@ for display purposes only. - + True - 0 - _Name: - True - GTK_JUSTIFY_CENTER - entry_add_script_name + True + * + + + 1 + 2 + + + + + + True + + 1 + 2 + 1 + 2 GTK_FILL @@ -5405,64 +5233,105 @@ for display purposes only. 6 6 - + True - True - * + 0 + H_TTP Proxy: + True + txtHttpHost + + + GTK_FILL + + + + + + True + 0 + _Secure HTTP Proxy: + True + txtHttpsHost + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + S_OCKS Host: + True + txtSocksHost + + + 2 + 3 + GTK_FILL + + + + + + True + 0 + No _Proxy for: + True + txtIgnoreHosts - 1 - 4 3 4 + GTK_FILL - + True True - 0 0 65535 1 10 0 - 1 + * - 3 - 4 - 2 - 3 + 1 + 2 - + True True - 0 0 65535 1 10 0 - 1 + * - 3 - 4 + 1 + 2 1 2 - + True True - 0 0 65535 1 10 0 - 1 + * - 3 - 4 + 1 + 2 + 2 + 3 - + True 0 Port: @@ -5470,8 +5339,6 @@ for display purposes only. 2 3 - 2 - 3 GTK_FILL @@ -5492,7 +5359,7 @@ for display purposes only. - + True 0 Port: @@ -5500,105 +5367,66 @@ for display purposes only. 2 3 + 2 + 3 GTK_FILL - + True True - * + 0 0 65535 1 10 0 + 1 - 1 - 2 - 2 - 3 + 3 + 4 - + True True - * + 0 0 65535 1 10 0 + 1 - 1 - 2 + 3 + 4 1 2 - + True True - * - - - 1 - 2 - - - - - - True - 0 - No _Proxy for: - True - txtIgnoreHosts - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - S_OCKS Host: - True - txtSocksHost + 0 0 65535 1 10 0 + 1 + 3 + 4 2 3 - GTK_FILL - - True - 0 - _Secure HTTP Proxy: - True - txtHttpsHost - - - 1 - 2 - GTK_FILL - - - - - + True - 0 - H_TTP Proxy: - True - txtHttpHost + True + * - GTK_FILL + 1 + 4 + 3 + 4 @@ -5633,28 +5461,16 @@ for display purposes only. 6 3 - - True - True - False - * - - - 1 - 2 - 1 - 2 - - - - + True - True - * + 0 + Us_ername: + True + txtAuthUser - 1 - 2 + GTK_FILL + @@ -5673,16 +5489,28 @@ for display purposes only. - + True - 0 - Us_ername: - True - txtAuthUser + True + * - GTK_FILL - + 1 + 2 + + + + + True + True + False + * + + + 1 + 2 + 1 + 2 diff --git a/mail/mail-config.h b/mail/mail-config.h index a667faf946..ecbdb198ea 100644 --- a/mail/mail-config.h +++ b/mail/mail-config.h @@ -111,8 +111,6 @@ gboolean mail_config_get_enable_magic_spacebar (void); struct _EAccountService *mail_config_get_default_transport (void); /* signatures */ -struct _ESignature *mail_config_signature_new (const char *filename, gboolean script, gboolean html); - char *mail_config_signature_run_script (const char *script); diff --git a/mail/mail-signature-editor.c b/mail/mail-signature-editor.c deleted file mode 100644 index 511942ca77..0000000000 --- a/mail/mail-signature-editor.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * 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 - * - * - * Authors: - * Radek Doulik - * Jeffrey Stedfast - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "mail-signature-editor.h" - -#include -#include - -#include -#include -#include - -#include "mail-config.h" - -#define E_SIGNATURE_EDITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorPrivate)) - -enum { - PROP_0, - PROP_SIGNATURE -}; - -struct _ESignatureEditorPrivate { - GtkActionGroup *action_group; - ESignature *signature; - GtkWidget *entry; - gchar *original_name; -}; - -static const gchar *ui = -"\n" -" \n" -" \n" -" \n" -" \n" -" " -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -""; - -static gpointer parent_class = NULL; - -static void -handle_error (GError **error) -{ - if (*error != NULL) { - g_warning ("%s", (*error)->message); - g_clear_error (error); - } -} - -static void -action_close_cb (GtkAction *action, - ESignatureEditor *editor) -{ - gboolean something_changed = FALSE; - const gchar *original_name; - const gchar *signature_name; - - original_name = editor->priv->original_name; - signature_name = gtk_entry_get_text (GTK_ENTRY (editor->priv->entry)); - - something_changed |= gtkhtml_editor_has_undo (GTKHTML_EDITOR (editor)); - something_changed |= (strcmp (signature_name, original_name) != 0); - - if (something_changed) { - gint response; - - response = e_error_run ( - GTK_WINDOW (editor), - "mail:ask-signature-changed", NULL); - if (response == GTK_RESPONSE_YES) { - GtkActionGroup *action_group; - - action_group = editor->priv->action_group; - action = gtk_action_group_get_action ( - action_group, "save-and-close"); - gtk_action_activate (action); - return; - } else if (response == GTK_RESPONSE_CANCEL) - return; - } - - gtk_widget_destroy (GTK_WIDGET (editor)); -} - -static void -action_save_and_close_cb (GtkAction *action, - ESignatureEditor *editor) -{ - GtkWidget *entry; - ESignatureList *signature_list; - ESignature *signature; - ESignature *same_name; - const gchar *filename; - gchar *signature_name; - gboolean html; - GError *error = NULL; - - entry = editor->priv->entry; - html = gtkhtml_editor_get_html_mode (GTKHTML_EDITOR (editor)); - - if (editor->priv->signature == NULL) - signature = mail_config_signature_new (NULL, FALSE, html); - else { - signature = g_object_ref (editor->priv->signature); - signature->html = html; - } - - filename = signature->filename; - gtkhtml_editor_save (GTKHTML_EDITOR (editor), filename, html, &error); - - if (error != NULL) { - e_error_run ( - GTK_WINDOW (editor), - "mail:no-save-signature", - error->message, NULL); - g_clear_error (&error); - return; - } - - signature_list = e_get_signature_list (); - - signature_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))); - g_strstrip (signature_name); - - /* Make sure the signature name is not blank. */ - if (*signature_name == '\0') { - e_error_run ( - GTK_WINDOW (editor), - "mail:blank-signature", NULL); - gtk_widget_grab_focus (entry); - g_free (signature_name); - return; - } - - /* Don't overwrite an existing signature of the same name. - * XXX ESignatureList misuses const. */ - same_name = (ESignature *) e_signature_list_find ( - signature_list, E_SIGNATURE_FIND_NAME, signature_name); - if (same_name != NULL && strcmp (signature->uid, same_name->uid) != 0) { - e_error_run ( - GTK_WINDOW (editor), - "mail:signature-already-exists", - signature_name, NULL); - gtk_widget_grab_focus (entry); - g_free (signature_name); - return; - } - - g_free (signature->name); - signature->name = signature_name; - - if (editor->priv->signature != NULL) - e_signature_list_change (signature_list, signature); - else { - e_signature_list_add (signature_list, signature); - e_signature_list_save (signature_list); - } - - gtk_widget_destroy (GTK_WIDGET (editor)); -} - -static GtkActionEntry entries[] = { - - { "close", - GTK_STOCK_CLOSE, - N_("_Close"), - "w", - NULL, - G_CALLBACK (action_close_cb) }, - - { "save-and-close", - GTK_STOCK_SAVE, - N_("_Save and Close"), - "Return", - NULL, - G_CALLBACK (action_save_and_close_cb) }, - - { "file-menu", - NULL, - N_("_File"), - NULL, - NULL, - NULL } -}; - -static gboolean -signature_editor_delete_event_cb (ESignatureEditor *editor, - GdkEvent *event) -{ - GtkActionGroup *action_group; - GtkAction *action; - - action_group = editor->priv->action_group; - action = gtk_action_group_get_action (action_group, "close"); - gtk_action_activate (action); - - return TRUE; -} - -static void -signature_editor_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_SIGNATURE: - e_signature_editor_set_signature ( - E_SIGNATURE_EDITOR (object), - g_value_get_object (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -signature_editor_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_SIGNATURE: - g_value_set_object ( - value, e_signature_editor_get_signature ( - E_SIGNATURE_EDITOR (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -signature_editor_dispose (GObject *object) -{ - ESignatureEditorPrivate *priv; - - priv = E_SIGNATURE_EDITOR_GET_PRIVATE (object); - - if (priv->action_group != NULL) { - g_object_unref (priv->action_group); - priv->action_group = NULL; - } - - if (priv->signature != NULL) { - g_object_unref (priv->signature); - priv->signature = NULL; - } - - if (priv->entry != NULL) { - g_object_unref (priv->entry); - priv->entry = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -signature_editor_finalize (GObject *object) -{ - ESignatureEditorPrivate *priv; - - priv = E_SIGNATURE_EDITOR_GET_PRIVATE (object); - - g_free (priv->original_name); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -signature_editor_class_init (ESignatureEditorClass *class) -{ - GObjectClass *object_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (ESignatureEditorPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = signature_editor_set_property; - object_class->get_property = signature_editor_get_property; - object_class->dispose = signature_editor_dispose; - object_class->finalize = signature_editor_finalize; - - g_object_class_install_property ( - object_class, - PROP_SIGNATURE, - g_param_spec_object ( - "signature", - NULL, - NULL, - E_TYPE_SIGNATURE, - G_PARAM_READWRITE)); -} - -static void -signature_editor_init (ESignatureEditor *editor) -{ - GtkActionGroup *action_group; - GtkUIManager *manager; - GtkWidget *container; - GtkWidget *widget; - GtkWidget *vbox; - GError *error = NULL; - - editor->priv = E_SIGNATURE_EDITOR_GET_PRIVATE (editor); - vbox = GTKHTML_EDITOR (editor)->vbox; - - manager = gtkhtml_editor_get_ui_manager (GTKHTML_EDITOR (editor)); - - gtk_ui_manager_add_ui_from_string (manager, ui, -1, &error); - handle_error (&error); - - action_group = gtk_action_group_new ("signature"); - gtk_action_group_set_translation_domain ( - action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions ( - action_group, entries, - G_N_ELEMENTS (entries), editor); - gtk_ui_manager_insert_action_group (manager, action_group, 0); - editor->priv->action_group = g_object_ref (action_group); - - gtk_ui_manager_ensure_update (manager); - - gtk_window_set_title (GTK_WINDOW (editor), _("Edit Signature")); - - widget = gtk_hbox_new (FALSE, 6); - gtk_container_set_border_width (GTK_CONTAINER (widget), 6); - gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); - /* Position 2 should be between the main and style toolbars. */ - gtk_box_reorder_child (GTK_BOX (vbox), widget, 2); - gtk_widget_show (widget); - container = widget; - - widget = gtk_entry_new (); - gtk_box_pack_end (GTK_BOX (container), widget, TRUE, TRUE, 0); - editor->priv->entry = g_object_ref_sink (widget); - gtk_widget_show (widget); - - widget = gtk_label_new_with_mnemonic (_("_Signature Name:")); - gtk_label_set_mnemonic_widget (GTK_LABEL (widget), editor->priv->entry); - gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - g_signal_connect ( - editor, "delete-event", - G_CALLBACK (signature_editor_delete_event_cb), NULL); - - e_signature_editor_set_signature (editor, NULL); -} - -GType -e_signature_editor_get_type (void) -{ - static GType type = 0; - - if (G_UNLIKELY (type == 0)) { - static const GTypeInfo type_info = { - sizeof (ESignatureEditorClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) signature_editor_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (ESignatureEditor), - 0, /* n_preallocs */ - (GInstanceInitFunc) signature_editor_init, - NULL /* value_table */ - }; - - type = g_type_register_static ( - GTKHTML_TYPE_EDITOR, "ESignatureEditor", - &type_info, 0); - } - - return type; -} - -GtkWidget * -e_signature_editor_new (void) -{ - return g_object_new (E_TYPE_SIGNATURE_EDITOR, NULL); -} - -ESignature * -e_signature_editor_get_signature (ESignatureEditor *editor) -{ - g_return_val_if_fail (E_IS_SIGNATURE_EDITOR (editor), NULL); - - return editor->priv->signature; -} - -void -e_signature_editor_set_signature (ESignatureEditor *editor, - ESignature *signature) -{ - const gchar *filename; - const gchar *signature_name; - gchar *contents; - gsize length; - GError *error = NULL; - - g_return_if_fail (E_IS_SIGNATURE_EDITOR (editor)); - - if (signature != NULL) - g_return_if_fail (E_SIGNATURE (signature)); - - if (editor->priv->signature != NULL) { - g_object_unref (editor->priv->signature); - editor->priv->signature = NULL; - } - - if (signature == NULL) - goto exit; - - editor->priv->signature = g_object_ref (signature); - - /* Load signature content. */ - - filename = signature->filename; - - if (signature->html) - g_file_get_contents (filename, &contents, &length, &error); - else { - gchar *data; - - data = e_msg_composer_get_sig_file_content (filename, FALSE); - contents = g_strdup_printf ("
\n%s", data);
-		length = -1;
-		g_free (data);
-	}
-
-	if (error == NULL) {
-		gtkhtml_editor_set_html_mode (
-			GTKHTML_EDITOR (editor), signature->html);
-		gtkhtml_editor_set_text_html (
-			GTKHTML_EDITOR (editor), contents, length);
-		g_free (contents);
-	} else {
-		g_warning ("%s", error->message);
-		g_error_free (error);
-	}
-
-exit:
-	if (signature != NULL)
-		signature_name = signature->name;
-	else
-		signature_name = _("Unnamed");
-
-	/* Set the entry text before we grab focus. */
-	g_free (editor->priv->original_name);
-	editor->priv->original_name = g_strdup (signature_name);
-	gtk_entry_set_text (GTK_ENTRY (editor->priv->entry), signature_name);
-
-	/* Set the focus appropriately.  If this is a new signature, draw
-	 * the user's attention to the signature name entry.  Otherwise go
-	 * straight to the editing area. */
-	if (signature == NULL)
-		gtk_widget_grab_focus (editor->priv->entry);
-	else {
-		GtkHTML *html;
-
-		html = gtkhtml_editor_get_html (GTKHTML_EDITOR (editor));
-		gtk_widget_grab_focus (GTK_WIDGET (html));
-	}
-
-	g_object_notify (G_OBJECT (editor), "signature");
-}
diff --git a/mail/mail-signature-editor.h b/mail/mail-signature-editor.h
deleted file mode 100644
index 649504be18..0000000000
--- a/mail/mail-signature-editor.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- *
- * 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   
- *
- *
- * Authors:
- *		Radek Doulik 
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef MAIL_SIGNATURE_EDITOR_H
-#define MAIL_SIGNATURE_EDITOR_H
-
-#include 
-#include 
-
-/* Standard GObject macros */
-#define E_TYPE_SIGNATURE_EDITOR \
-	(e_signature_editor_get_type ())
-#define E_SIGNATURE_EDITOR(obj) \
-	(G_TYPE_CHECK_INSTANCE_CAST \
-	((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditor))
-#define E_SIGNATURE_EDITOR_CLASS(cls) \
-	(G_TYPE_CHECK_CLASS_CAST \
-	((cls), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorClass))
-#define E_IS_SIGNATURE_EDITOR(obj) \
-	(G_TYPE_CHECK_INSTANCE_TYPE \
-	((obj), E_TYPE_SIGNATURE_EDITOR))
-#define E_IS_SIGNATURE_EDITOR_CLASS(cls) \
-	(G_TYPE_CHECK_CLASS_TYPE \
-	((cls), E_TYPE_SIGNATURE_EDITOR))
-#define E_SIGNATURE_EDITOR_GET_CLASS(obj) \
-	(G_TYPE_INSTANCE_GET_CLASS \
-	((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ESignatureEditor ESignatureEditor;
-typedef struct _ESignatureEditorClass ESignatureEditorClass;
-typedef struct _ESignatureEditorPrivate ESignatureEditorPrivate;
-
-struct _ESignatureEditor {
-	GtkhtmlEditor parent;
-	ESignatureEditorPrivate *priv;
-};
-
-struct _ESignatureEditorClass {
-	GtkhtmlEditorClass parent_class;
-};
-
-GType		e_signature_editor_get_type	 (void);
-GtkWidget *	e_signature_editor_new		 (void);
-ESignature *	e_signature_editor_get_signature (ESignatureEditor *editor);
-void		e_signature_editor_set_signature (ESignatureEditor *editor,
-						  ESignature *signature);
-
-G_END_DECLS
-
-#endif /* MAIL_SIGNATURE_EDITOR_H */
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index ce702ec9fd..a1d555085b 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -78,6 +78,10 @@ widgetsinclude_HEADERS =			\
 	e-selection-model-simple.h		\
 	e-selection-model.h			\
 	e-signature-combo-box.h			\
+	e-signature-editor.h			\
+	e-signature-manager.h			\
+	e-signature-script-dialog.h		\
+	e-signature-tree-view.h			\
 	e-unicode.h				\
 	e-colors.h
 
@@ -125,6 +129,10 @@ libemiscwidgets_la_SOURCES =			\
 	e-selection-model-simple.c		\
 	e-selection-model.c			\
 	e-signature-combo-box.c			\
+	e-signature-editor.c			\
+	e-signature-manager.c			\
+	e-signature-script-dialog.c		\
+	e-signature-tree-view.c			\
 	e-unicode.c				\
 	e-colors.c
 
diff --git a/widgets/misc/e-signature-combo-box.c b/widgets/misc/e-signature-combo-box.c
index 9ebd20a0b2..40a93b7d25 100644
--- a/widgets/misc/e-signature-combo-box.c
+++ b/widgets/misc/e-signature-combo-box.c
@@ -1,4 +1,5 @@
 /*
+ * e-signature-combo-box.c
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
diff --git a/widgets/misc/e-signature-combo-box.h b/widgets/misc/e-signature-combo-box.h
index ec05c2b5d7..5cdd224e6b 100644
--- a/widgets/misc/e-signature-combo-box.h
+++ b/widgets/misc/e-signature-combo-box.h
@@ -1,4 +1,5 @@
 /*
+ * e-signature-combo-box.h
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
diff --git a/widgets/misc/e-signature-editor.c b/widgets/misc/e-signature-editor.c
new file mode 100644
index 0000000000..c7dcbdaad9
--- /dev/null
+++ b/widgets/misc/e-signature-editor.c
@@ -0,0 +1,503 @@
+/*
+ * e-signature-editor.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   
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-signature-editor.h"
+
+#include 
+#include 
+
+#include 
+#include 
+
+#define E_SIGNATURE_EDITOR_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorPrivate))
+
+enum {
+	PROP_0,
+	PROP_SIGNATURE
+};
+
+struct _ESignatureEditorPrivate {
+	GtkActionGroup *action_group;
+	ESignature *signature;
+	GtkWidget *entry;
+	gchar *original_name;
+};
+
+static const gchar *ui =
+"\n"
+"  \n"
+"    \n"
+"      \n"
+"        \n"
+"        "
+"        \n"
+"      \n"
+"    \n"
+"  \n"
+"  \n"
+"    \n"
+"      \n"
+"    \n"
+"  \n"
+"";
+
+static gpointer parent_class = NULL;
+
+static void
+handle_error (GError **error)
+{
+	if (*error != NULL) {
+		g_warning ("%s", (*error)->message);
+		g_clear_error (error);
+	}
+}
+
+static void
+action_close_cb (GtkAction *action,
+                 ESignatureEditor *editor)
+{
+	gboolean something_changed = FALSE;
+	const gchar *original_name;
+	const gchar *signature_name;
+
+	original_name = editor->priv->original_name;
+	signature_name = gtk_entry_get_text (GTK_ENTRY (editor->priv->entry));
+
+	something_changed |= gtkhtml_editor_has_undo (GTKHTML_EDITOR (editor));
+	something_changed |= (strcmp (signature_name, original_name) != 0);
+
+	if (something_changed) {
+		gint response;
+
+		response = e_error_run (
+			GTK_WINDOW (editor),
+			"mail:ask-signature-changed", NULL);
+		if (response == GTK_RESPONSE_YES) {
+			GtkActionGroup *action_group;
+
+			action_group = editor->priv->action_group;
+			action = gtk_action_group_get_action (
+				action_group, "save-and-close");
+			gtk_action_activate (action);
+			return;
+		} else if (response == GTK_RESPONSE_CANCEL)
+			return;
+	}
+
+	gtk_widget_destroy (GTK_WIDGET (editor));
+}
+
+static void
+action_save_and_close_cb (GtkAction *action,
+                          ESignatureEditor *editor)
+{
+	GtkWidget *entry;
+	ESignatureList *signature_list;
+	ESignature *signature;
+	ESignature *same_name;
+	const gchar *filename;
+	gchar *signature_name;
+	gboolean html;
+	GError *error = NULL;
+
+	entry = editor->priv->entry;
+	html = gtkhtml_editor_get_html_mode (GTKHTML_EDITOR (editor));
+
+	if (editor->priv->signature == NULL) {
+		signature = e_signature_new ();
+		signature->name = g_strdup (_("Unnamed"));
+		signature->script = FALSE;
+		signature->html = html;
+
+		/* FIXME Pass a GError and deal with it. */
+		signature->filename = e_create_signature_file (NULL);
+	} else {
+		signature = g_object_ref (editor->priv->signature);
+		signature->html = html;
+	}
+
+	filename = signature->filename;
+	gtkhtml_editor_save (GTKHTML_EDITOR (editor), filename, html, &error);
+
+	if (error != NULL) {
+		e_error_run (
+			GTK_WINDOW (editor),
+			"mail:no-save-signature",
+			error->message, NULL);
+		g_clear_error (&error);
+		return;
+	}
+
+	signature_list = e_get_signature_list ();
+
+	signature_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+	g_strstrip (signature_name);
+
+	/* Make sure the signature name is not blank. */
+	if (*signature_name == '\0') {
+		e_error_run (
+			GTK_WINDOW (editor),
+			"mail:blank-signature", NULL);
+		gtk_widget_grab_focus (entry);
+		g_free (signature_name);
+		return;
+	}
+
+	/* Don't overwrite an existing signature of the same name.
+	 * XXX ESignatureList misuses const. */
+	same_name = (ESignature *) e_signature_list_find (
+		signature_list, E_SIGNATURE_FIND_NAME, signature_name);
+	if (same_name != NULL && strcmp (signature->uid, same_name->uid) != 0) {
+		e_error_run (
+			GTK_WINDOW (editor),
+			"mail:signature-already-exists",
+			signature_name, NULL);
+		gtk_widget_grab_focus (entry);
+		g_free (signature_name);
+		return;
+	}
+
+	g_free (signature->name);
+	signature->name = signature_name;
+
+	if (editor->priv->signature != NULL)
+		e_signature_list_change (signature_list, signature);
+	else
+		e_signature_list_add (signature_list, signature);
+	e_signature_list_save (signature_list);
+
+	gtk_widget_destroy (GTK_WIDGET (editor));
+}
+
+static GtkActionEntry entries[] = {
+
+	{ "close",
+	  GTK_STOCK_CLOSE,
+	  N_("_Close"),
+	  "w",
+	  NULL,
+	  G_CALLBACK (action_close_cb) },
+
+	{ "save-and-close",
+	  GTK_STOCK_SAVE,
+	  N_("_Save and Close"),
+	  "Return",
+	  NULL,
+	  G_CALLBACK (action_save_and_close_cb) },
+
+	{ "file-menu",
+	  NULL,
+	  N_("_File"),
+	  NULL,
+	  NULL,
+	  NULL }
+};
+
+static gboolean
+signature_editor_delete_event_cb (ESignatureEditor *editor,
+                                  GdkEvent *event)
+{
+	GtkActionGroup *action_group;
+	GtkAction *action;
+
+	action_group = editor->priv->action_group;
+	action = gtk_action_group_get_action (action_group, "close");
+	gtk_action_activate (action);
+
+	return TRUE;
+}
+
+static void
+signature_editor_set_property (GObject *object,
+                               guint property_id,
+                               const GValue *value,
+                               GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_SIGNATURE:
+			e_signature_editor_set_signature (
+				E_SIGNATURE_EDITOR (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_editor_get_property (GObject *object,
+                               guint property_id,
+                               GValue *value,
+                               GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_SIGNATURE:
+			g_value_set_object (
+				value, e_signature_editor_get_signature (
+				E_SIGNATURE_EDITOR (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_editor_dispose (GObject *object)
+{
+	ESignatureEditorPrivate *priv;
+
+	priv = E_SIGNATURE_EDITOR_GET_PRIVATE (object);
+
+	if (priv->action_group != NULL) {
+		g_object_unref (priv->action_group);
+		priv->action_group = NULL;
+	}
+
+	if (priv->signature != NULL) {
+		g_object_unref (priv->signature);
+		priv->signature = NULL;
+	}
+
+	if (priv->entry != NULL) {
+		g_object_unref (priv->entry);
+		priv->entry = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+signature_editor_finalize (GObject *object)
+{
+	ESignatureEditorPrivate *priv;
+
+	priv = E_SIGNATURE_EDITOR_GET_PRIVATE (object);
+
+	g_free (priv->original_name);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+signature_editor_class_init (ESignatureEditorClass *class)
+{
+	GObjectClass *object_class;
+
+	parent_class = g_type_class_peek_parent (class);
+	g_type_class_add_private (class, sizeof (ESignatureEditorPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = signature_editor_set_property;
+	object_class->get_property = signature_editor_get_property;
+	object_class->dispose = signature_editor_dispose;
+	object_class->finalize = signature_editor_finalize;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SIGNATURE,
+		g_param_spec_object (
+			"signature",
+			NULL,
+			NULL,
+			E_TYPE_SIGNATURE,
+			G_PARAM_READWRITE));
+}
+
+static void
+signature_editor_init (ESignatureEditor *editor)
+{
+	GtkActionGroup *action_group;
+	GtkUIManager *manager;
+	GtkWidget *container;
+	GtkWidget *widget;
+	GtkWidget *vbox;
+	GError *error = NULL;
+
+	editor->priv = E_SIGNATURE_EDITOR_GET_PRIVATE (editor);
+	vbox = GTKHTML_EDITOR (editor)->vbox;
+
+	manager = gtkhtml_editor_get_ui_manager (GTKHTML_EDITOR (editor));
+
+	gtk_ui_manager_add_ui_from_string (manager, ui, -1, &error);
+	handle_error (&error);
+
+	action_group = gtk_action_group_new ("signature");
+	gtk_action_group_set_translation_domain (
+		action_group, GETTEXT_PACKAGE);
+	gtk_action_group_add_actions (
+		action_group, entries,
+		G_N_ELEMENTS (entries), editor);
+	gtk_ui_manager_insert_action_group (manager, action_group, 0);
+	editor->priv->action_group = g_object_ref (action_group);
+
+	gtk_ui_manager_ensure_update (manager);
+
+	gtk_window_set_title (GTK_WINDOW (editor), _("Edit Signature"));
+
+	widget = gtk_hbox_new (FALSE, 6);
+	gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
+	gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
+	/* Position 2 should be between the main and style toolbars. */
+	gtk_box_reorder_child (GTK_BOX (vbox), widget, 2);
+	gtk_widget_show (widget);
+	container = widget;
+
+	widget = gtk_entry_new ();
+	gtk_box_pack_end (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	editor->priv->entry = g_object_ref_sink (widget);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new_with_mnemonic (_("_Signature Name:"));
+	gtk_label_set_mnemonic_widget (GTK_LABEL (widget), editor->priv->entry);
+	gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	g_signal_connect (
+		editor, "delete-event",
+		G_CALLBACK (signature_editor_delete_event_cb), NULL);
+
+	e_signature_editor_set_signature (editor, NULL);
+}
+
+GType
+e_signature_editor_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo type_info = {
+			sizeof (ESignatureEditorClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) signature_editor_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,  /* class_data */
+			sizeof (ESignatureEditor),
+			0,     /* n_preallocs */
+			(GInstanceInitFunc) signature_editor_init,
+			NULL   /* value_table */
+		};
+
+		type = g_type_register_static (
+			GTKHTML_TYPE_EDITOR, "ESignatureEditor",
+			&type_info, 0);
+	}
+
+	return type;
+}
+
+GtkWidget *
+e_signature_editor_new (void)
+{
+	return g_object_new (E_TYPE_SIGNATURE_EDITOR, NULL);
+}
+
+ESignature *
+e_signature_editor_get_signature (ESignatureEditor *editor)
+{
+	g_return_val_if_fail (E_IS_SIGNATURE_EDITOR (editor), NULL);
+
+	return editor->priv->signature;
+}
+
+void
+e_signature_editor_set_signature (ESignatureEditor *editor,
+                                  ESignature *signature)
+{
+	const gchar *filename;
+	const gchar *signature_name;
+	gchar *contents;
+	gsize length;
+	GError *error = NULL;
+
+	g_return_if_fail (E_IS_SIGNATURE_EDITOR (editor));
+
+	if (signature != NULL)
+		g_return_if_fail (E_SIGNATURE (signature));
+
+	if (editor->priv->signature != NULL) {
+		g_object_unref (editor->priv->signature);
+		editor->priv->signature = NULL;
+	}
+
+	if (signature == NULL)
+		goto exit;
+
+	editor->priv->signature = g_object_ref (signature);
+
+	/* Load signature content. */
+
+	filename = signature->filename;
+
+	if (signature->html)
+		g_file_get_contents (filename, &contents, &length, &error);
+	else {
+		gchar *data;
+
+		data = e_read_signature_file (signature, FALSE, &error);
+		if (data != NULL)
+			contents = g_strdup_printf ("
\n%s", data);
+		else
+			contents = NULL;
+		length = -1;
+		g_free (data);
+	}
+
+	if (error == NULL) {
+		gtkhtml_editor_set_html_mode (
+			GTKHTML_EDITOR (editor), signature->html);
+		gtkhtml_editor_set_text_html (
+			GTKHTML_EDITOR (editor), contents, length);
+		g_free (contents);
+	} else {
+		g_warning ("%s", error->message);
+		g_error_free (error);
+	}
+
+exit:
+	if (signature != NULL)
+		signature_name = signature->name;
+	else
+		signature_name = _("Unnamed");
+
+	/* Set the entry text before we grab focus. */
+	g_free (editor->priv->original_name);
+	editor->priv->original_name = g_strdup (signature_name);
+	gtk_entry_set_text (GTK_ENTRY (editor->priv->entry), signature_name);
+
+	/* Set the focus appropriately.  If this is a new signature, draw
+	 * the user's attention to the signature name entry.  Otherwise go
+	 * straight to the editing area. */
+	if (signature == NULL)
+		gtk_widget_grab_focus (editor->priv->entry);
+	else {
+		GtkHTML *html;
+
+		html = gtkhtml_editor_get_html (GTKHTML_EDITOR (editor));
+		gtk_widget_grab_focus (GTK_WIDGET (html));
+	}
+
+	g_object_notify (G_OBJECT (editor), "signature");
+}
diff --git a/widgets/misc/e-signature-editor.h b/widgets/misc/e-signature-editor.h
new file mode 100644
index 0000000000..9d6c37ac87
--- /dev/null
+++ b/widgets/misc/e-signature-editor.h
@@ -0,0 +1,70 @@
+/*
+ * e-signature-editor.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   
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_SIGNATURE_EDITOR_H
+#define E_SIGNATURE_EDITOR_H
+
+#include 
+#include 
+
+/* Standard GObject macros */
+#define E_TYPE_SIGNATURE_EDITOR \
+	(e_signature_editor_get_type ())
+#define E_SIGNATURE_EDITOR(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditor))
+#define E_SIGNATURE_EDITOR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorClass))
+#define E_IS_SIGNATURE_EDITOR(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_SIGNATURE_EDITOR))
+#define E_IS_SIGNATURE_EDITOR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_SIGNATURE_EDITOR))
+#define E_SIGNATURE_EDITOR_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESignatureEditor ESignatureEditor;
+typedef struct _ESignatureEditorClass ESignatureEditorClass;
+typedef struct _ESignatureEditorPrivate ESignatureEditorPrivate;
+
+struct _ESignatureEditor {
+	GtkhtmlEditor parent;
+	ESignatureEditorPrivate *priv;
+};
+
+struct _ESignatureEditorClass {
+	GtkhtmlEditorClass parent_class;
+};
+
+GType		e_signature_editor_get_type	 (void);
+GtkWidget *	e_signature_editor_new		 (void);
+ESignature *	e_signature_editor_get_signature (ESignatureEditor *editor);
+void		e_signature_editor_set_signature (ESignatureEditor *editor,
+						  ESignature *signature);
+
+G_END_DECLS
+
+#endif /* E_SIGNATURE_EDITOR_H */
diff --git a/widgets/misc/e-signature-manager.c b/widgets/misc/e-signature-manager.c
new file mode 100644
index 0000000000..0c145e9821
--- /dev/null
+++ b/widgets/misc/e-signature-manager.c
@@ -0,0 +1,746 @@
+/*
+ * e-signature-manager.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   
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-signature-manager.h"
+
+#include 
+#include 
+#include 
+#include "e-util/e-binding.h"
+#include "e-signature-tree-view.h"
+#include "e-signature-script-dialog.h"
+
+#define E_SIGNATURE_MANAGER_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_SIGNATURE_MANAGER, ESignatureManagerPrivate))
+
+struct _ESignatureManagerPrivate {
+	ESignatureList *signature_list;
+
+	GtkWidget *tree_view;
+	GtkWidget *add_button;
+	GtkWidget *add_script_button;
+	GtkWidget *edit_button;
+	GtkWidget *remove_button;
+
+	guint allow_scripts : 1;
+	guint prefer_html   : 1;
+};
+
+enum {
+	PROP_0,
+	PROP_ALLOW_SCRIPTS,
+	PROP_PREFER_HTML,
+	PROP_SIGNATURE_LIST
+};
+
+enum {
+	ADD_SIGNATURE,
+	ADD_SIGNATURE_SCRIPT,
+	EDITOR_CREATED,
+	EDIT_SIGNATURE,
+	REMOVE_SIGNATURE,
+	LAST_SIGNAL
+};
+
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
+
+static void
+signature_manager_emit_editor_created (ESignatureManager *manager,
+                                       GtkWidget *editor)
+{
+	g_return_if_fail (E_IS_SIGNATURE_EDITOR (editor));
+
+	g_signal_emit (manager, signals[EDITOR_CREATED], 0, editor);
+}
+
+static gboolean
+signature_manager_key_press_event_cb (ESignatureManager *manager,
+                                      GdkEventKey *event)
+{
+	if (event->keyval == GDK_Delete) {
+		e_signature_manager_remove_signature (manager);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static gboolean
+signature_manager_run_script_dialog (ESignatureManager *manager,
+                                     ESignature *signature,
+                                     const gchar *title)
+{
+	GtkWidget *dialog;
+	GFile *script_file;
+	const gchar *script_name;
+	gboolean success = FALSE;
+	gpointer parent;
+
+	parent = gtk_widget_get_toplevel (GTK_WIDGET (manager));
+	parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
+
+	dialog = e_signature_script_dialog_new (parent);
+	gtk_window_set_title (GTK_WINDOW (dialog), title);
+
+	if (signature->filename != NULL && signature->name != NULL) {
+
+		script_file = g_file_new_for_path (signature->filename);
+		script_name = signature->name;
+
+		e_signature_script_dialog_set_script_file (
+			E_SIGNATURE_SCRIPT_DIALOG (dialog), script_file);
+		e_signature_script_dialog_set_script_name (
+			E_SIGNATURE_SCRIPT_DIALOG (dialog), script_name);
+
+		g_object_unref (script_file);
+	}
+
+	if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK)
+		goto exit;
+
+	script_file = e_signature_script_dialog_get_script_file (
+		E_SIGNATURE_SCRIPT_DIALOG (dialog));
+	script_name = e_signature_script_dialog_get_script_name (
+		E_SIGNATURE_SCRIPT_DIALOG (dialog));
+
+	g_free (signature->filename);
+	signature->filename = g_file_get_path (script_file);
+
+	g_free (signature->name);
+	signature->name = g_strdup (script_name);
+
+	g_object_unref (script_file);
+
+	success = TRUE;
+
+exit:
+	gtk_widget_destroy (dialog);
+
+	return success;
+}
+
+static void
+signature_manager_selection_changed_cb (ESignatureManager *manager,
+                                        GtkTreeSelection *selection)
+{
+	GtkWidget *edit_button;
+	GtkWidget *remove_button;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+
+	edit_button = manager->priv->edit_button;
+	remove_button = manager->priv->remove_button;
+
+	if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+		gtk_widget_set_sensitive (edit_button, TRUE);
+		gtk_widget_set_sensitive (remove_button, TRUE);
+	} else {
+		gtk_widget_set_sensitive (edit_button, FALSE);
+		gtk_widget_set_sensitive (remove_button, FALSE);
+	}
+}
+
+static void
+signature_manager_set_property (GObject *object,
+                                guint property_id,
+                                const GValue *value,
+                                GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ALLOW_SCRIPTS:
+			e_signature_manager_set_allow_scripts (
+				E_SIGNATURE_MANAGER (object),
+				g_value_get_boolean (value));
+			return;
+
+		case PROP_PREFER_HTML:
+			e_signature_manager_set_prefer_html (
+				E_SIGNATURE_MANAGER (object),
+				g_value_get_boolean (value));
+			return;
+
+		case PROP_SIGNATURE_LIST:
+			e_signature_manager_set_signature_list (
+				E_SIGNATURE_MANAGER (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_manager_get_property (GObject *object,
+                                guint property_id,
+                                GValue *value,
+                                GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ALLOW_SCRIPTS:
+			g_value_set_boolean (
+				value,
+				e_signature_manager_get_allow_scripts (
+				E_SIGNATURE_MANAGER (object)));
+			return;
+
+		case PROP_PREFER_HTML:
+			g_value_set_boolean (
+				value,
+				e_signature_manager_get_prefer_html (
+				E_SIGNATURE_MANAGER (object)));
+			return;
+
+		case PROP_SIGNATURE_LIST:
+			g_value_set_object (
+				value,
+				e_signature_manager_get_signature_list (
+				E_SIGNATURE_MANAGER (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_manager_dispose (GObject *object)
+{
+	ESignatureManagerPrivate *priv;
+
+	priv = E_SIGNATURE_MANAGER_GET_PRIVATE (object);
+
+	if (priv->signature_list != NULL) {
+		g_object_unref (priv->signature_list);
+		priv->signature_list = NULL;
+	}
+
+	if (priv->tree_view != NULL) {
+		g_object_unref (priv->tree_view);
+		priv->tree_view = NULL;
+	}
+
+	if (priv->add_button != NULL) {
+		g_object_unref (priv->add_button);
+		priv->add_button = NULL;
+	}
+
+	if (priv->add_script_button != NULL) {
+		g_object_unref (priv->add_script_button);
+		priv->add_script_button = NULL;
+	}
+
+	if (priv->edit_button != NULL) {
+		g_object_unref (priv->edit_button);
+		priv->edit_button = NULL;
+	}
+
+	if (priv->remove_button != NULL) {
+		g_object_unref (priv->remove_button);
+		priv->remove_button = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+signature_manager_add_signature (ESignatureManager *manager)
+{
+	ESignatureTreeView *tree_view;
+	GtkWidget *editor;
+
+	tree_view = e_signature_manager_get_tree_view (manager);
+
+	editor = e_signature_editor_new ();
+	gtkhtml_editor_set_html_mode (
+		GTKHTML_EDITOR (editor), manager->priv->prefer_html);
+	signature_manager_emit_editor_created (manager, editor);
+
+	gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+}
+
+static void
+signature_manager_add_signature_script (ESignatureManager *manager)
+{
+	ESignatureTreeView *tree_view;
+	ESignatureList *signature_list;
+	ESignature *signature;
+	const gchar *title;
+
+	title = _("Add Signature Script");
+	tree_view = e_signature_manager_get_tree_view (manager);
+	signature_list = e_signature_manager_get_signature_list (manager);
+
+	signature = e_signature_new ();
+	signature->script = TRUE;
+	signature->html = TRUE;
+
+	if (signature_manager_run_script_dialog (manager, signature, title))
+		e_signature_list_add (signature_list, signature);
+
+	e_signature_list_save (signature_list);
+	g_object_unref (signature);
+
+	gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+}
+
+static void
+signature_manager_editor_created (ESignatureManager *manager,
+                                  ESignatureEditor *editor)
+{
+	GtkWindowPosition position;
+	gpointer parent;
+
+	position = GTK_WIN_POS_CENTER_ON_PARENT;
+	parent = gtk_widget_get_toplevel (GTK_WIDGET (manager));
+	parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
+
+	gtk_window_set_transient_for (GTK_WINDOW (editor), parent);
+	gtk_window_set_position (GTK_WINDOW (editor), position);
+	gtk_widget_show (GTK_WIDGET (editor));
+}
+
+static void
+signature_manager_edit_signature (ESignatureManager *manager)
+{
+	ESignatureTreeView *tree_view;
+	ESignatureList *signature_list;
+	ESignature *signature;
+	GtkWidget *editor;
+	const gchar *title;
+	gchar *filename;
+
+	tree_view = e_signature_manager_get_tree_view (manager);
+	signature = e_signature_tree_view_get_selected (tree_view);
+	signature_list = e_signature_manager_get_signature_list (manager);
+
+	if (signature == NULL)
+		return;
+
+	if (signature->script)
+		goto script;
+
+	filename = signature->filename;
+	if (filename == NULL || *filename == '\0') {
+		g_free (filename);
+		filename = g_strdup (_("Unnamed"));
+		signature->filename = filename;
+	}
+
+	editor = e_signature_editor_new ();
+	e_signature_editor_set_signature (
+		E_SIGNATURE_EDITOR (editor), signature);
+	signature_manager_emit_editor_created (manager, editor);
+
+	goto exit;
+
+script:
+	title = _("Edit Signature Script");
+
+	if (signature_manager_run_script_dialog (manager, signature, title))
+		e_signature_list_change (signature_list, signature);
+
+	e_signature_list_save (signature_list);
+
+exit:
+	gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+
+	g_object_unref (signature);
+}
+
+static void
+signature_manager_remove_signature (ESignatureManager *manager)
+{
+	ESignatureTreeView *tree_view;
+	ESignatureList *signature_list;
+	ESignature *signature;
+
+	tree_view = e_signature_manager_get_tree_view (manager);
+	signature = e_signature_tree_view_get_selected (tree_view);
+	signature_list = e_signature_tree_view_get_signature_list (tree_view);
+
+	if (signature == NULL)
+		return;
+
+	if (signature->filename != NULL && !signature->script)
+		g_unlink (signature->filename);
+
+	e_signature_list_remove (signature_list, signature);
+	e_signature_list_save (signature_list);
+
+	gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+}
+
+static void
+signature_manager_class_init (ESignatureManagerClass *class)
+{
+	GObjectClass *object_class;
+
+	parent_class = g_type_class_peek_parent (class);
+	g_type_class_add_private (class, sizeof (ESignatureManagerPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = signature_manager_set_property;
+	object_class->get_property = signature_manager_get_property;
+	object_class->dispose = signature_manager_dispose;
+
+	class->add_signature = signature_manager_add_signature;
+	class->add_signature_script = signature_manager_add_signature_script;
+	class->editor_created = signature_manager_editor_created;
+	class->edit_signature = signature_manager_edit_signature;
+	class->remove_signature = signature_manager_remove_signature;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ALLOW_SCRIPTS,
+		g_param_spec_boolean (
+			"allow-scripts",
+			"Allow Scripts",
+			NULL,
+			TRUE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_PREFER_HTML,
+		g_param_spec_boolean (
+			"prefer-html",
+			"Prefer HTML",
+			NULL,
+			TRUE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SIGNATURE_LIST,
+		g_param_spec_object (
+			"signature-list",
+			"Signature List",
+			NULL,
+			E_TYPE_SIGNATURE_LIST,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT));
+
+	signals[ADD_SIGNATURE] = g_signal_new (
+		"add-signature",
+		G_OBJECT_CLASS_TYPE (class),
+		G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		G_STRUCT_OFFSET (ESignatureManagerClass, add_signature),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+
+	signals[ADD_SIGNATURE_SCRIPT] = g_signal_new (
+		"add-signature-script",
+		G_OBJECT_CLASS_TYPE (class),
+		G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		G_STRUCT_OFFSET (ESignatureManagerClass, add_signature_script),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+
+	signals[EDITOR_CREATED] = g_signal_new (
+		"editor-created",
+		G_OBJECT_CLASS_TYPE (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (ESignatureManagerClass, editor_created),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__OBJECT,
+		G_TYPE_NONE, 1,
+		E_TYPE_SIGNATURE_EDITOR);
+
+	signals[EDIT_SIGNATURE] = g_signal_new (
+		"edit-signature",
+		G_OBJECT_CLASS_TYPE (class),
+		G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		G_STRUCT_OFFSET (ESignatureManagerClass, edit_signature),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+
+	signals[REMOVE_SIGNATURE] = g_signal_new (
+		"remove-signature",
+		G_OBJECT_CLASS_TYPE (class),
+		G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		G_STRUCT_OFFSET (ESignatureManagerClass, remove_signature),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+}
+
+static void
+signature_manager_init (ESignatureManager *manager)
+{
+	GtkTreeSelection *selection;
+	GtkWidget *container;
+	GtkWidget *widget;
+
+	manager->priv = E_SIGNATURE_MANAGER_GET_PRIVATE (manager);
+
+	gtk_table_resize (GTK_TABLE (manager), 1, 2);
+	gtk_table_set_col_spacings (GTK_TABLE (manager), 6);
+	gtk_table_set_row_spacings (GTK_TABLE (manager), 12);
+
+	container = GTK_WIDGET (manager);
+
+	widget = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_policy (
+		GTK_SCROLLED_WINDOW (widget),
+		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_scrolled_window_set_shadow_type (
+		GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
+	gtk_table_attach (
+		GTK_TABLE (container), widget, 0, 1, 0, 1,
+		GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = e_signature_tree_view_new ();
+	gtk_container_add (GTK_CONTAINER (container), widget);
+	manager->priv->tree_view = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	e_mutual_binding_new (
+		G_OBJECT (manager), "signature-list",
+		G_OBJECT (widget), "signature-list");
+
+	g_signal_connect_swapped (
+		widget, "key-press-event",
+		G_CALLBACK (signature_manager_key_press_event_cb),
+		manager);
+
+	g_signal_connect_swapped (
+		widget, "row-activated",
+		G_CALLBACK (e_signature_manager_edit_signature),
+		manager);
+
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+
+	g_signal_connect_swapped (
+		selection, "changed",
+		G_CALLBACK (signature_manager_selection_changed_cb),
+		manager);
+
+	container = GTK_WIDGET (manager);
+
+	widget = gtk_vbutton_box_new ();
+	gtk_button_box_set_layout (
+		GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START);
+	gtk_box_set_spacing (GTK_BOX (widget), 6);
+	gtk_table_attach (
+		GTK_TABLE (container), widget,
+		1, 2, 0, 2, 0, GTK_FILL, 0, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = gtk_button_new_from_stock (GTK_STOCK_ADD);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	manager->priv->add_button = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "clicked",
+		G_CALLBACK (e_signature_manager_add_signature),
+		manager);
+
+	widget = gtk_button_new_with_mnemonic (_("Add _Script"));
+	gtk_button_set_image (
+		GTK_BUTTON (widget), gtk_image_new_from_stock (
+		GTK_STOCK_EXECUTE, GTK_ICON_SIZE_BUTTON));
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	manager->priv->add_script_button = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	e_binding_new (
+		G_OBJECT (manager), "allow-scripts",
+		G_OBJECT (widget), "sensitive");
+
+	g_signal_connect_swapped (
+		widget, "clicked",
+		G_CALLBACK (e_signature_manager_add_signature_script),
+		manager);
+
+	widget = gtk_button_new_from_stock (GTK_STOCK_EDIT);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	manager->priv->edit_button = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "clicked",
+		G_CALLBACK (e_signature_manager_edit_signature),
+		manager);
+
+	widget = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	manager->priv->remove_button = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "clicked",
+		G_CALLBACK (e_signature_manager_remove_signature),
+		manager);
+}
+
+GType
+e_signature_manager_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo type_info = {
+			sizeof (ESignatureManagerClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) signature_manager_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,  /* class_init */
+			sizeof (ESignatureManager),
+			0,     /* n_preallocs */
+			(GInstanceInitFunc) signature_manager_init,
+			NULL   /* value_table */
+		};
+
+		type = g_type_register_static (
+			GTK_TYPE_TABLE, "ESignatureManager", &type_info, 0);
+	}
+
+	return type;
+}
+
+GtkWidget *
+e_signature_manager_new (ESignatureList *signature_list)
+{
+	g_return_val_if_fail (E_IS_SIGNATURE_LIST (signature_list), NULL);
+
+	return g_object_new (
+		E_TYPE_SIGNATURE_MANAGER,
+		"signature-list", signature_list, NULL);
+}
+
+void
+e_signature_manager_add_signature (ESignatureManager *manager)
+{
+	g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager));
+
+	g_signal_emit (manager, signals[ADD_SIGNATURE], 0);
+}
+
+void
+e_signature_manager_add_signature_script (ESignatureManager *manager)
+{
+	g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager));
+
+	g_signal_emit (manager, signals[ADD_SIGNATURE_SCRIPT], 0);
+}
+
+void
+e_signature_manager_edit_signature (ESignatureManager *manager)
+{
+	g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager));
+
+	g_signal_emit (manager, signals[EDIT_SIGNATURE], 0);
+}
+
+void
+e_signature_manager_remove_signature (ESignatureManager *manager)
+{
+	g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager));
+
+	g_signal_emit (manager, signals[REMOVE_SIGNATURE], 0);
+}
+
+gboolean
+e_signature_manager_get_allow_scripts (ESignatureManager *manager)
+{
+	g_return_val_if_fail (E_IS_SIGNATURE_MANAGER (manager), FALSE);
+
+	return manager->priv->allow_scripts;
+}
+
+void
+e_signature_manager_set_allow_scripts (ESignatureManager *manager,
+                                       gboolean allow_scripts)
+{
+	g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager));
+
+	manager->priv->allow_scripts = allow_scripts;
+
+	g_object_notify (G_OBJECT (manager), "allow-scripts");
+}
+
+gboolean
+e_signature_manager_get_prefer_html (ESignatureManager *manager)
+{
+	g_return_val_if_fail (E_IS_SIGNATURE_MANAGER (manager), FALSE);
+
+	return manager->priv->prefer_html;
+}
+
+void
+e_signature_manager_set_prefer_html (ESignatureManager *manager,
+                                     gboolean prefer_html)
+{
+	g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager));
+
+	manager->priv->prefer_html = prefer_html;
+
+	g_object_notify (G_OBJECT (manager), "prefer-html");
+}
+
+ESignatureList *
+e_signature_manager_get_signature_list (ESignatureManager *manager)
+{
+	g_return_val_if_fail (E_IS_SIGNATURE_MANAGER (manager), NULL);
+
+	return manager->priv->signature_list;
+}
+
+void
+e_signature_manager_set_signature_list (ESignatureManager *manager,
+                                        ESignatureList *signature_list)
+{
+	g_return_if_fail (E_IS_SIGNATURE_MANAGER (manager));
+
+	if (signature_list != NULL) {
+		g_return_if_fail (E_IS_SIGNATURE_LIST (signature_list));
+		g_object_ref (signature_list);
+	}
+
+	if (manager->priv->signature_list != NULL)
+		g_object_unref (manager->priv->signature_list);
+
+	manager->priv->signature_list = signature_list;
+
+	g_object_notify (G_OBJECT (manager), "signature-list");
+}
+
+ESignatureTreeView *
+e_signature_manager_get_tree_view (ESignatureManager *manager)
+{
+	g_return_val_if_fail (E_IS_SIGNATURE_MANAGER (manager), NULL);
+
+	return E_SIGNATURE_TREE_VIEW (manager->priv->tree_view);
+}
diff --git a/widgets/misc/e-signature-manager.h b/widgets/misc/e-signature-manager.h
new file mode 100644
index 0000000000..6c182badab
--- /dev/null
+++ b/widgets/misc/e-signature-manager.h
@@ -0,0 +1,100 @@
+/*
+ * e-signature-manager.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   
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_SIGNATURE_MANAGER_H
+#define E_SIGNATURE_MANAGER_H
+
+#include 
+#include 
+#include 
+#include 
+
+/* Standard GObject macros */
+#define E_TYPE_SIGNATURE_MANAGER \
+	(e_signature_manager_get_type ())
+#define E_SIGNATURE_MANAGER(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_SIGNATURE_MANAGER, ESignatureManager))
+#define E_SIGNATURE_MANAGER_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_SIGNATURE_MANAGER, ESignatureManagerClass))
+#define E_IS_SIGNATURE_MANAGER(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_SIGNATURE_MANAGER))
+#define E_IS_SIGNATURE_MANAGER_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_SIGNATURE_MANAGER))
+#define E_SIGNATURE_MANAGER_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_SIGNATURE_MANAGER, ESignatureManagerClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESignatureManager ESignatureManager;
+typedef struct _ESignatureManagerClass ESignatureManagerClass;
+typedef struct _ESignatureManagerPrivate ESignatureManagerPrivate;
+
+struct _ESignatureManager {
+	GtkTable parent;
+	ESignatureManagerPrivate *priv;
+};
+
+struct _ESignatureManagerClass {
+	GtkTableClass parent_class;
+
+	void		(*add_signature)	(ESignatureManager *manager);
+	void		(*add_signature_script)	(ESignatureManager *manager);
+	void		(*editor_created)	(ESignatureManager *manager,
+						 ESignatureEditor *editor);
+	void		(*edit_signature)	(ESignatureManager *manager);
+	void		(*remove_signature)	(ESignatureManager *manager);
+};
+
+GType		e_signature_manager_get_type	(void);
+GtkWidget *	e_signature_manager_new		(ESignatureList *signature_list);
+void		e_signature_manager_add_signature
+						(ESignatureManager *manager);
+void		e_signature_manager_add_signature_script
+						(ESignatureManager *manager);
+void		e_signature_manager_edit_signature
+						(ESignatureManager *manager);
+void		e_signature_manager_remove_signature
+						(ESignatureManager *manager);
+gboolean	e_signature_manager_get_allow_scripts
+						(ESignatureManager *manager);
+void		e_signature_manager_set_allow_scripts
+						(ESignatureManager *manager,
+						 gboolean allow_scripts);
+gboolean	e_signature_manager_get_prefer_html
+						(ESignatureManager *manager);
+void		e_signature_manager_set_prefer_html
+						(ESignatureManager *manager,
+						 gboolean prefer_html);
+ESignatureList *e_signature_manager_get_signature_list
+						(ESignatureManager *manager);
+void		e_signature_manager_set_signature_list
+						(ESignatureManager *manager,
+						 ESignatureList *signature_list);
+ESignatureTreeView *
+		e_signature_manager_get_tree_view
+						(ESignatureManager *manager);
+
+#endif /* E_SIGNATURE_MANAGER_H */
diff --git a/widgets/misc/e-signature-script-dialog.c b/widgets/misc/e-signature-script-dialog.c
new file mode 100644
index 0000000000..06e021b046
--- /dev/null
+++ b/widgets/misc/e-signature-script-dialog.c
@@ -0,0 +1,463 @@
+/*
+ * e-signature-script-dialog.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   
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-signature-script-dialog.h"
+
+#include 
+#include "e-util/e-binding.h"
+
+#define E_SIGNATURE_SCRIPT_DIALOG_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_SIGNATURE_SCRIPT_DIALOG, ESignatureScriptDialogPrivate))
+
+struct _ESignatureScriptDialogPrivate {
+	GtkWidget *entry;
+	GtkWidget *file_chooser;
+	GtkWidget *alert;
+};
+
+enum {
+	PROP_0,
+	PROP_SCRIPT_FILE,
+	PROP_SCRIPT_NAME
+};
+
+static gpointer parent_class;
+
+static gboolean
+signature_script_dialog_filter_cb (const GtkFileFilterInfo *filter_info)
+{
+	const gchar *filename = filter_info->filename;
+
+	return g_file_test (filename, G_FILE_TEST_IS_EXECUTABLE);
+}
+
+static void
+signature_script_dialog_update_status (ESignatureScriptDialog *dialog)
+{
+	GFile *script_file;
+	const gchar *script_name;
+	gboolean show_alert;
+	gboolean sensitive;
+
+	script_file = e_signature_script_dialog_get_script_file (dialog);
+	script_name = e_signature_script_dialog_get_script_name (dialog);
+
+	sensitive = (script_name != NULL && *script_name != '\0');
+
+	if (script_file != NULL) {
+		gboolean executable;
+		gchar *filename;
+
+		filename = g_file_get_path (script_file);
+		executable = g_file_test (filename, G_FILE_TEST_IS_EXECUTABLE);
+		g_free (filename);
+
+		show_alert = !executable;
+		sensitive &= executable;
+
+		g_object_unref (script_file);
+	} else {
+		sensitive = FALSE;
+		show_alert = FALSE;
+	}
+
+	if (show_alert)
+		gtk_widget_show (dialog->priv->alert);
+	else
+		gtk_widget_hide (dialog->priv->alert);
+
+	gtk_dialog_set_response_sensitive (
+		GTK_DIALOG (dialog), GTK_RESPONSE_OK, sensitive);
+}
+
+static void
+signature_script_dialog_set_property (GObject *object,
+                                      guint property_id,
+                                      const GValue *value,
+                                      GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_SCRIPT_FILE:
+			e_signature_script_dialog_set_script_file (
+				E_SIGNATURE_SCRIPT_DIALOG (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_SCRIPT_NAME:
+			e_signature_script_dialog_set_script_name (
+				E_SIGNATURE_SCRIPT_DIALOG (object),
+				g_value_get_string (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_script_dialog_get_property (GObject *object,
+                                      guint property_id,
+                                      GValue *value,
+                                      GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_SCRIPT_FILE:
+			g_value_set_object (
+				value,
+				e_signature_script_dialog_get_script_file (
+				E_SIGNATURE_SCRIPT_DIALOG (object)));
+			return;
+
+		case PROP_SCRIPT_NAME:
+			g_value_set_string (
+				value,
+				e_signature_script_dialog_get_script_name (
+				E_SIGNATURE_SCRIPT_DIALOG (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_script_dialog_dispose (GObject *object)
+{
+	ESignatureScriptDialogPrivate *priv;
+
+	priv = E_SIGNATURE_SCRIPT_DIALOG_GET_PRIVATE (object);
+
+	if (priv->entry != NULL) {
+		g_object_unref (priv->entry);
+		priv->entry = NULL;
+	}
+
+	if (priv->file_chooser != NULL) {
+		g_object_unref (priv->file_chooser);
+		priv->file_chooser = NULL;
+	}
+
+	if (priv->alert != NULL) {
+		g_object_unref (priv->alert);
+		priv->alert = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+signature_script_dialog_map (GtkWidget *widget)
+{
+	GtkWidget *action_area;
+	GtkWidget *content_area;
+
+	/* Chain up to parent's map() method. */
+	GTK_WIDGET_CLASS (parent_class)->map (widget);
+
+	/* XXX Override GtkDialog's broken style property defaults. */
+	action_area = gtk_dialog_get_action_area (GTK_DIALOG (widget));
+	content_area = gtk_dialog_get_content_area (GTK_DIALOG (widget));
+
+	gtk_box_set_spacing (GTK_BOX (content_area), 12);
+	gtk_container_set_border_width (GTK_CONTAINER (action_area), 0);
+	gtk_container_set_border_width (GTK_CONTAINER (content_area), 12);
+}
+
+static void
+signature_script_dialog_class_init (ESignatureScriptDialogClass *class)
+{
+	GObjectClass *object_class;
+	GtkWidgetClass *widget_class;
+
+	parent_class = g_type_class_peek_parent (class);
+	g_type_class_add_private (class, sizeof (ESignatureScriptDialogPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = signature_script_dialog_set_property;
+	object_class->get_property = signature_script_dialog_get_property;
+	object_class->dispose = signature_script_dialog_dispose;
+
+	widget_class = GTK_WIDGET_CLASS (class);
+	widget_class->map = signature_script_dialog_map;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SCRIPT_FILE,
+		g_param_spec_object (
+			"script-file",
+			"Script File",
+			NULL,
+			G_TYPE_FILE,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SCRIPT_NAME,
+		g_param_spec_string (
+			"script-name",
+			"Script Name",
+			NULL,
+			_("Unnamed"),
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT));
+}
+
+static void
+signature_script_dialog_init (ESignatureScriptDialog *dialog)
+{
+	GtkFileFilter *filter;
+	GtkWidget *content_area;
+	GtkWidget *container;
+	GtkWidget *widget;
+	gchar *markup;
+
+	dialog->priv = E_SIGNATURE_SCRIPT_DIALOG_GET_PRIVATE (dialog);
+
+	content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+	gtk_dialog_add_button (
+		GTK_DIALOG (dialog),
+		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+
+	gtk_dialog_add_button (
+		GTK_DIALOG (dialog),
+		GTK_STOCK_SAVE, GTK_RESPONSE_OK);
+
+	gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+	container = content_area;
+
+	widget = gtk_table_new (4, 2, FALSE);
+	gtk_table_set_col_spacings (GTK_TABLE (widget), 6);
+	gtk_table_set_row_spacings (GTK_TABLE (widget), 6);
+	gtk_table_set_row_spacing (GTK_TABLE (widget), 0, 12);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = gtk_image_new_from_stock (
+		GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG);
+	gtk_table_attach (
+		GTK_TABLE (container), widget,
+		0, 1, 0, 1, 0, 0, 0, 0);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (_(
+		"The output of this script will be used as your\n"
+		"signature. The name you specify will be used\n"
+		"for display purposes only."));
+	gtk_table_attach (
+		GTK_TABLE (container), widget,
+		1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
+	gtk_widget_show (widget);
+
+	widget = gtk_entry_new ();
+	gtk_entry_set_activates_default (GTK_ENTRY (widget), TRUE);
+	gtk_table_attach (
+		GTK_TABLE (container), widget,
+		1, 2, 1, 2, GTK_FILL | GTK_EXPAND, 0, 0, 0);
+	dialog->priv->entry = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new_with_mnemonic (_("_Name:"));
+	gtk_label_set_mnemonic_widget (
+		GTK_LABEL (widget), dialog->priv->entry);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_table_attach (
+		GTK_TABLE (container), widget,
+		0, 1, 1, 2, GTK_FILL, 0, 0, 0);
+	gtk_widget_show (widget);
+
+	widget = gtk_file_chooser_button_new (
+		NULL, GTK_FILE_CHOOSER_ACTION_OPEN);
+	gtk_table_attach (
+		GTK_TABLE (container), widget,
+		1, 2, 2, 3, GTK_FILL | GTK_EXPAND, 0, 0, 0);
+	dialog->priv->file_chooser = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	/* Restrict file selection to executable files. */
+	filter = gtk_file_filter_new ();
+	gtk_file_filter_add_custom (
+		filter, GTK_FILE_FILTER_FILENAME,
+		(GtkFileFilterFunc) signature_script_dialog_filter_cb,
+		NULL, NULL);
+	gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (widget), filter);
+
+	/* XXX ESignature stores a filename instead of a URI,
+	 *     so we have to restrict it to local files only. */
+	gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
+
+	widget = gtk_label_new_with_mnemonic (_("S_cript:"));
+	gtk_label_set_mnemonic_widget (
+		GTK_LABEL (widget), dialog->priv->file_chooser);
+	gtk_table_attach (
+		GTK_TABLE (container), widget,
+		0, 1, 2, 3, GTK_FILL, 0, 0, 0);
+	gtk_widget_show (widget);
+
+	/* This is just a placeholder. */
+	widget = gtk_label_new (NULL);
+	gtk_table_attach (
+		GTK_TABLE (container), widget,
+		0, 1, 3, 4, GTK_FILL, 0, 0, 0);
+	gtk_widget_show (widget);
+
+	widget = gtk_hbox_new (FALSE, 6);
+	gtk_table_attach (
+		GTK_TABLE (container), widget,
+		1, 2, 3, 4, 0, 0, 0, 0);
+	dialog->priv->alert = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = gtk_image_new_from_stock (
+		GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	markup = g_markup_printf_escaped (
+		"%s",
+		_("Script file must be executable."));
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	gtk_widget_show (widget);
+	g_free (markup);
+
+	g_signal_connect (
+		dialog, "notify::script-file",
+		G_CALLBACK (signature_script_dialog_update_status), NULL);
+
+	g_signal_connect (
+		dialog, "notify::script-name",
+		G_CALLBACK (signature_script_dialog_update_status), NULL);
+
+	g_signal_connect_swapped (
+		dialog->priv->entry, "changed",
+		G_CALLBACK (signature_script_dialog_update_status), dialog);
+
+	g_signal_connect_swapped (
+		dialog->priv->file_chooser, "file-set",
+		G_CALLBACK (signature_script_dialog_update_status), dialog);
+
+	signature_script_dialog_update_status (dialog);
+}
+
+GType
+e_signature_script_dialog_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo type_info = {
+			sizeof (ESignatureScriptDialogClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) signature_script_dialog_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,  /* class_data */
+			sizeof (ESignatureScriptDialog),
+			0,     /* n_preallocs */
+			(GInstanceInitFunc) signature_script_dialog_init,
+			NULL   /* value_table */
+		};
+
+		type = g_type_register_static (
+			GTK_TYPE_DIALOG, "ESignatureScriptDialog",
+			&type_info, 0);
+	}
+
+	return type;
+}
+
+GtkWidget *
+e_signature_script_dialog_new (GtkWindow *parent)
+{
+	return g_object_new (
+		E_TYPE_SIGNATURE_SCRIPT_DIALOG,
+		"transient-for", parent, NULL);
+}
+
+GFile *
+e_signature_script_dialog_get_script_file (ESignatureScriptDialog *dialog)
+{
+	GtkFileChooser *file_chooser;
+
+	g_return_val_if_fail (E_IS_SIGNATURE_SCRIPT_DIALOG (dialog), NULL);
+
+	file_chooser = GTK_FILE_CHOOSER (dialog->priv->file_chooser);
+
+	return gtk_file_chooser_get_file (file_chooser);
+}
+
+void
+e_signature_script_dialog_set_script_file (ESignatureScriptDialog *dialog,
+                                           GFile *script_file)
+{
+	GtkFileChooser *file_chooser;
+	GError *error = NULL;
+
+	g_return_if_fail (E_IS_SIGNATURE_SCRIPT_DIALOG (dialog));
+	g_return_if_fail (G_IS_FILE (script_file));
+
+	file_chooser = GTK_FILE_CHOOSER (dialog->priv->file_chooser);
+
+	if (gtk_file_chooser_set_file (file_chooser, script_file, &error))
+		g_object_notify (G_OBJECT (dialog), "script-file");
+	else {
+		g_warning ("%s", error->message);
+		g_error_free (error);
+	}
+}
+
+const gchar *
+e_signature_script_dialog_get_script_name (ESignatureScriptDialog *dialog)
+{
+	GtkEntry *entry;
+
+	g_return_val_if_fail (E_IS_SIGNATURE_SCRIPT_DIALOG (dialog), NULL);
+
+	entry = GTK_ENTRY (dialog->priv->entry);
+
+	return gtk_entry_get_text (entry);
+}
+
+void
+e_signature_script_dialog_set_script_name (ESignatureScriptDialog *dialog,
+                                           const gchar *script_name)
+{
+	GtkEntry *entry;
+
+	g_return_if_fail (E_IS_SIGNATURE_SCRIPT_DIALOG (dialog));
+
+	if (script_name == NULL)
+		script_name = "";
+
+	entry = GTK_ENTRY (dialog->priv->entry);
+	gtk_entry_set_text (entry, script_name);
+
+	g_object_notify (G_OBJECT (dialog), "script-name");
+}
diff --git a/widgets/misc/e-signature-script-dialog.h b/widgets/misc/e-signature-script-dialog.h
new file mode 100644
index 0000000000..4cd7f05632
--- /dev/null
+++ b/widgets/misc/e-signature-script-dialog.h
@@ -0,0 +1,76 @@
+/*
+ * e-signature-script-dialog.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   
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_SIGNATURE_SCRIPT_DIALOG_H
+#define E_SIGNATURE_SCRIPT_DIALOG_H
+
+#include 
+
+/* Standard GObject macros */
+#define E_TYPE_SIGNATURE_SCRIPT_DIALOG \
+	(e_signature_script_dialog_get_type ())
+#define E_SIGNATURE_SCRIPT_DIALOG(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_SIGNATURE_SCRIPT_DIALOG, ESignatureScriptDialog))
+#define E_SIGNATURE_SCRIPT_DIALOG_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_SIGNATURE_SCRIPT_DIALOG, ESignatureScriptDialogClass))
+#define E_IS_SIGNATURE_SCRIPT_DIALOG(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_SIGNATURE_SCRIPT_DIALOG))
+#define E_IS_SIGNATURE_SCRIPT_DIALOG_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_SIGNATURE_SCRIPT_DIALOG))
+#define E_SIGNATURE_SCRIPT_DIALOG_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_SIGNATURE_SCRIPT_DIALOG, ESignatureScriptDialogClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESignatureScriptDialog ESignatureScriptDialog;
+typedef struct _ESignatureScriptDialogClass ESignatureScriptDialogClass;
+typedef struct _ESignatureScriptDialogPrivate ESignatureScriptDialogPrivate;
+
+struct _ESignatureScriptDialog {
+	GtkDialog parent;
+	ESignatureScriptDialogPrivate *priv;
+};
+
+struct _ESignatureScriptDialogClass {
+	GtkDialogClass parent_class;
+};
+
+GType		e_signature_script_dialog_get_type	(void);
+GtkWidget *	e_signature_script_dialog_new		(GtkWindow *parent);
+GFile *		e_signature_script_dialog_get_script_file
+					(ESignatureScriptDialog *dialog);
+void		e_signature_script_dialog_set_script_file
+					(ESignatureScriptDialog *dialog,
+					 GFile *script_file);
+const gchar *	e_signature_script_dialog_get_script_name
+					(ESignatureScriptDialog *dialog);
+void		e_signature_script_dialog_set_script_name
+					(ESignatureScriptDialog *dialog,
+					 const gchar *script_name);
+
+G_END_DECLS
+
+#endif /* E_SIGNATURE_SCRIPT_DIALOG_H */
diff --git a/widgets/misc/e-signature-tree-view.c b/widgets/misc/e-signature-tree-view.c
new file mode 100644
index 0000000000..ef1cc36b14
--- /dev/null
+++ b/widgets/misc/e-signature-tree-view.c
@@ -0,0 +1,405 @@
+/*
+ * e-signature-tree-view.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   
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-signature-tree-view.h"
+
+#define E_SIGNATURE_TREE_VIEW_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_SIGNATURE_TREE_VIEW, ESignatureTreeViewPrivate))
+
+enum {
+	COLUMN_STRING,
+	COLUMN_SIGNATURE
+};
+
+enum {
+	PROP_0,
+	PROP_SIGNATURE_LIST
+};
+
+enum {
+	REFRESHED,
+	LAST_SIGNAL
+};
+
+struct _ESignatureTreeViewPrivate {
+	ESignatureList *signature_list;
+	GHashTable *index;
+};
+
+static gpointer parent_class;
+static guint signal_ids[LAST_SIGNAL];
+
+static void
+signature_tree_view_refresh_cb (ESignatureList *signature_list,
+                                ESignature *unused,
+                                ESignatureTreeView *tree_view)
+{
+	GtkListStore *store;
+	GtkTreeModel *model;
+	GtkTreeIter tree_iter;
+	EIterator *signature_iter;
+	ESignature *signature;
+	GHashTable *index;
+	GList *list = NULL;
+	GList *iter;
+
+	store = gtk_list_store_new (2, G_TYPE_STRING, E_TYPE_SIGNATURE);
+	model = GTK_TREE_MODEL (store);
+	index = tree_view->priv->index;
+
+	g_hash_table_remove_all (index);
+
+	if (signature_list == NULL)
+		goto skip;
+
+	/* Build a list of ESignatures to display. */
+	signature_iter = e_list_get_iterator (E_LIST (signature_list));
+	while (e_iterator_is_valid (signature_iter)) {
+
+		/* XXX EIterator misuses const. */
+		signature = (ESignature *) e_iterator_get (signature_iter);
+		list = g_list_prepend (list, signature);
+		e_iterator_next (signature_iter);
+	}
+	g_object_unref (signature_iter);
+
+	list = g_list_reverse (list);
+
+	/* Populate the list store and index. */
+	for (iter = list; iter != NULL; iter = iter->next) {
+		GtkTreeRowReference *reference;
+		GtkTreePath *path;
+
+		signature = iter->data;
+
+		/* Skip autogenerated signatures. */
+		if (signature->autogen)
+			continue;
+
+		gtk_list_store_append (store, &tree_iter);
+		gtk_list_store_set (
+			store, &tree_iter,
+			COLUMN_STRING, signature->name,
+			COLUMN_SIGNATURE, signature, -1);
+
+		path = gtk_tree_model_get_path (model, &tree_iter);
+		reference = gtk_tree_row_reference_new (model, path);
+		g_hash_table_insert (index, signature, reference);
+		gtk_tree_path_free (path);
+	}
+
+skip:
+	/* Restore the previously selected signature. */
+	signature = e_signature_tree_view_get_selected (tree_view);
+	if (signature != NULL)
+		g_object_ref (signature);
+	gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), model);
+	e_signature_tree_view_set_selected (tree_view, signature);
+	if (signature != NULL)
+		g_object_unref (signature);
+
+	g_signal_emit (tree_view, signal_ids[REFRESHED], 0);
+}
+
+static GObject *
+signature_tree_view_constructor (GType type,
+                                 guint n_construct_properties,
+                                 GObjectConstructParam *construct_properties)
+{
+	GObject *object;
+	GtkTreeView *tree_view;
+	GtkTreeViewColumn *column;
+	GtkCellRenderer *renderer;
+
+	/* Chain up to parent's constructor() method. */
+	object = G_OBJECT_CLASS (parent_class)->constructor (
+		type, n_construct_properties, construct_properties);
+
+	tree_view = GTK_TREE_VIEW (object);
+	gtk_tree_view_set_headers_visible (tree_view, FALSE);
+
+	column = gtk_tree_view_column_new ();
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_pack_start (column, renderer, TRUE);
+	gtk_tree_view_column_add_attribute (
+		column, renderer, "text", COLUMN_STRING);
+	gtk_tree_view_append_column (tree_view, column);
+
+	return object;
+}
+
+static void
+signature_tree_view_set_property (GObject *object,
+                                  guint property_id,
+                                  const GValue *value,
+                                  GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_SIGNATURE_LIST:
+			e_signature_tree_view_set_signature_list (
+				E_SIGNATURE_TREE_VIEW (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_tree_view_get_property (GObject *object,
+                                  guint property_id,
+                                  GValue *value,
+                                  GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_SIGNATURE_LIST:
+			g_value_set_object (
+				value,
+				e_signature_tree_view_get_signature_list (
+				E_SIGNATURE_TREE_VIEW (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+signature_tree_view_dispose (GObject *object)
+{
+	ESignatureTreeViewPrivate *priv;
+
+	priv = E_SIGNATURE_TREE_VIEW_GET_PRIVATE (object);
+
+	if (priv->signature_list != NULL) {
+		g_signal_handlers_disconnect_by_func (
+			priv->signature_list,
+			signature_tree_view_refresh_cb, object);
+		g_object_unref (priv->signature_list);
+		priv->signature_list = NULL;
+	}
+
+	g_hash_table_remove_all (priv->index);
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+signature_tree_view_finalize (GObject *object)
+{
+	ESignatureTreeViewPrivate *priv;
+
+	priv = E_SIGNATURE_TREE_VIEW_GET_PRIVATE (object);
+
+	g_hash_table_destroy (priv->index);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+signature_tree_view_class_init (ESignatureTreeViewClass *class)
+{
+	GObjectClass *object_class;
+
+	parent_class = g_type_class_peek_parent (class);
+	g_type_class_add_private (class, sizeof (ESignatureTreeViewPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->constructor = signature_tree_view_constructor;
+	object_class->set_property = signature_tree_view_set_property;
+	object_class->get_property = signature_tree_view_get_property;
+	object_class->dispose = signature_tree_view_dispose;
+	object_class->finalize = signature_tree_view_finalize;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SIGNATURE_LIST,
+		g_param_spec_object (
+			"signature-list",
+			"Signature List",
+			NULL,
+			E_TYPE_SIGNATURE_LIST,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT));
+
+	signal_ids[REFRESHED] = g_signal_new (
+		"refreshed",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		0, NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+}
+
+static void
+signature_tree_view_init (ESignatureTreeView *tree_view)
+{
+	GHashTable *index;
+
+	/* Reverse-lookup index */
+	index = g_hash_table_new_full (
+		g_direct_hash, g_direct_equal,
+		(GDestroyNotify) g_object_unref,
+		(GDestroyNotify) gtk_tree_row_reference_free);
+
+	tree_view->priv = E_SIGNATURE_TREE_VIEW_GET_PRIVATE (tree_view);
+	tree_view->priv->index = index;
+}
+
+GType
+e_signature_tree_view_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo type_info = {
+			sizeof (ESignatureTreeViewClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) signature_tree_view_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,  /* class_data */
+			sizeof (ESignatureTreeView),
+			0,     /* n_preallocs */
+			(GInstanceInitFunc) signature_tree_view_init,
+			NULL  /* value_table */
+		};
+
+		type = g_type_register_static (
+			GTK_TYPE_TREE_VIEW, "ESignatureTreeView",
+			&type_info, 0);
+	}
+
+	return type;
+}
+
+GtkWidget *
+e_signature_tree_view_new (void)
+{
+	return g_object_new (E_TYPE_SIGNATURE_TREE_VIEW, NULL);
+}
+
+ESignatureList *
+e_signature_tree_view_get_signature_list (ESignatureTreeView *tree_view)
+{
+	g_return_val_if_fail (E_IS_SIGNATURE_TREE_VIEW (tree_view), NULL);
+
+	return tree_view->priv->signature_list;
+}
+
+void
+e_signature_tree_view_set_signature_list (ESignatureTreeView *tree_view,
+                                          ESignatureList *signature_list)
+{
+	ESignatureTreeViewPrivate *priv;
+
+	g_return_if_fail (E_IS_SIGNATURE_TREE_VIEW (tree_view));
+
+	if (signature_list != NULL)
+		g_return_if_fail (E_IS_SIGNATURE_LIST (signature_list));
+
+	priv = E_SIGNATURE_TREE_VIEW_GET_PRIVATE (tree_view);
+
+	if (priv->signature_list != NULL) {
+		g_signal_handlers_disconnect_by_func (
+			priv->signature_list,
+			signature_tree_view_refresh_cb, tree_view);
+		g_object_unref (priv->signature_list);
+		priv->signature_list = NULL;
+	}
+
+	if (signature_list != NULL) {
+		priv->signature_list = g_object_ref (signature_list);
+
+		/* Listen for changes to the signature list. */
+		g_signal_connect (
+			priv->signature_list, "signature-added",
+			G_CALLBACK (signature_tree_view_refresh_cb),
+			tree_view);
+		g_signal_connect (
+			priv->signature_list, "signature-changed",
+			G_CALLBACK (signature_tree_view_refresh_cb),
+			tree_view);
+		g_signal_connect (
+			priv->signature_list, "signature-removed",
+			G_CALLBACK (signature_tree_view_refresh_cb),
+			tree_view);
+	}
+
+	signature_tree_view_refresh_cb (signature_list, NULL, tree_view);
+
+	g_object_notify (G_OBJECT (tree_view), "signature-list");
+}
+
+ESignature *
+e_signature_tree_view_get_selected (ESignatureTreeView *tree_view)
+{
+	ESignature *signature;
+	GtkTreeSelection *selection;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+
+	g_return_val_if_fail (E_IS_SIGNATURE_TREE_VIEW (tree_view), NULL);
+
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+		return NULL;
+
+	gtk_tree_model_get (model, &iter, COLUMN_SIGNATURE, &signature, -1);
+
+	return signature;
+}
+
+gboolean
+e_signature_tree_view_set_selected (ESignatureTreeView *tree_view,
+                                    ESignature *signature)
+{
+	GtkTreeRowReference *reference;
+	GtkTreeSelection *selection;
+	GtkTreePath *path;
+
+	g_return_val_if_fail (E_IS_SIGNATURE_TREE_VIEW (tree_view), FALSE);
+
+	if (signature != NULL)
+		g_return_val_if_fail (E_IS_SIGNATURE (signature), FALSE);
+
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+
+	/* NULL means clear the selection. */
+	if (signature == NULL) {
+		gtk_tree_selection_unselect_all (selection);
+		return TRUE;
+	}
+
+	/* Lookup the tree row reference for the signature. */
+	reference = g_hash_table_lookup (tree_view->priv->index, signature);
+	if (reference == NULL)
+		return FALSE;
+
+	/* Select the referenced path. */
+	path = gtk_tree_row_reference_get_path (reference);
+	gtk_tree_selection_select_path (selection, path);
+	gtk_tree_path_free (path);
+
+	return TRUE;
+}
diff --git a/widgets/misc/e-signature-tree-view.h b/widgets/misc/e-signature-tree-view.h
new file mode 100644
index 0000000000..3afe569136
--- /dev/null
+++ b/widgets/misc/e-signature-tree-view.h
@@ -0,0 +1,78 @@
+/*
+ * e-signature-tree-view.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   
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_SIGNATURE_TREE_VIEW_H
+#define E_SIGNATURE_TREE_VIEW_H
+
+#include 
+#include 
+#include 
+
+/* Standard GObject macros */
+#define E_TYPE_SIGNATURE_TREE_VIEW \
+	(e_signature_tree_view_get_type ())
+#define E_SIGNATURE_TREE_VIEW(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_SIGNATURE_TREE_VIEW, ESignatureTreeView))
+#define E_SIGNATURE_TREE_VIEW_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_SIGNATURE_TREE_VIEW, ESignatureTreeViewClass))
+#define E_IS_SIGNATURE_TREE_VIEW(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_SIGNATURE_TREE_VIEW))
+#define E_IS_SIGNATURE_TREE_VIEW_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_SIGNATURE_TREE_VIEW))
+#define E_SIGNATURE_TREE_VIEW_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_SIGNATURE_TREE_VIEW, ESignatureTreeViewClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESignatureTreeView ESignatureTreeView;
+typedef struct _ESignatureTreeViewClass ESignatureTreeViewClass;
+typedef struct _ESignatureTreeViewPrivate ESignatureTreeViewPrivate;
+
+struct _ESignatureTreeView {
+	GtkTreeView parent;
+	ESignatureTreeViewPrivate *priv;
+};
+
+struct _ESignatureTreeViewClass {
+	GtkTreeViewClass parent_class;
+};
+
+GType		e_signature_tree_view_get_type	(void);
+GtkWidget *	e_signature_tree_view_new	(void);
+ESignatureList *e_signature_tree_view_get_signature_list
+					(ESignatureTreeView *tree_view);
+void		e_signature_tree_view_set_signature_list
+					(ESignatureTreeView *tree_view,
+					 ESignatureList *signature_list);
+ESignature *	e_signature_tree_view_get_selected
+					(ESignatureTreeView *tree_view);
+gboolean	e_signature_tree_view_set_selected
+					(ESignatureTreeView *tree_view,
+					 ESignature *signature);
+
+G_END_DECLS
+
+#endif /* E_SIGNATURE_TREE_VIEW_H */
-- 
cgit v1.2.3