diff options
Diffstat (limited to 'composer/e-msg-composer-attachment.c')
-rw-r--r-- | composer/e-msg-composer-attachment.c | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/composer/e-msg-composer-attachment.c b/composer/e-msg-composer-attachment.c new file mode 100644 index 0000000000..f4741d987f --- /dev/null +++ b/composer/e-msg-composer-attachment.c @@ -0,0 +1,480 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-msg-composer-attachment.c + * + * Copyright (C) 1999 Helix Code, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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 General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Ettore Perazzoli + */ + +/* This is the object representing an email attachment. It is implemented as a + GtkObject to make it easier for the application to handle it. For example, + the "changed" signal is emitted whenever something changes in the + attachment. Also, this contains the code to let users edit the + attachment manually. */ + +#include <sys/stat.h> + +#include <gnome.h> + +#include "e-msg-composer-attachment.h" + + +enum { + CHANGED, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + +static GtkObjectClass *parent_class = NULL; + + +/* Utility functions. */ + +static const gchar * +get_mime_type (const gchar *file_name) +{ + const gchar *mime_type; + + mime_type = gnome_mime_type_of_file (file_name); + if (mime_type == NULL) + mime_type = "application/octet-stream"; + + return mime_type; +} + +static void +init_mime_type (EMsgComposerAttachment *attachment) +{ + attachment->mime_type = g_strdup (get_mime_type (attachment->file_name)); +} + +static void +set_mime_type (EMsgComposerAttachment *attachment) +{ + g_free (attachment->mime_type); + init_mime_type (attachment); +} + +static void +changed (EMsgComposerAttachment *attachment) +{ + gtk_signal_emit (GTK_OBJECT (attachment), signals[CHANGED]); +} + + +/* GtkObject methods. */ + +static void +destroy (GtkObject *object) +{ + EMsgComposerAttachment *attachment; + + attachment = E_MSG_COMPOSER_ATTACHMENT (object); + + g_free (attachment->file_name); + g_free (attachment->description); + g_free (attachment->mime_type); +} + + +/* Signals. */ + +static void +real_changed (EMsgComposerAttachment *msg_composer_attachment) +{ + g_return_if_fail (msg_composer_attachment != NULL); + g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT (msg_composer_attachment)); +} + + +static void +class_init (EMsgComposerAttachmentClass *klass) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass*) klass; + + parent_class = gtk_type_class (gtk_object_get_type ()); + + object_class->destroy = destroy; + + signals[CHANGED] = gtk_signal_new ("changed", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET + (EMsgComposerAttachmentClass, + changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); + + klass->changed = real_changed; +} + +static void +init (EMsgComposerAttachment *msg_composer_attachment) +{ + msg_composer_attachment->editor_gui = NULL; + msg_composer_attachment->file_name = NULL; + msg_composer_attachment->description = NULL; + msg_composer_attachment->mime_type = NULL; + msg_composer_attachment->size = 0; +} + +GtkType +e_msg_composer_attachment_get_type (void) +{ + static GtkType type = 0; + + if (type == 0) { + static const GtkTypeInfo info = { + "EMsgComposerAttachment", + sizeof (EMsgComposerAttachment), + sizeof (EMsgComposerAttachmentClass), + (GtkClassInitFunc) class_init, + (GtkObjectInitFunc) init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + type = gtk_type_unique (gtk_object_get_type (), &info); + } + + return type; +} + + +/** + * e_msg_composer_attachment_new: + * @file_name: + * + * Return value: + **/ +EMsgComposerAttachment * +e_msg_composer_attachment_new (const gchar *file_name) +{ + EMsgComposerAttachment *new; + struct stat statbuf; + + g_return_val_if_fail (file_name != NULL, NULL); + + new = gtk_type_new (e_msg_composer_attachment_get_type ()); + + new->editor_gui = NULL; + + new->file_name = g_strdup (file_name); + new->description = g_strdup (g_basename (new->file_name)); + + if (stat (file_name, &statbuf) < 0) + new->size = 0; + else + new->size = statbuf.st_size; + + init_mime_type (new); + + return new; +} + + +/* The attachment property dialog. */ + +struct _DialogData { + GtkWidget *dialog; + GtkEntry *file_name_entry; + GtkEntry *description_entry; + GtkEntry *mime_type_entry; + GtkWidget *browse_widget; + EMsgComposerAttachment *attachment; +}; +typedef struct _DialogData DialogData; + +static void +destroy_dialog_data (DialogData *data) +{ + if (data->browse_widget != NULL) + gtk_widget_destroy (data->browse_widget); + g_free (data); +} + +static void +update_mime_type (DialogData *data) +{ + const gchar *mime_type; + const gchar *file_name; + + file_name = gtk_entry_get_text (data->file_name_entry); + mime_type = get_mime_type (file_name); + + gtk_entry_set_text (data->mime_type_entry, mime_type); +} + +static void +browse_ok_cb (GtkWidget *widget, + gpointer data) +{ + GtkWidget *file_selection; + DialogData *dialog_data; + const gchar *file_name; + + dialog_data = (DialogData *) data; + file_selection = gtk_widget_get_toplevel (widget); + + file_name = gtk_file_selection_get_filename + (GTK_FILE_SELECTION (file_selection)); + + gtk_entry_set_text (dialog_data->file_name_entry, file_name); + + update_mime_type (dialog_data); + + gtk_widget_hide (file_selection); +} + +static void +browse (DialogData *data) +{ + if (data->browse_widget == NULL) { + GtkWidget *file_selection; + GtkWidget *cancel_button; + GtkWidget *ok_button; + + file_selection + = gtk_file_selection_new (_("Select attachment")); + gtk_window_set_position (GTK_WINDOW (file_selection), + GTK_WIN_POS_MOUSE); + gtk_window_set_transient_for (GTK_WINDOW (file_selection), + GTK_WINDOW (data->dialog)); + + ok_button = GTK_FILE_SELECTION (file_selection)->ok_button; + gtk_signal_connect (GTK_OBJECT (ok_button), + "clicked", GTK_SIGNAL_FUNC (browse_ok_cb), + data); + + cancel_button + = GTK_FILE_SELECTION (file_selection)->cancel_button; + gtk_signal_connect_object (GTK_OBJECT (cancel_button), + "clicked", + GTK_SIGNAL_FUNC (gtk_widget_hide), + GTK_OBJECT (file_selection)); + + data->browse_widget = file_selection; + } + + gtk_widget_show (GTK_WIDGET (data->browse_widget)); +} + +static void +set_entry (GladeXML *xml, + const gchar *widget_name, + const gchar *value) +{ + GtkEntry *entry; + + entry = GTK_ENTRY (glade_xml_get_widget (xml, widget_name)); + if (entry == NULL) + g_warning ("Entry for `%s' not found.", widget_name); + gtk_entry_set_text (entry, value); +} + +static void +connect_entry_changed (GladeXML *gui, + const gchar *name, + GtkSignalFunc func, + gpointer data) +{ + GtkWidget *widget; + + widget = glade_xml_get_widget (gui, name); + gtk_signal_connect (GTK_OBJECT (widget), "changed", func, data); +} + +static void +connect_widget (GladeXML *gui, + const gchar *name, + const gchar *signal_name, + GtkSignalFunc func, + gpointer data) +{ + GtkWidget *widget; + + widget = glade_xml_get_widget (gui, name); + gtk_signal_connect (GTK_OBJECT (widget), signal_name, func, data); +} + +static void +apply (DialogData *data) +{ + EMsgComposerAttachment *attachment; + + attachment = data->attachment; + + g_free (attachment->file_name); + attachment->file_name = g_strdup (gtk_entry_get_text + (data->file_name_entry)); + + g_free (attachment->description); + attachment->description = g_strdup (gtk_entry_get_text + (data->description_entry)); + + g_free (attachment->mime_type); + attachment->mime_type = g_strdup (gtk_entry_get_text + (data->mime_type_entry)); + + changed (attachment); +} + +static void +entry_changed_cb (GtkWidget *widget, gpointer data) +{ + DialogData *dialog_data; + GladeXML *gui; + GtkWidget *apply_button; + + dialog_data = (DialogData *) data; + gui = dialog_data->attachment->editor_gui; + + apply_button = glade_xml_get_widget (gui, "apply_button"); + gtk_widget_set_sensitive (apply_button, TRUE); +} + +static void +close_cb (GtkWidget *widget, + gpointer data) +{ + EMsgComposerAttachment *attachment; + DialogData *dialog_data; + + dialog_data = (DialogData *) data; + attachment = dialog_data->attachment; + + gtk_widget_destroy (glade_xml_get_widget (attachment->editor_gui, + "dialog")); + gtk_object_unref (GTK_OBJECT (attachment->editor_gui)); + attachment->editor_gui = NULL; + + destroy_dialog_data (dialog_data); +} + +static void +apply_cb (GtkWidget *widget, + gpointer data) +{ + DialogData *dialog_data; + + dialog_data = (DialogData *) data; + apply (dialog_data); +} + +static void +ok_cb (GtkWidget *widget, + gpointer data) +{ + apply_cb (widget, data); + close_cb (widget, data); +} + +static void +browse_cb (GtkWidget *widget, + gpointer data) +{ + DialogData *dialog_data; + + dialog_data = (DialogData *) data; + browse (dialog_data); +} + +static void +file_name_focus_out_cb (GtkWidget *widget, + GdkEventFocus *event, + gpointer data) +{ + DialogData *dialog_data; + + dialog_data = (DialogData *) data; + update_mime_type (dialog_data); +} + + +void +e_msg_composer_attachment_edit (EMsgComposerAttachment *attachment, + GtkWidget *parent) +{ + DialogData *dialog_data; + GladeXML *editor_gui; + + g_return_if_fail (attachment != NULL); + g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT (attachment)); + + if (attachment->editor_gui != NULL) { + GtkWidget *window; + + window = glade_xml_get_widget (attachment->editor_gui, + "dialog"); + gdk_window_show (window->window); + return; + } + + editor_gui = glade_xml_new (E_GLADEDIR "/e-msg-composer-attachment.glade", + NULL); + if (editor_gui == NULL) { + g_warning ("Cannot load `e-msg-composer-attachment.glade'"); + return; + } + + attachment->editor_gui = editor_gui; + + gtk_window_set_transient_for + (GTK_WINDOW (glade_xml_get_widget (editor_gui, "dialog")), + GTK_WINDOW (gtk_widget_get_toplevel (parent))); + + dialog_data = g_new (DialogData, 1); + dialog_data->browse_widget = NULL; + dialog_data->attachment = attachment; + dialog_data->dialog = glade_xml_get_widget (editor_gui, "dialog"); + dialog_data->file_name_entry = GTK_ENTRY (glade_xml_get_widget + (editor_gui, + "file_name_entry")); + dialog_data->description_entry = GTK_ENTRY (glade_xml_get_widget + (editor_gui, + "description_entry")); + dialog_data->mime_type_entry = GTK_ENTRY (glade_xml_get_widget + (editor_gui, + "mime_type_entry")); + + if (attachment != NULL) { + set_entry (editor_gui, "file_name_entry", attachment->file_name); + set_entry (editor_gui, "description_entry", attachment->description); + set_entry (editor_gui, "mime_type_entry", attachment->mime_type); + } + + connect_entry_changed (editor_gui, "file_name_entry", + entry_changed_cb, dialog_data); + connect_entry_changed (editor_gui, "description_entry", + entry_changed_cb, dialog_data); + + connect_widget (editor_gui, "ok_button", "clicked", ok_cb, dialog_data); + connect_widget (editor_gui, "apply_button", "clicked", apply_cb, dialog_data); + connect_widget (editor_gui, "close_button", "clicked", close_cb, dialog_data); + + connect_widget (editor_gui, "browse_button", "clicked", browse_cb, dialog_data); + + connect_widget (editor_gui, "file_name_entry", "focus_out_event", + file_name_focus_out_cb, dialog_data); +} |