aboutsummaryrefslogblamecommitdiffstats
path: root/e-util/e-mail-signature-manager.c
blob: b32e9ddd604a49bf6caf5921b38c293d7ea593bd (plain) (tree)























                                                                             
                                          


























































































































































































































































                                                                               
                                                             







































                                                                         
                                                               










































































                                                                           


                                                              

                                                                     






































































































































































































































































































                                                                               
                                                      

                       











                                                                           
/*
 * e-mail-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 <http://www.gnu.org/licenses/>
 *
 */

#include "e-mail-signature-manager.h"

#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <gdk/gdkkeysyms.h>

#include <libedataserver/libedataserver.h>

#include "e-mail-signature-preview.h"
#include "e-mail-signature-tree-view.h"
#include "e-mail-signature-script-dialog.h"

#define E_MAIL_SIGNATURE_MANAGER_GET_PRIVATE(obj) \
    (G_TYPE_INSTANCE_GET_PRIVATE \
    ((obj), E_TYPE_MAIL_SIGNATURE_MANAGER, EMailSignatureManagerPrivate))

#define PREVIEW_HEIGHT 200

struct _EMailSignatureManagerPrivate {
    ESourceRegistry *registry;

    GtkWidget *tree_view;       /* not referenced */
    GtkWidget *add_button;      /* not referenced */
    GtkWidget *add_script_button;   /* not referenced */
    GtkWidget *edit_button;     /* not referenced */
    GtkWidget *remove_button;   /* not referenced */
    GtkWidget *preview;     /* not referenced */

    gboolean prefer_html;
};

enum {
    PROP_0,
    PROP_PREFER_HTML,
    PROP_REGISTRY
};

enum {
    ADD_SIGNATURE,
    ADD_SIGNATURE_SCRIPT,
    EDITOR_CREATED,
    EDIT_SIGNATURE,
    REMOVE_SIGNATURE,
    LAST_SIGNAL
};

static guint signals[LAST_SIGNAL];

G_DEFINE_TYPE (
    EMailSignatureManager,
    e_mail_signature_manager,
    GTK_TYPE_PANED)

static void
mail_signature_manager_emit_editor_created (EMailSignatureManager *manager,
                                            GtkWidget *editor)
{
    g_return_if_fail (E_IS_MAIL_SIGNATURE_EDITOR (editor));

    g_signal_emit (manager, signals[EDITOR_CREATED], 0, editor);
}

static gboolean
mail_signature_manager_key_press_event_cb (EMailSignatureManager *manager,
                                           GdkEventKey *event)
{
    if (event->keyval == GDK_KEY_Delete) {
        e_mail_signature_manager_remove_signature (manager);
        return TRUE;
    }

    return FALSE;
}

static void
mail_signature_manager_run_script_dialog (EMailSignatureManager *manager,
                                          ESource *source,
                                          const gchar *title)
{
    ESourceRegistry *registry;
    GtkWidget *dialog;
    gpointer parent;

    registry = e_mail_signature_manager_get_registry (manager);

    parent = gtk_widget_get_toplevel (GTK_WIDGET (manager));
    parent = gtk_widget_is_toplevel (parent) ? parent : NULL;

    dialog = e_mail_signature_script_dialog_new (registry, parent, source);
    gtk_window_set_title (GTK_WINDOW (dialog), title);

    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
        EAsyncClosure *closure;
        GAsyncResult *result;
        GError *error = NULL;

        closure = e_async_closure_new ();

        /* FIXME Make this cancellable. */
        e_mail_signature_script_dialog_commit (
            E_MAIL_SIGNATURE_SCRIPT_DIALOG (dialog), NULL,
            e_async_closure_callback, closure);

        result = e_async_closure_wait (closure);

        e_mail_signature_script_dialog_commit_finish (
            E_MAIL_SIGNATURE_SCRIPT_DIALOG (dialog),
            result, &error);

        e_async_closure_free (closure);

        /* FIXME Make this into an EAlert. */
        if (error != NULL) {
            g_warning ("%s: %s", G_STRFUNC, error->message);
            g_error_free (error);
        }
    }

    gtk_widget_destroy (dialog);
}

static void
mail_signature_manager_selection_changed_cb (EMailSignatureManager *manager,
                                             GtkTreeSelection *selection)
{
    EMailSignaturePreview *preview;
    EMailSignatureTreeView *tree_view;
    ESource *source;
    GtkWidget *edit_button;
    GtkWidget *remove_button;
    gboolean sensitive;
    const gchar *uid = NULL;

    edit_button = manager->priv->edit_button;
    remove_button = manager->priv->remove_button;

    tree_view = E_MAIL_SIGNATURE_TREE_VIEW (manager->priv->tree_view);
    source = e_mail_signature_tree_view_ref_selected_source (tree_view);

    if (source != NULL)
        uid = e_source_get_uid (source);

    preview = E_MAIL_SIGNATURE_PREVIEW (manager->priv->preview);
    e_mail_signature_preview_set_source_uid (preview, uid);

    sensitive = (source != NULL);
    gtk_widget_set_sensitive (edit_button, sensitive);
    gtk_widget_set_sensitive (remove_button, sensitive);

    if (source != NULL)
        g_object_unref (source);
}

static void
mail_signature_manager_set_registry (EMailSignatureManager *manager,
                                     ESourceRegistry *registry)
{
    g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
    g_return_if_fail (manager->priv->registry == NULL);

    manager->priv->registry = g_object_ref (registry);
}

static void
mail_signature_manager_set_property (GObject *object,
                                guint property_id,
                                const GValue *value,
                                GParamSpec *pspec)
{
    switch (property_id) {
        case PROP_PREFER_HTML:
            e_mail_signature_manager_set_prefer_html (
                E_MAIL_SIGNATURE_MANAGER (object),
                g_value_get_boolean (value));
            return;

        case PROP_REGISTRY:
            mail_signature_manager_set_registry (
                E_MAIL_SIGNATURE_MANAGER (object),
                g_value_get_object (value));
            return;
    }

    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}

static void
mail_signature_manager_get_property (GObject *object,
                                guint property_id,
                                GValue *value,
                                GParamSpec *pspec)
{
    switch (property_id) {
        case PROP_PREFER_HTML:
            g_value_set_boolean (
                value,
                e_mail_signature_manager_get_prefer_html (
                E_MAIL_SIGNATURE_MANAGER (object)));
            return;

        case PROP_REGISTRY:
            g_value_set_object (
                value,
                e_mail_signature_manager_get_registry (
                E_MAIL_SIGNATURE_MANAGER (object)));
            return;
    }

    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}

static void
mail_signature_manager_dispose (GObject *object)
{
    EMailSignatureManagerPrivate *priv;

    priv = E_MAIL_SIGNATURE_MANAGER_GET_PRIVATE (object);

    if (priv->registry != NULL) {
        g_object_unref (priv->registry);
        priv->registry = NULL;
    }

    /* Chain up to parent's dispose() method. */
    G_OBJECT_CLASS (e_mail_signature_manager_parent_class)->
        dispose (object);
}

static void
mail_signature_manager_constructed (GObject *object)
{
    EMailSignatureManager *manager;
    GtkTreeSelection *selection;
    ESourceRegistry *registry;
    GSettings *settings;
    GtkWidget *container;
    GtkWidget *widget;
    GtkWidget *hbox;

    /* Chain up to parent's constructed() method. */
    G_OBJECT_CLASS (e_mail_signature_manager_parent_class)->
        constructed (object);

    manager = E_MAIL_SIGNATURE_MANAGER (object);
    registry = e_mail_signature_manager_get_registry (manager);

    gtk_orientable_set_orientation (
        GTK_ORIENTABLE (manager), GTK_ORIENTATION_VERTICAL);

    container = GTK_WIDGET (manager);

    widget = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
    gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 12, 0, 0);
    gtk_paned_pack1 (GTK_PANED (container), widget, TRUE, FALSE);
    gtk_widget_show (widget);

    container = widget;

    widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
    gtk_container_add (GTK_CONTAINER (container), widget);
    gtk_widget_show (widget);

    container = hbox = widget;

    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_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
    gtk_widget_show (widget);

    container = widget;

    widget = e_mail_signature_tree_view_new (registry);
    gtk_container_add (GTK_CONTAINER (container), widget);
    manager->priv->tree_view = widget;  /* not referenced */
    gtk_widget_show (widget);

    g_signal_connect_swapped (
        widget, "key-press-event",
        G_CALLBACK (mail_signature_manager_key_press_event_cb),
        manager);

    g_signal_connect_swapped (
        widget, "row-activated",
        G_CALLBACK (e_mail_signature_manager_edit_signature),
        manager);

    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));

    g_signal_connect_swapped (
        selection, "changed",
        G_CALLBACK (mail_signature_manager_selection_changed_cb),
        manager);

    container = hbox;

    widget = gtk_button_box_new (GTK_ORIENTATION_VERTICAL);
    gtk_button_box_set_layout (
        GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START);
    gtk_box_set_spacing (GTK_BOX (widget), 6);
    gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 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 = widget;  /* not referenced */
    gtk_widget_show (widget);

    g_signal_connect_swapped (
        widget, "clicked",
        G_CALLBACK (e_mail_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 = widget;  /* not referenced */
    gtk_widget_show (widget);

    settings = g_settings_new ("org.gnome.desktop.lockdown");

    g_settings_bind (
        settings, "disable-command-line",
        widget, "visible",
        G_SETTINGS_BIND_GET |
        G_SETTINGS_BIND_INVERT_BOOLEAN);

    g_object_unref (settings);

    g_signal_connect_swapped (
        widget, "clicked",
        G_CALLBACK (e_mail_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 = widget;  /* not referenced */
    gtk_widget_show (widget);

    g_signal_connect_swapped (
        widget, "clicked",
        G_CALLBACK (e_mail_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 = widget;  /* not referenced */
    gtk_widget_show (widget);

    g_signal_connect_swapped (
        widget, "clicked",
        G_CALLBACK (e_mail_signature_manager_remove_signature),
        manager);

    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_paned_pack2 (GTK_PANED (container), widget, FALSE, FALSE);
    gtk_widget_show (widget);

    container = widget;

    widget = e_mail_signature_preview_new (registry);
    gtk_container_add (GTK_CONTAINER (container), widget);
    manager->priv->preview = widget;  /* not referenced */
    gtk_widget_show (widget);

    gtk_paned_set_position (GTK_PANED (manager), PREVIEW_HEIGHT);
}

static void
mail_signature_manager_add_signature (EMailSignatureManager *manager)
{
    ESourceRegistry *registry;
    GtkWidget *editor;

    registry = e_mail_signature_manager_get_registry (manager);

    editor = e_mail_signature_editor_new (registry, NULL);
    gtkhtml_editor_set_html_mode (
        GTKHTML_EDITOR (editor), manager->priv->prefer_html);
    mail_signature_manager_emit_editor_created (manager, editor);

    gtk_widget_grab_focus (manager->priv->tree_view);
}

static void
mail_signature_manager_add_signature_script (EMailSignatureManager *manager)
{
    const gchar *title;

    title = _("Add Signature Script");
    mail_signature_manager_run_script_dialog (manager, NULL, title);

    gtk_widget_grab_focus (manager->priv->tree_view);
}

static void
mail_signature_manager_editor_created (EMailSignatureManager *manager,
                                       EMailSignatureEditor *editor)
{
    GtkWindowPosition position;
    gpointer parent;

    position = GTK_WIN_POS_CENTER_ON_PARENT;
    parent = gtk_widget_get_toplevel (GTK_WIDGET (manager));
    parent = gtk_widget_is_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
mail_signature_manager_edit_signature (EMailSignatureManager *manager)
{
    EMailSignatureTreeView *tree_view;
    ESourceMailSignature *extension;
    ESourceRegistry *registry;
    GtkWidget *editor;
    ESource *source;
    GFileInfo *file_info;
    GFile *file;
    const gchar *attribute;
    const gchar *extension_name;
    const gchar *title;
    GError *error = NULL;

    registry = e_mail_signature_manager_get_registry (manager);
    tree_view = E_MAIL_SIGNATURE_TREE_VIEW (manager->priv->tree_view);
    source = e_mail_signature_tree_view_ref_selected_source (tree_view);
    g_return_if_fail (source != NULL);

    extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
    extension = e_source_get_extension (source, extension_name);
    file = e_source_mail_signature_get_file (extension);

    attribute = G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE;

    /* XXX This blocks but it should just be a local file. */
    file_info = g_file_query_info (
        file, attribute, G_FILE_QUERY_INFO_NONE, NULL, &error);

    /* FIXME Make this into an EAlert. */
    if (error != NULL) {
        g_warn_if_fail (file_info == NULL);
        g_warning ("%s: %s", G_STRFUNC, error->message);
        g_object_unref (source);
        g_error_free (error);
        return;
    }

    if (g_file_info_get_attribute_boolean (file_info, attribute))
        goto script;

    editor = e_mail_signature_editor_new (registry, source);
    mail_signature_manager_emit_editor_created (manager, editor);

    goto exit;

script:
    title = _("Edit Signature Script");
    mail_signature_manager_run_script_dialog (manager, source, title);

exit:
    gtk_widget_grab_focus (GTK_WIDGET (tree_view));

    g_object_unref (file_info);
    g_object_unref (source);
}

static void
mail_signature_manager_remove_signature (EMailSignatureManager *manager)
{
    EMailSignatureTreeView *tree_view;
    ESourceMailSignature *extension;
    ESource *source;
    GFile *file;
    const gchar *extension_name;
    GError *error = NULL;

    tree_view = E_MAIL_SIGNATURE_TREE_VIEW (manager->priv->tree_view);
    source = e_mail_signature_tree_view_ref_selected_source (tree_view);

    if (source == NULL)
        return;

    extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
    extension = e_source_get_extension (source, extension_name);

    file = e_source_mail_signature_get_file (extension);

    /* XXX This blocks but it should just be a local file. */
    if (!g_file_delete (file, NULL, &error)) {
        g_warning ("%s", error->message);
        g_clear_error (&error);
    }

    /* Remove the mail signature data source asynchronously.
     * XXX No callback function because there's not much we can do
     *     if this fails.  We should probably implement EAlertSink. */
    e_source_remove (source, NULL, NULL, NULL);

    gtk_widget_grab_focus (GTK_WIDGET (tree_view));

    g_object_unref (source);
}

static void
e_mail_signature_manager_class_init (EMailSignatureManagerClass *class)
{
    GObjectClass *object_class;

    g_type_class_add_private (
        class, sizeof (EMailSignatureManagerPrivate));

    object_class = G_OBJECT_CLASS (class);
    object_class->set_property = mail_signature_manager_set_property;
    object_class->get_property = mail_signature_manager_get_property;
    object_class->dispose = mail_signature_manager_dispose;
    object_class->constructed = mail_signature_manager_constructed;

    class->add_signature = mail_signature_manager_add_signature;
    class->add_signature_script =
        mail_signature_manager_add_signature_script;
    class->editor_created = mail_signature_manager_editor_created;
    class->edit_signature = mail_signature_manager_edit_signature;
    class->remove_signature = mail_signature_manager_remove_signature;

    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_PARAM_STATIC_STRINGS));

    g_object_class_install_property (
        object_class,
        PROP_REGISTRY,
        g_param_spec_object (
            "registry",
            "Registry",
            NULL,
            E_TYPE_SOURCE_REGISTRY,
            G_PARAM_READWRITE |
            G_PARAM_CONSTRUCT |
            G_PARAM_STATIC_STRINGS));

    signals[ADD_SIGNATURE] = g_signal_new (
        "add-signature",
        G_OBJECT_CLASS_TYPE (class),
        G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
        G_STRUCT_OFFSET (EMailSignatureManagerClass, 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 (
            EMailSignatureManagerClass, 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 (EMailSignatureManagerClass, editor_created),
        NULL, NULL,
        g_cclosure_marshal_VOID__OBJECT,
        G_TYPE_NONE, 1,
        E_TYPE_MAIL_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 (EMailSignatureManagerClass, 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 (EMailSignatureManagerClass, remove_signature),
        NULL, NULL,
        g_cclosure_marshal_VOID__VOID,
        G_TYPE_NONE, 0);
}

static void
e_mail_signature_manager_init (EMailSignatureManager *manager)
{
    manager->priv = E_MAIL_SIGNATURE_MANAGER_GET_PRIVATE (manager);
}

GtkWidget *
e_mail_signature_manager_new (ESourceRegistry *registry)
{
    g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);

    return g_object_new (
        E_TYPE_MAIL_SIGNATURE_MANAGER,
        "registry", registry, NULL);
}

void
e_mail_signature_manager_add_signature (EMailSignatureManager *manager)
{
    g_return_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager));

    g_signal_emit (manager, signals[ADD_SIGNATURE], 0);
}

void
e_mail_signature_manager_add_signature_script (EMailSignatureManager *manager)
{
    g_return_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager));

    g_signal_emit (manager, signals[ADD_SIGNATURE_SCRIPT], 0);
}

void
e_mail_signature_manager_edit_signature (EMailSignatureManager *manager)
{
    g_return_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager));

    g_signal_emit (manager, signals[EDIT_SIGNATURE], 0);
}

void
e_mail_signature_manager_remove_signature (EMailSignatureManager *manager)
{
    g_return_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager));

    g_signal_emit (manager, signals[REMOVE_SIGNATURE], 0);
}

gboolean
e_mail_signature_manager_get_prefer_html (EMailSignatureManager *manager)
{
    g_return_val_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager), FALSE);

    return manager->priv->prefer_html;
}

void
e_mail_signature_manager_set_prefer_html (EMailSignatureManager *manager,
                                          gboolean prefer_html)
{
    g_return_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager));

    if (manager->priv->prefer_html == prefer_html)
        return;

    manager->priv->prefer_html = prefer_html;

    g_object_notify (G_OBJECT (manager), "prefer-html");
}

ESourceRegistry *
e_mail_signature_manager_get_registry (EMailSignatureManager *manager)
{
    g_return_val_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager), NULL);

    return manager->priv->registry;
}