From d518eefe676594b630ee8c9936796257f7b33130 Mon Sep 17 00:00:00 2001 From: Alfons Hoogervorst Date: Sat, 30 Jun 2001 17:23:33 +0000 Subject: [PATCH] allow multiple attachment / insertion in the compose window --- ChangeLog.claws | 7 ++ src/compose.c | 38 +++++++---- src/filesel.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++-- src/filesel.h | 2 + 4 files changed, 201 insertions(+), 15 deletions(-) diff --git a/ChangeLog.claws b/ChangeLog.claws index 09b58403f..ff61b1b14 100644 --- a/ChangeLog.claws +++ b/ChangeLog.claws @@ -1,3 +1,10 @@ +2001-06-30 [alfons] + + * src/filesel.[ch] + * src/compose.c + allow inserting / attaching multiple files in + the composer window + 2001-06-30 [paul] * src/codeconv.c diff --git a/src/compose.c b/src/compose.c index eeeea4803..079c3c72b 100644 --- a/src/compose.c +++ b/src/compose.c @@ -3251,7 +3251,7 @@ static Compose *compose_create(PrefsAccount *account) #include "pixmaps/stock_mail_attach.xpm" #include "pixmaps/stock_mail_compose.xpm" #include "pixmaps/linewrap.xpm" -//#include "pixmaps/tb_mail_queue_send.xpm" +/*#include "pixmaps/tb_mail_queue_send.xpm"*/ #include "pixmaps/tb_address_book.xpm" #define CREATE_TOOLBAR_ICON(xpm_d) \ @@ -3294,7 +3294,7 @@ static void compose_toolbar_create(Compose *compose, GtkWidget *container) icon_wid, toolbar_send_cb, compose); CREATE_TOOLBAR_ICON(stock_mail_send_xpm); - //CREATE_TOOLBAR_ICON(tb_mail_queue_send_xpm); + /* CREATE_TOOLBAR_ICON(tb_mail_queue_send_xpm); */ sendl_btn = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), _("Send later"), _("Put into queue folder and send later"), @@ -4316,7 +4316,7 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget) g_free(tmp); - //folderview_scan_folder_a(DRAFT_DIR, TRUE); + /* folderview_scan_folder_a(DRAFT_DIR, TRUE); */ gtk_widget_destroy(compose->window); } @@ -4324,24 +4324,40 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget) static void compose_attach_cb(gpointer data, guint action, GtkWidget *widget) { Compose *compose = (Compose *)data; - gchar *file; + GList *file_list; + + file_list = filesel_select_multiple_files(_("Select file"), NULL); - file = filesel_select_file(_("Select file"), NULL); + if (file_list) { + GList *tmp; - if (file) - compose_attach_append(compose, file, MIME_UNKNOWN); + for ( tmp = file_list; tmp; tmp = tmp->next) { + gchar *file = (gchar *) tmp->data; + compose_attach_append(compose, file, MIME_UNKNOWN); + g_free(file); + } + g_list_free(file_list); + } } static void compose_insert_file_cb(gpointer data, guint action, GtkWidget *widget) { Compose *compose = (Compose *)data; - gchar *file; + GList *file_list; - file = filesel_select_file(_("Select file"), NULL); + file_list = filesel_select_multiple_files(_("Select file"), NULL); - if (file) - compose_insert_file(compose, file); + if (file_list) { + GList *tmp; + + for ( tmp = file_list; tmp; tmp = tmp->next) { + gchar *file = (gchar *) tmp->data; + compose_insert_file(compose, file); + g_free(file); + } + g_list_free(file_list); + } } static gint compose_delete_cb(GtkWidget *widget, GdkEventAny *event, diff --git a/src/filesel.c b/src/filesel.c index 4c61bc042..c7cf96a9d 100644 --- a/src/filesel.c +++ b/src/filesel.c @@ -1,6 +1,6 @@ /* * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999,2000 Hiroyuki Yamamoto + * Copyright (C) 1999-2001 Hiroyuki Yamamoto * * 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 @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "main.h" #include "filesel.h" @@ -32,18 +34,26 @@ static GtkWidget *filesel; static gboolean filesel_ack; -static void filesel_create(const gchar *title); +static void filesel_create(const gchar *title, gboolean multiple_files); static void filesel_ok_cb(GtkWidget *widget, gpointer data); static void filesel_cancel_cb(GtkWidget *widget, gpointer data); static gint delete_event(GtkWidget *widget, GdkEventAny *event, gpointer data); static void key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data); +static void filesel_file_list_select_row(GtkCList *clist, gint row, gint col, + GdkEventButton *event, gpointer userdata); + +static void filesel_dir_list_select_row(GtkCList *clist, gint row, gint col, + GdkEventButton *event, gpointer userdata); + +static GList *filesel_get_multiple_filenames(void); + gchar *filesel_select_file(const gchar *title, const gchar *file) { static gchar *filename = NULL; static gchar *cwd = NULL; - filesel_create(title); + filesel_create(title, FALSE); manage_window_set_transient(GTK_WINDOW(filesel)); @@ -88,7 +98,46 @@ gchar *filesel_select_file(const gchar *title, const gchar *file) return filename; } -static void filesel_create(const gchar *title) +GList *filesel_select_multiple_files(const gchar *title, const gchar *file) +{ + /* ALF - sorry for the exuberant code duping... need to + * be cleaned up. */ + static gchar *filename = NULL; + static gchar *cwd = NULL; + GList *list = NULL; + + filesel_create(title, TRUE); + + manage_window_set_transient(GTK_WINDOW(filesel)); + + if (filename) { + g_free(filename); + filename = NULL; + } + + if (!cwd) + cwd = g_strconcat(startup_dir, G_DIR_SEPARATOR_S, NULL); + + gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel), cwd); + + if (file) + gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel), + file); + gtk_widget_show(filesel); + + gtk_main(); + + if (filesel_ack) + list = filesel_get_multiple_filenames(); + + manage_window_focus_out(filesel, NULL, NULL); + gtk_widget_destroy(filesel); + GTK_EVENTS_FLUSH(); + + return list; +} + +static void filesel_create(const gchar *title, gboolean multiple_files) { filesel = gtk_file_selection_new(title); gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button), @@ -108,6 +157,25 @@ static void filesel_create(const gchar *title) GTK_SIGNAL_FUNC(manage_window_focus_out), NULL); gtk_window_set_modal(GTK_WINDOW(filesel), TRUE); + + if (multiple_files) { + gtk_clist_set_selection_mode + (GTK_CLIST(GTK_FILE_SELECTION(filesel)->file_list), + GTK_SELECTION_MULTIPLE); + gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->file_list), + "select_row", + GTK_SIGNAL_FUNC(filesel_file_list_select_row), + NULL); + gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->file_list), + "unselect_row", + GTK_SIGNAL_FUNC(filesel_file_list_select_row), + NULL); + gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->dir_list), + "select_row", + GTK_SIGNAL_FUNC(filesel_dir_list_select_row), + NULL); + } + } static void filesel_ok_cb(GtkWidget *widget, gpointer data) @@ -133,3 +201,96 @@ static void key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data) if (event && event->keyval == GDK_Escape) filesel_cancel_cb(NULL, NULL); } + +/* handle both "select_row" and "unselect_row". note that we're using the + * entry box to put there the selected file names in. we're not using these + * entry box to get the selected file names. instead we use the clist selection. + * the entry box is used only to retrieve dir name. */ +static void filesel_file_list_select_row(GtkCList *clist, gint row, gint col, + GdkEventButton *event, gpointer userdata) +{ + /* simple implementation in which we clear the file entry and refill it */ + GList *list = clist->selection; + GtkEntry *entry = GTK_ENTRY(GTK_FILE_SELECTION(filesel)->selection_entry); + + gtk_editable_delete_text(GTK_EDITABLE(entry), 0, -1); + +#define INVALID_FILENAME_CHARS " " + for (; list; list = list->next) { + gint row = GPOINTER_TO_INT(list->data); + gchar *text = NULL, *tmp; + + if (!gtk_clist_get_text(clist, row, 0, &text)) + break; + + /* NOTE: quick glance in source code of GtkCList + * reveals we should not free the returned 'text' */ + + tmp = g_strconcat(text, " ", NULL); + text = tmp; + gtk_entry_append_text(entry, text); + g_free(text); + } +#undef INVALID_FILENAME_CHARS +} + +static void filesel_dir_list_select_row(GtkCList *clist, gint row, gint col, + GdkEventButton *event, gpointer userdata) +{ + GtkEntry *entry = GTK_ENTRY(GTK_FILE_SELECTION(filesel)->selection_entry); + GtkCList *file_list = GTK_CLIST(GTK_FILE_SELECTION(filesel)->file_list); + + /* if dir list is selected we clean everything */ + gtk_editable_delete_text(GTK_EDITABLE(entry), 0, -1); + gtk_clist_unselect_all(file_list); +} + +static GList *filesel_get_multiple_filenames(void) +{ + /* as noted before we are not using the entry text when selecting + * multiple files. to much hassle to parse out invalid chars (chars + * that need to be escaped). instead we use the file_list. the + * entry is only useful for extracting the current directory. */ + GtkCList *file_list = GTK_CLIST(GTK_FILE_SELECTION(filesel)->file_list); + GtkEntry *file_entry = GTK_ENTRY(GTK_FILE_SELECTION(filesel)->selection_entry); + GList *list = NULL, *sel_list; + gchar *cwd, *tmp; + gboolean separator; + + g_return_val_if_fail(file_list->selection != NULL, NULL); + + tmp = gtk_file_selection_get_filename(GTK_FILE_SELECTION(filesel)); + tmp = g_strdup(tmp); + cwd = g_dirname(tmp); + g_free(tmp); + g_return_val_if_fail(cwd != NULL, NULL); + + /* only quick way to check the end of a multi byte string for our + * separator... */ + g_strreverse(cwd); + separator = 0 == g_strncasecmp(cwd, G_DIR_SEPARATOR_S, strlen(G_DIR_SEPARATOR_S)) + ? TRUE : FALSE; + g_strreverse(cwd); + + /* fetch the selected file names */ + for (sel_list = file_list->selection; sel_list; sel_list = sel_list->next) { + gint sel = GPOINTER_TO_INT(sel_list->data); + gchar *sel_text = NULL; + gchar *fname = NULL; + + gtk_clist_get_text(file_list, sel, 0, &sel_text); + if (!sel_text) continue; + sel_text = g_strdup(sel_text); + + if (separator) + fname = g_strconcat(cwd, sel_text, NULL); + else + fname = g_strconcat(cwd, G_DIR_SEPARATOR_S, sel_text, NULL); + + list = g_list_append(list, fname); + g_free(sel_text); + } + + return list; +} + diff --git a/src/filesel.h b/src/filesel.h index e40185852..4ffc27848 100644 --- a/src/filesel.h +++ b/src/filesel.h @@ -24,4 +24,6 @@ gchar *filesel_select_file(const gchar *title, const gchar *file); +GList *filesel_select_multiple_files(const gchar *title, const gchar *file); + #endif /* __FILESEL_H__ */ -- 2.25.1