diff options
author | Ettore Perazzoli <ettore@src.gnome.org> | 1999-11-17 23:35:43 +0800 |
---|---|---|
committer | Ettore Perazzoli <ettore@src.gnome.org> | 1999-11-17 23:35:43 +0800 |
commit | 9663037f6c0daaf03d74c88afb002a6bb33f222b (patch) | |
tree | a6edccc1e5963511d0734e3171b97d853bf14b5c /composer/e-msg-composer-attachment-bar.c | |
parent | ca7044930f42a698fd88f914c2512a20e2eeaae9 (diff) | |
download | gsoc2013-evolution-9663037f6c0daaf03d74c88afb002a6bb33f222b.tar.gz gsoc2013-evolution-9663037f6c0daaf03d74c88afb002a6bb33f222b.tar.zst gsoc2013-evolution-9663037f6c0daaf03d74c88afb002a6bb33f222b.zip |
More work:
- Fixed some Camel API naming issues.
- Moved the message composer stuff to the `composer' directory.
svn path=/trunk/; revision=1395
Diffstat (limited to 'composer/e-msg-composer-attachment-bar.c')
-rw-r--r-- | composer/e-msg-composer-attachment-bar.c | 665 |
1 files changed, 665 insertions, 0 deletions
diff --git a/composer/e-msg-composer-attachment-bar.c b/composer/e-msg-composer-attachment-bar.c new file mode 100644 index 0000000000..b55a4cbad4 --- /dev/null +++ b/composer/e-msg-composer-attachment-bar.c @@ -0,0 +1,665 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-msg-composer-attachment-bar.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 + */ + +#include <gnome.h> +#include <glade/glade.h> + +#include "e-msg-composer-attachment.h" +#include "e-msg-composer-attachment-bar.h" + + +#define ICON_WIDTH 64 +#define ICON_SEPARATORS " /-_" +#define ICON_SPACING 2 +#define ICON_ROW_SPACING ICON_SPACING +#define ICON_COL_SPACING ICON_SPACING +#define ICON_BORDER 2 +#define ICON_TEXT_SPACING 2 + + +static GnomeIconListClass *parent_class = NULL; + +struct _EMsgComposerAttachmentBarPrivate { + GList *attachments; + guint num_attachments; + + GtkWidget *context_menu; + GtkWidget *icon_context_menu; +}; + + +enum { + CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + + +static void update (EMsgComposerAttachmentBar *bar); + + +static gchar * +size_to_string (gulong size) +{ + gchar *size_string; + + /* FIXME: The following should probably go into a separate module, as + we might have to do the same thing in other places as well. Also, + I am not sure this will be OK for all the languages. */ + + if (size < 1e3L) { + if (size == 1) + size_string = g_strdup (_("1 byte")); + else + size_string = g_strdup_printf (_("%u bytes"), + (guint) size); + } else { + gdouble displayed_size; + + if (size < 1e6L) { + displayed_size = (gdouble) size / 1.0e3; + size_string = g_strdup_printf (_("%.1fK"), + displayed_size); + } else if (size < 1e9L) { + displayed_size = (gdouble) size / 1.0e6; + size_string = g_strdup_printf (_("%.1fM"), + displayed_size); + } else { + displayed_size = (gdouble) size / 1.0e9; + size_string = g_strdup_printf (_("%.1fG"), + displayed_size); + } + } + + return size_string; +} + + +/* Sorting. */ + +static gint +attachment_sort_func (gconstpointer a, gconstpointer b) +{ + const EMsgComposerAttachment *attachment_a, *attachment_b; + + attachment_a = (EMsgComposerAttachment *) a; + attachment_b = (EMsgComposerAttachment *) b; + + return strcmp (attachment_a->description, attachment_b->description); +} + +static void +sort (EMsgComposerAttachmentBar *bar) +{ + EMsgComposerAttachmentBarPrivate *priv; + + priv = bar->priv; + + priv->attachments = g_list_sort (priv->attachments, + attachment_sort_func); +} + + +/* Attachment handling functions. */ + +static void +free_attachment_list (EMsgComposerAttachmentBar *bar) +{ + EMsgComposerAttachmentBarPrivate *priv; + GList *p; + + priv = bar->priv; + + for (p = priv->attachments; p != NULL; p = p->next) + gtk_object_unref (GTK_OBJECT (p->data)); +} + +static void +attachment_changed_cb (EMsgComposerAttachment *attachment, + gpointer data) +{ + update (E_MSG_COMPOSER_ATTACHMENT_BAR (data)); +} + +static void +add_from_file (EMsgComposerAttachmentBar *bar, + const gchar *file_name) +{ + EMsgComposerAttachment *attachment; + + attachment = e_msg_composer_attachment_new (file_name); + + gtk_signal_connect (GTK_OBJECT (attachment), "changed", + GTK_SIGNAL_FUNC (attachment_changed_cb), + bar); + + bar->priv->attachments = g_list_append (bar->priv->attachments, + attachment); + bar->priv->num_attachments++; + + sort (bar); + update (bar); + + gtk_signal_emit (GTK_OBJECT (bar), signals[CHANGED]); +} + +static void +remove_attachment (EMsgComposerAttachmentBar *bar, + EMsgComposerAttachment *attachment) +{ + bar->priv->attachments = g_list_remove (bar->priv->attachments, + attachment); + bar->priv->num_attachments--; + + gtk_object_unref (GTK_OBJECT (attachment)); + + gtk_signal_emit (GTK_OBJECT (bar), signals[CHANGED]); +} + + +/* Icon list contents handling. */ + +static void +update (EMsgComposerAttachmentBar *bar) +{ + EMsgComposerAttachmentBarPrivate *priv; + GnomeIconList *icon_list; + GList *p; + + priv = bar->priv; + icon_list = GNOME_ICON_LIST (bar); + + gnome_icon_list_freeze (icon_list); + + gnome_icon_list_clear (icon_list); + + /* FIXME could be faster, but we don't care. */ + + for (p = priv->attachments; p != NULL; p = p->next) { + EMsgComposerAttachment *attachment; + const gchar *icon_name; + gchar *size_string; + gchar *label; + + attachment = p->data; + icon_name = gnome_mime_get_value (attachment->mime_type, + "icon-filename"); + + /* FIXME we need some better default icon. */ + if (icon_name == NULL) + icon_name = gnome_mime_get_value ("text/plain", + "icon-filename"); + + size_string = size_to_string (attachment->size); + + /* FIXME: If GnomeIconList honoured "\n", the result would be a + lot better. */ + label = g_strconcat (attachment->description, "\n(", + size_string, ")", NULL); + + gnome_icon_list_append (icon_list, icon_name, label); + + g_free (label); + g_free (size_string); + } + + gnome_icon_list_thaw (icon_list); +} + +static void +remove_selected (EMsgComposerAttachmentBar *bar) +{ + GnomeIconList *icon_list; + EMsgComposerAttachment *attachment; + GList *attachment_list; + GList *p; + gint num; + + icon_list = GNOME_ICON_LIST (bar); + + /* Weee! I am especially proud of this piece of cheesy code: it is + truly awful. But unless one attaches a huge number of files, it + will not be as greedy as intended. FIXME of course. */ + + attachment_list = NULL; + for (p = icon_list->selection; p != NULL; p = p->next) { + num = GPOINTER_TO_INT (p->data); + attachment = E_MSG_COMPOSER_ATTACHMENT + (g_list_nth (bar->priv->attachments, num)->data); + attachment_list = g_list_prepend (attachment_list, attachment); + } + + for (p = attachment_list; p != NULL; p = p->next) + remove_attachment (bar, E_MSG_COMPOSER_ATTACHMENT (p->data)); + + g_list_free (attachment_list); + + update (bar); +} + +static void +edit_selected (EMsgComposerAttachmentBar *bar) +{ + GnomeIconList *icon_list; + EMsgComposerAttachment *attachment; + gint num; + + icon_list = GNOME_ICON_LIST (bar); + + num = GPOINTER_TO_INT (icon_list->selection->data); + attachment = g_list_nth (bar->priv->attachments, num)->data; + + e_msg_composer_attachment_edit (attachment, GTK_WIDGET (bar)); +} + + +/* "Attach" dialog. */ + +static void +attach_cb (GtkWidget *widget, + gpointer data) +{ + EMsgComposerAttachmentBar *bar; + GtkWidget *file_selection; + const gchar *file_name; + + file_selection = gtk_widget_get_toplevel (widget); + bar = E_MSG_COMPOSER_ATTACHMENT_BAR (data); + + file_name = gtk_file_selection_get_filename + (GTK_FILE_SELECTION (file_selection)); + add_from_file (bar, file_name); + + gtk_widget_hide (file_selection); +} + +static void +add_from_user (EMsgComposerAttachmentBar *bar) +{ + GtkWidget *file_selection; + GtkWidget *cancel_button; + GtkWidget *ok_button; + + file_selection = gtk_file_selection_new (_("Add attachment")); + gtk_window_set_position (GTK_WINDOW (file_selection), + GTK_WIN_POS_MOUSE); + + ok_button = GTK_FILE_SELECTION (file_selection)->ok_button; + gtk_signal_connect (GTK_OBJECT (ok_button), + "clicked", GTK_SIGNAL_FUNC (attach_cb), bar); + + 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)); + + gtk_widget_show (GTK_WIDGET (file_selection)); +} + + +/* Callbacks. */ + +static void +add_cb (GtkWidget *widget, + gpointer data) +{ + g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (data)); + + add_from_user (E_MSG_COMPOSER_ATTACHMENT_BAR (data)); +} + +static void +properties_cb (GtkWidget *widget, + gpointer data) +{ + EMsgComposerAttachmentBar *bar; + + g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (data)); + + bar = E_MSG_COMPOSER_ATTACHMENT_BAR (data); + edit_selected (data); +} + +static void +remove_cb (GtkWidget *widget, + gpointer data) +{ + EMsgComposerAttachmentBar *bar; + + g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (data)); + + bar = E_MSG_COMPOSER_ATTACHMENT_BAR (data); + remove_selected (bar); +} + + +/* Popup menu handling. */ + +static GnomeUIInfo icon_context_menu_info[] = { + GNOMEUIINFO_ITEM (N_("Remove"), + N_("Remove selected items from the attachment list"), + remove_cb, NULL), + GNOMEUIINFO_MENU_PROPERTIES_ITEM (properties_cb, NULL), + GNOMEUIINFO_END +}; + +static GtkWidget * +get_icon_context_menu (EMsgComposerAttachmentBar *bar) +{ + EMsgComposerAttachmentBarPrivate *priv; + + priv = bar->priv; + if (priv->icon_context_menu == NULL) + priv->icon_context_menu = gnome_popup_menu_new + (icon_context_menu_info); + + return priv->icon_context_menu; +} + +static void +popup_icon_context_menu (EMsgComposerAttachmentBar *bar, + gint num, + GdkEventButton *event) +{ + GtkWidget *menu; + + menu = get_icon_context_menu (bar); + gnome_popup_menu_do_popup (menu, NULL, NULL, event, bar); +} + +static GnomeUIInfo context_menu_info[] = { + GNOMEUIINFO_ITEM (N_("Add attachment..."), + N_("Attach a file to the message"), + add_cb, NULL), + GNOMEUIINFO_END +}; + +static GtkWidget * +get_context_menu (EMsgComposerAttachmentBar *bar) +{ + EMsgComposerAttachmentBarPrivate *priv; + + priv = bar->priv; + if (priv->context_menu == NULL) + priv->context_menu = gnome_popup_menu_new (context_menu_info); + + return priv->context_menu; +} + +static void +popup_context_menu (EMsgComposerAttachmentBar *bar, + GdkEventButton *event) +{ + GtkWidget *menu; + + menu = get_context_menu (bar); + gnome_popup_menu_do_popup (menu, NULL, NULL, event, bar); +} + + +/* GtkObject methods. */ + +static void +destroy (GtkObject *object) +{ + EMsgComposerAttachmentBar *bar; + + bar = E_MSG_COMPOSER_ATTACHMENT_BAR (object); + + free_attachment_list (bar); + + if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + +/* GtkWidget methods. */ + +static gint +button_press_event (GtkWidget *widget, + GdkEventButton *event) +{ + EMsgComposerAttachmentBar *bar; + GnomeIconList *icon_list; + gint icon_number; + + bar = E_MSG_COMPOSER_ATTACHMENT_BAR (widget); + icon_list = GNOME_ICON_LIST (widget); + + if (event->button != 3) + return GTK_WIDGET_CLASS (parent_class)->button_press_event + (widget, event); + + icon_number = gnome_icon_list_get_icon_at (icon_list, + event->x, event->y); + + if (icon_number >= 0) { + gnome_icon_list_select_icon (icon_list, icon_number); + popup_icon_context_menu (bar, icon_number, event); + } else { + popup_context_menu (bar, event); + } + + return TRUE; +} + + +/* GnomeIconList methods. */ + +static gboolean +text_changed (GnomeIconList *gil, + gint num, + const gchar *new_text) +{ + EMsgComposerAttachmentBar *bar; + EMsgComposerAttachment *attachment; + GList *p; + + bar = E_MSG_COMPOSER_ATTACHMENT_BAR (gil); + p = g_list_nth (bar->priv->attachments, num); + attachment = p->data; + + g_free (attachment->description); + attachment->description = g_strdup (new_text); + + return TRUE; +} + + +/* Initialization. */ + +static void +class_init (EMsgComposerAttachmentBarClass *class) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + GnomeIconListClass *icon_list_class; + + object_class = GTK_OBJECT_CLASS (class); + widget_class = GTK_WIDGET_CLASS (class); + icon_list_class = GNOME_ICON_LIST_CLASS (class); + + parent_class = gtk_type_class (gnome_icon_list_get_type ()); + + object_class->destroy = destroy; + + widget_class->button_press_event = button_press_event; + + icon_list_class->text_changed = text_changed; + + /* Setup signals. */ + + signals[CHANGED] = + gtk_signal_new ("changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (EMsgComposerAttachmentBarClass, + changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); +} + +static void +init (EMsgComposerAttachmentBar *bar) +{ + EMsgComposerAttachmentBarPrivate *priv; + guint icon_size; + + priv = g_new (EMsgComposerAttachmentBarPrivate, 1); + + priv->attachments = NULL; + priv->context_menu = NULL; + priv->icon_context_menu = NULL; + + priv->num_attachments = 0; + + bar->priv = priv; + + /* FIXME partly hardcoded. We should compute height from the font, and + allow at least 2 lines for every item. */ + icon_size = ICON_WIDTH + ICON_SPACING + ICON_BORDER + ICON_TEXT_SPACING; + icon_size += 24; + + gtk_widget_set_usize (GTK_WIDGET (bar), icon_size * 4, icon_size); +} + + +GtkType +e_msg_composer_attachment_bar_get_type (void) +{ + static GtkType type = 0; + + if (type == 0) { + static const GtkTypeInfo info = { + "EMsgComposerAttachmentBar", + sizeof (EMsgComposerAttachmentBar), + sizeof (EMsgComposerAttachmentBarClass), + (GtkClassInitFunc) class_init, + (GtkObjectInitFunc) init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + type = gtk_type_unique (gnome_icon_list_get_type (), &info); + } + + return type; +} + +GtkWidget * +e_msg_composer_attachment_bar_new (GtkAdjustment *adj) +{ + EMsgComposerAttachmentBar *new; + GnomeIconList *icon_list; + + gtk_widget_push_visual (gdk_imlib_get_visual ()); + gtk_widget_push_colormap (gdk_imlib_get_colormap ()); + new = gtk_type_new (e_msg_composer_attachment_bar_get_type ()); + gtk_widget_pop_visual (); + gtk_widget_pop_colormap (); + + icon_list = GNOME_ICON_LIST (new); + + gnome_icon_list_construct (icon_list, ICON_WIDTH, adj, 0); + + gnome_icon_list_set_separators (icon_list, ICON_SEPARATORS); + gnome_icon_list_set_row_spacing (icon_list, ICON_ROW_SPACING); + gnome_icon_list_set_col_spacing (icon_list, ICON_COL_SPACING); + gnome_icon_list_set_icon_border (icon_list, ICON_BORDER); + gnome_icon_list_set_text_spacing (icon_list, ICON_TEXT_SPACING); + gnome_icon_list_set_selection_mode (icon_list, GTK_SELECTION_MULTIPLE); + + return GTK_WIDGET (new); +} + + +static void +attach_to_multipart (CamelMultipart *multipart, + EMsgComposerAttachment *attachment) +{ + CamelMimeBodyPart *part; + + /* FIXME encoding etc. etc. ? */ + /* FIXME I am not sure how to add an attachment through the Camel + API. :-/ */ + + part = camel_mime_body_part_new (); + camel_mime_part_set_disposition (CAMEL_MIME_PART (part), "attachment"); + camel_mime_part_set_filename (CAMEL_MIME_PART (part), + g_strdup (g_basename (attachment->file_name))); + camel_mime_part_set_description (CAMEL_MIME_PART (part), + g_strdup (attachment->description)); + camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (part), + g_strdup (attachment->mime_type)); +} + +void +e_msg_composer_attachment_bar_to_multipart (EMsgComposerAttachmentBar *bar, + CamelMultipart *multipart) +{ + EMsgComposerAttachmentBarPrivate *priv; + GList *p; + + g_return_if_fail (bar != NULL); + g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (bar)); + g_return_if_fail (multipart != NULL); + g_return_if_fail (CAMEL_IS_MULTIPART (multipart)); + + priv = bar->priv; + + for (p = priv->attachments; p != NULL; p = p->next) { + EMsgComposerAttachment *attachment; + + attachment = E_MSG_COMPOSER_ATTACHMENT (p->data); + attach_to_multipart (multipart, attachment); + } +} + + +guint +e_msg_composer_attachment_bar_get_num_attachments (EMsgComposerAttachmentBar *bar) +{ + g_return_val_if_fail (bar != NULL, 0); + g_return_val_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (bar), 0); + + return bar->priv->num_attachments; +} + + +void +e_msg_composer_attachment_bar_attach (EMsgComposerAttachmentBar *bar, + const gchar *file_name) +{ + g_return_if_fail (bar != NULL); + g_return_if_fail (E_IS_MSG_COMPOSER_ATTACHMENT_BAR (bar)); + + if (file_name == NULL) + add_from_user (bar); + else + add_from_file (bar, file_name); +} |