aboutsummaryrefslogblamecommitdiffstats
path: root/composer/e-composer-actions.c
blob: 763d9920d6f733440fa1d05e69120dffe6d33d98 (plain) (tree)





































                                                                           
                                 



































                                                                           
                                                       

                                                            





                                                       




































                                                                               
                          



                                           
                                       

                                                   
                                                           
 
                                            


                       
                                          













                                                              
                                                 



                                                                  
                                                    





















































































































































































                                                                             
                                                                    




























































































































































































                                                            
                                    







































                                                    
                                      




























































































































                                                                             
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Copyright (C) 2008 Novell, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * 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
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "e-composer-actions.h"
#include "e-composer-private.h"

#include <errno.h>
#include <fcntl.h>
#include <e-util/e-error.h>
#include <mail/em-event.h>
#include <mail/em-format-html-print.h>

#include "misc/e-charset-picker.h"

static void
action_attach_cb (GtkAction *action,
                  EMsgComposer *composer)
{
    EAttachmentBar *bar;
    GtkWidget *dialog;
    GtkWidget *option;
    GSList *uris, *iter;
    const gchar *disposition;
    gboolean active;
    gint response;

    bar = E_ATTACHMENT_BAR (composer->priv->attachment_bar);

    dialog = gtk_file_chooser_dialog_new (
        _("Insert Attachment"),
        GTK_WINDOW (composer),
        GTK_FILE_CHOOSER_ACTION_OPEN,
        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
        _("A_ttach"), GTK_RESPONSE_OK,
        NULL);

    gtk_dialog_set_default_response (
        GTK_DIALOG (dialog), GTK_RESPONSE_OK);
    gtk_file_chooser_set_local_only (
        GTK_FILE_CHOOSER (dialog), FALSE);
    gtk_file_chooser_set_select_multiple (
        GTK_FILE_CHOOSER (dialog), TRUE);
    gtk_window_set_icon_name (
        GTK_WINDOW (dialog), "mail-message-new");

    option = gtk_check_button_new_with_mnemonic (
        _("_Suggest automatic display of attachment"));
    gtk_widget_show (option);
    gtk_file_chooser_set_extra_widget (
        GTK_FILE_CHOOSER (dialog), option);

    response = gtkhtml_editor_file_chooser_dialog_run (
        GTKHTML_EDITOR (composer), dialog);

    if (response != GTK_RESPONSE_OK)
        goto exit;

    uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
    active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (option));
    disposition = active ? "inline" : "attachment";

    for (iter = uris; iter != NULL; iter = iter->next) {
        CamelURL *url;

        url = camel_url_new (iter->data, NULL);
        if (url == NULL)
            continue;

        if (!g_ascii_strcasecmp (url->protocol, "file"))
            e_attachment_bar_attach (bar, url->path, disposition);
        else
            e_attachment_bar_attach (bar, iter->data, disposition);

        camel_url_free (url);
    }

    g_slist_foreach (uris, (GFunc) g_free, NULL);
    g_slist_free (uris);

exit:
    gtk_widget_destroy (dialog);
}

static void
action_charset_cb (GtkRadioAction *action,
                   GtkRadioAction *current,
                   EMsgComposer *composer)
{
    const gchar *charset;

    if (action != current)
        return;

    charset = gtk_action_get_name (GTK_ACTION (current));

    g_free (composer->priv->charset);
    composer->priv->charset = g_strdup (charset);
}

static void
action_close_cb (GtkAction *action,
                 EMsgComposer *composer)
{
    GtkhtmlEditor *editor;
    EComposerHeaderTable *table;
    GtkWidget *widget;
    const gchar *subject;
    gint response;

    editor = GTKHTML_EDITOR (composer);
    widget = GTK_WIDGET (composer);

    if (!gtkhtml_editor_get_changed (editor) &&
        e_composer_autosave_get_saved (composer)) {

        gtk_widget_destroy (widget);
        return;
    }

    gdk_window_raise (widget->window);

    table = e_msg_composer_get_header_table (composer);
    subject = e_composer_header_table_get_subject (table);

    if (subject == NULL || *subject == '\0')
        subject = _("Untitled Message");

    response = e_error_run (
        GTK_WINDOW (composer),
        "mail-composer:exit-unsaved",
        subject, NULL);

    switch (response) {
        case GTK_RESPONSE_YES:
            gtk_widget_hide (widget);
            gtk_action_activate (ACTION (SAVE_DRAFT));
            break;

        case GTK_RESPONSE_NO:
            gtk_widget_destroy (widget);
            break;

        case GTK_RESPONSE_CANCEL:
            break;
    }
}

static void
action_pgp_encrypt_cb (GtkToggleAction *action,
                       EMsgComposer *composer)
{
    GtkhtmlEditor *editor;

    editor = GTKHTML_EDITOR (composer);
    gtkhtml_editor_set_changed (editor, TRUE);
}

static void
action_pgp_sign_cb (GtkToggleAction *action,
                    EMsgComposer *composer)
{
    GtkhtmlEditor *editor;

    editor = GTKHTML_EDITOR (composer);
    gtkhtml_editor_set_changed (editor, TRUE);
}

static void
action_print_cb (GtkAction *action,
                 EMsgComposer *composer)
{
    GtkPrintOperationAction print_action;
    CamelMimeMessage *message;
    EMFormatHTMLPrint *efhp;

    print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG;
    message = e_msg_composer_get_message (composer, 1);

    efhp = em_format_html_print_new (NULL, print_action);
    em_format_html_print_raw_message (efhp, message);
    g_object_unref (efhp);
}

static void
action_print_preview_cb (GtkAction *action,
                         EMsgComposer *composer)
{
    GtkPrintOperationAction print_action;
    CamelMimeMessage *message;
    EMFormatHTMLPrint *efhp;

    print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW;
    message = e_msg_composer_get_message_print (composer, 1);

    efhp = em_format_html_print_new (NULL, print_action);
    em_format_html_print_raw_message (efhp, message);
    g_object_unref (efhp);
}

static void
action_save_cb (GtkAction *action,
                EMsgComposer *composer)
{
    GtkhtmlEditor *editor = GTKHTML_EDITOR (composer);
    const gchar *filename;
    gint fd;
    GError *error = NULL;

    filename = gtkhtml_editor_get_filename (editor);
    if (filename == NULL) {
        gtk_action_activate (ACTION (SAVE_AS));
        return;
    }

    /* Check if the file already exists and we can create it. */
    fd = g_open (filename, O_RDONLY | O_CREAT | O_EXCL, 0777);
    if (fd < 0) {
        gint errno_saved = errno;

        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
            gint response;

            response = e_error_run (
                GTK_WINDOW (composer),
                E_ERROR_ASK_FILE_EXISTS_OVERWRITE,
                filename, NULL);
            if (response != GTK_RESPONSE_OK)
                return;
        } else {
            e_error_run (
                GTK_WINDOW (composer),
                E_ERROR_NO_SAVE_FILE, filename,
                g_strerror (errno_saved));
            return;
        }
    } else
        close (fd);

    if (!gtkhtml_editor_save (editor, filename, TRUE, &error)) {
        e_error_run (
            GTK_WINDOW (composer),
            E_ERROR_NO_SAVE_FILE,
            filename, error->message);
        g_error_free (error);
        return;
    }

    gtkhtml_editor_run_command (GTKHTML_EDITOR (composer), "saved");
    e_composer_autosave_set_saved (composer, FALSE);
}

static void
action_save_as_cb (GtkAction *action,
                   EMsgComposer *composer)
{
    GtkWidget *dialog;
    gchar *filename;
    gint response;

    dialog = gtk_file_chooser_dialog_new (
        _("Save as..."), GTK_WINDOW (composer),
        GTK_FILE_CHOOSER_ACTION_SAVE,
        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
        GTK_STOCK_SAVE, GTK_RESPONSE_OK,
        NULL);

    gtk_dialog_set_default_response (
        GTK_DIALOG (dialog), GTK_RESPONSE_OK);
    gtk_file_chooser_set_local_only (
        GTK_FILE_CHOOSER (dialog), FALSE);
    gtk_window_set_icon_name (
        GTK_WINDOW (dialog), "mail-message-new");

    response = gtkhtml_editor_file_chooser_dialog_run (
        GTKHTML_EDITOR (composer), dialog);

    if (response != GTK_RESPONSE_OK)
        goto exit;

    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
    gtkhtml_editor_set_filename (GTKHTML_EDITOR (composer), filename);
    g_free (filename);

    gtk_action_activate (ACTION (SAVE));

exit:
    gtk_widget_destroy (dialog);
}

static void
action_save_draft_cb (GtkAction *action,
                      EMsgComposer *composer)
{
    e_msg_composer_save_draft (composer);
}

static void
action_send_cb (GtkAction *action,
                EMsgComposer *composer)
{
    e_msg_composer_send (composer);
}

static void
action_send_options_cb (GtkAction *action,
                        EMsgComposer *composer)
{
    EMEvent *event = em_event_peek ();
    EMEventTargetComposer *target;

    target = em_event_target_new_composer (
        event, composer, EM_EVENT_COMPOSER_SEND_OPTION);
    e_msg_composer_set_send_options (composer, FALSE);

    e_event_emit (
        (EEvent *) event,
        "composer.selectsendoption",
        (EEventTarget *) target);

    if (!composer->priv->send_invoked)
        e_error_run (
            GTK_WINDOW (composer),
            "mail-composer:send-options-support", NULL);
}

static void
action_smime_encrypt_cb (GtkToggleAction *action,
                         EMsgComposer *composer)
{
    GtkhtmlEditor *editor;

    editor = GTKHTML_EDITOR (composer);
    gtkhtml_editor_set_changed (editor, TRUE);
}

static void
action_smime_sign_cb (GtkToggleAction *action,
                      EMsgComposer *composer)
{
    GtkhtmlEditor *editor;

    editor = GTKHTML_EDITOR (composer);
    gtkhtml_editor_set_changed (editor, TRUE);
}

static void
action_view_bcc_cb (GtkToggleAction *action,
                    EMsgComposer *composer)
{
    EComposerHeaderTable *table;
    gboolean active;

    table = e_msg_composer_get_header_table (composer);
    active = gtk_toggle_action_get_active (action);

    e_composer_header_table_set_header_visible (
        table, E_COMPOSER_HEADER_BCC, active);
}

static void
action_view_cc_cb (GtkToggleAction *action,
                   EMsgComposer *composer)
{
    EComposerHeaderTable *table;
    gboolean active;

    table = e_msg_composer_get_header_table (composer);
    active = gtk_toggle_action_get_active (action);

    e_composer_header_table_set_header_visible (
        table, E_COMPOSER_HEADER_CC, active);
}

static void
action_view_from_cb (GtkToggleAction *action,
                     EMsgComposer *composer)
{
    EComposerHeaderTable *table;
    gboolean active;

    table = e_msg_composer_get_header_table (composer);
    active = gtk_toggle_action_get_active (action);

    e_composer_header_table_set_header_visible (
        table, E_COMPOSER_HEADER_FROM, active);
}

static void
action_view_post_to_cb (GtkToggleAction *action,
                        EMsgComposer *composer)
{
    EComposerHeaderTable *table;
    gboolean active;

    table = e_msg_composer_get_header_table (composer);
    active = gtk_toggle_action_get_active (action);

    e_composer_header_table_set_header_visible (
        table, E_COMPOSER_HEADER_POST_TO, active);
}

static void
action_view_reply_to_cb (GtkToggleAction *action,
                         EMsgComposer *composer)
{
    EComposerHeaderTable *table;
    gboolean active;

    table = e_msg_composer_get_header_table (composer);
    active = gtk_toggle_action_get_active (action);

    e_composer_header_table_set_header_visible (
        table, E_COMPOSER_HEADER_REPLY_TO, active);
}

static void
action_view_subject_cb (GtkToggleAction *action,
                        EMsgComposer *composer)
{
    EComposerHeaderTable *table;
    gboolean active;

    table = e_msg_composer_get_header_table (composer);
    active = gtk_toggle_action_get_active (action);

    e_composer_header_table_set_header_visible (
        table, E_COMPOSER_HEADER_SUBJECT, active);
}

static void
action_view_to_cb (GtkToggleAction *action,
                   EMsgComposer *composer)
{
    EComposerHeaderTable *table;
    gboolean active;

    table = e_msg_composer_get_header_table (composer);
    active = gtk_toggle_action_get_active (action);

    e_composer_header_table_set_header_visible (
        table, E_COMPOSER_HEADER_TO, active);
}

static GtkActionEntry entries[] = {

    { "attach",
          "mail-attachment",
      N_("_Attachment..."),
      "<Control>m",
      N_("Attach a file"),
      G_CALLBACK (action_attach_cb) },

    { "close",
      GTK_STOCK_CLOSE,
      N_("_Close"),
      "<Control>w",
      N_("Close the current file"),
      G_CALLBACK (action_close_cb) },

    { "print",
      GTK_STOCK_PRINT,
      N_("_Print..."),
      "<Control>p",
      NULL,
      G_CALLBACK (action_print_cb) },

    { "print-preview",
      GTK_STOCK_PRINT_PREVIEW,
      N_("Print Pre_view"),
      "<Shift><Control>p",
      NULL,
      G_CALLBACK (action_print_preview_cb) },

    { "save",
      GTK_STOCK_SAVE,
      N_("_Save"),
      "<Control>s",
      N_("Save the current file"),
      G_CALLBACK (action_save_cb) },

    { "save-as",
      GTK_STOCK_SAVE_AS,
      N_("Save _As..."),
      NULL,
      N_("Save the current file with a different name"),
      G_CALLBACK (action_save_as_cb) },

    { "save-draft",
      GTK_STOCK_SAVE,
      N_("Save _Draft"),
      "<Shift><Control>s",
      N_("Save as draft"),
      G_CALLBACK (action_save_draft_cb) },

    { "send",
      "mail-send",
      N_("S_end"),
      "<Control>Return",
      N_("Send this message"),
      G_CALLBACK (action_send_cb) },

    { "send-options",
      NULL,
      N_("_Send Options"),
      NULL,
      N_("Insert Send options"),
      G_CALLBACK (action_send_options_cb) },

    /* Menus */

    { "charset-menu",
      NULL,
      N_("Character _Encoding"),
      NULL,
      NULL,
      NULL },

    { "security-menu",
      NULL,
      N_("_Security"),
      NULL,
      NULL,
      NULL }
};

static GtkToggleActionEntry toggle_entries[] = {

    { "pgp-encrypt",
      NULL,
      N_("PGP _Encrypt"),
      NULL,
      N_("Encrypt this message with PGP"),
      G_CALLBACK (action_pgp_encrypt_cb),
      FALSE },

    { "pgp-sign",
      NULL,
      N_("PGP _Sign"),
      NULL,
      N_("Sign this message with your PGP key"),
      G_CALLBACK (action_pgp_sign_cb),
      FALSE },

    { "prioritize-message",
      NULL,
      N_("_Prioritize Message"),
      NULL,
      N_("Set the message priority to high"),
      NULL,  /* no callback */
      FALSE },

    { "request-read-receipt",
      NULL,
      N_("Re_quest Read Receipt"),
      NULL,
      N_("Get delivery notification when your message is read"),
      NULL,  /* no callback */
      FALSE },

    { "smime-encrypt",
      NULL,
      N_("S/MIME En_crypt"),
      NULL,
      N_("Encrypt this message with your S/MIME Encryption Certificate"),
      G_CALLBACK (action_smime_encrypt_cb),
      FALSE },

    { "smime-sign",
      NULL,
      N_("S/MIME Sig_n"),
      NULL,
      N_("Sign this message with your S/MIME Signature Certificate"),
      G_CALLBACK (action_smime_sign_cb),
      FALSE },

    { "view-bcc",
      NULL,
      N_("_Bcc Field"),
      NULL,
      N_("Toggles whether the BCC field is displayed"),
      G_CALLBACK (action_view_bcc_cb),
      FALSE },

    { "view-cc",
      NULL,
      N_("_Cc Field"),
      NULL,
      N_("Toggles whether the CC field is displayed"),
      G_CALLBACK (action_view_cc_cb),
      FALSE },

    { "view-from",
      NULL,
      N_("_From Field"),
      NULL,
      N_("Toggles whether the From chooser is displayed"),
      G_CALLBACK (action_view_from_cb),
      FALSE },

    { "view-post-to",
      NULL,
      N_("_Post-To Field"),
      NULL,
      N_("Toggles whether the Post-To field is displayed"),
      G_CALLBACK (action_view_post_to_cb),
      FALSE },

    { "view-reply-to",
      NULL,
      N_("_Reply-To Field"),
      NULL,
      N_("Toggles whether the Reply-To field is displayed"),
      G_CALLBACK (action_view_reply_to_cb),
      FALSE },

    { "view-subject",
      NULL,
      N_("_Subject Field"),
      NULL,
      N_("Toggles whether the Subject field is displayed"),
      G_CALLBACK (action_view_subject_cb),
      FALSE },

    { "view-to",
      NULL,
      N_("_To Field"),
      NULL,
      N_("Toggles whether the To field is displayed"),
      G_CALLBACK (action_view_to_cb),
      FALSE }
};

void
e_composer_actions_init (EMsgComposer *composer)
{
    GtkActionGroup *action_group;
    GtkUIManager *manager;
    gboolean visible;

    g_return_if_fail (E_IS_MSG_COMPOSER (composer));

    manager = gtkhtml_editor_get_ui_manager (GTKHTML_EDITOR (composer));

    /* Composer Actions */
    action_group = composer->priv->composer_actions;
    gtk_action_group_set_translation_domain (
        action_group, GETTEXT_PACKAGE);
    gtk_action_group_add_actions (
        action_group, entries,
        G_N_ELEMENTS (entries), composer);
    gtk_action_group_add_toggle_actions (
        action_group, toggle_entries,
        G_N_ELEMENTS (toggle_entries), composer);
    gtk_ui_manager_insert_action_group (manager, action_group, 0);

    /* Character Set Actions */
    action_group = composer->priv->charset_actions;
    gtk_action_group_set_translation_domain (
        action_group, GETTEXT_PACKAGE);
    e_charset_add_radio_actions (
        action_group, composer->priv->charset,
        G_CALLBACK (action_charset_cb), composer);
    gtk_ui_manager_insert_action_group (manager, action_group, 0);

    /* Fine Tuning */

    g_object_set (
        G_OBJECT (ACTION (ATTACH)),
        "short-label", _("Attach"), NULL);

#if defined (HAVE_NSS) && defined (SMIME_SUPPORTED)
    visible = TRUE;
#else
    visible = FALSE;
#endif

    gtk_action_set_visible (ACTION (SMIME_ENCRYPT), visible);
    gtk_action_set_visible (ACTION (SMIME_SIGN), visible);
}