Am 28.08.07 21:39 schrieb(en) Albrecht Dreß:
I am using this patch here, and could re-post it...
... and it seems 2b limited to one single source file. The gui clearly needs some polish, but would this meets your intentions?
Cheers, Albrecht. --Albrecht Dreß - Johanna-Kirchner-Straße 13 - D-53123 Bonn (Germany)
Phone (+49) 228 6199571 - mailto:albrecht dress arcor de GnuPG public key: http://www.mynetcologne.de/~nc-dreszal/pubkey.asc
Index: src/sendmsg-window.c =================================================================== --- src/sendmsg-window.c (Revision 7684) +++ src/sendmsg-window.c (Arbeitskopie) @@ -54,6 +54,7 @@ #include "libbalsa.h" #include "misc.h" #include "send.h" +#include "html.h" #include "balsa-app.h" #include "balsa-message.h" @@ -2782,7 +2783,6 @@ g_free(sstr); } - /* create_info_pane creates upper panel with the message headers: From, To, ... and returns it. @@ -3277,6 +3277,291 @@ return subject; } +/* --- stuff for collecting parts for a reply --- */ + +static GList * +scan_bodies(GList * list, LibBalsaMessageBody * body, gboolean ignore_html, + gboolean container_mp_alt) +{ + gchar * mime_type; + + while (body) { + switch (libbalsa_message_body_type(body)) { + case LIBBALSA_MESSAGE_BODY_TYPE_TEXT: + { + gchar *mime_type; + LibBalsaHTMLType html_type; + + mime_type = libbalsa_message_body_get_mime_type(body); + html_type = libbalsa_html_type(mime_type); + g_free(mime_type); + + /* On a multipart/alternative, ignore_html defines if html or + * non-html parts will be added. Eject from the container when + * the first part has been found. + * Otherwise, select all text parts. */ + if (container_mp_alt) { + if ((ignore_html && html_type == LIBBALSA_HTML_TYPE_NONE) || + (!ignore_html && html_type != LIBBALSA_HTML_TYPE_NONE)) { + list = g_list_append(list, body); + return list; + } + } else + list = g_list_append(list, body); + break; + } + + case LIBBALSA_MESSAGE_BODY_TYPE_MULTIPART: + case LIBBALSA_MESSAGE_BODY_TYPE_MESSAGE: + mime_type = libbalsa_message_body_get_mime_type(body); + list = scan_bodies(list, body->parts, ignore_html, + !g_ascii_strcasecmp(mime_type, "multipart/alternative")); + g_free(mime_type); + break; + + default: + break; + } + + body = body->next; + } + + return list; +} + +enum { + QUOTE_INCLUDE, + QUOTE_MIME_TYPE, + QUOTE_DISP_TYPE, + QUOTE_FILENAME, + QUOTE_BODY, + QOUTE_NUM_ELEMS +}; + +static void +list_add_quote_body(LibBalsaMessageBody * body, GtkListStore * store) +{ + GtkTreeIter iter; + gchar * mime_type = libbalsa_message_body_get_mime_type(body); + const gchar * disp_type; + static gboolean preselect; + + gtk_list_store_append(store, &iter); + if (body->mime_part) + disp_type = g_mime_part_get_content_disposition(GMIME_PART(body->mime_part)); + else + disp_type = NULL; + preselect = !disp_type || *disp_type == '\0' || + !g_ascii_strcasecmp(disp_type, "inline"); + gtk_list_store_set(store, &iter, + QUOTE_INCLUDE, preselect, + QUOTE_MIME_TYPE, mime_type, + QUOTE_DISP_TYPE, disp_type, + QUOTE_FILENAME, body->filename, + QUOTE_BODY, body, + -1); + g_free(mime_type); +} + +static void +cell_toggled_cb(GtkCellRendererToggle *cell, gchar *path_str, GtkTreeView *treeview) +{ + GtkTreeModel *model = NULL; + GtkTreePath *path; + GtkTreeIter iter; + gboolean active; + + g_return_if_fail (GTK_IS_TREE_VIEW (treeview)); + if (!(model = gtk_tree_view_get_model(treeview))) + return; + + path = gtk_tree_path_new_from_string(path_str); + if (!gtk_tree_model_get_iter(model, &iter, path)) + return; + gtk_tree_path_free(path); + + gtk_tree_model_get(GTK_TREE_MODEL (model), + &iter, + QUOTE_INCLUDE, &active, + -1); + gtk_list_store_set(GTK_LIST_STORE (model), + &iter, + QUOTE_INCLUDE, !active, + -1); +} + +static GList * +quote_parts_select_dlg(GList * body_list, GtkWindow * parent) +{ + GtkWidget *dialog; + GtkWidget *label; + GtkWidget *image; + GtkWidget *hbox; + GtkWidget *vbox; + GtkListStore *list_store; + GtkWidget *list_view; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + GList *result = NULL; + + dialog = gtk_dialog_new_with_buttons(_("Select parts for quotation"), + parent, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_OK, GTK_RESPONSE_OK, + NULL); + + label = gtk_label_new(_("Select the parts of the message which shall be quoted in the reply")); + gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); + gtk_label_set_selectable(GTK_LABEL(label), TRUE); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0); + + image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION, + GTK_ICON_SIZE_DIALOG); + gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.0); + + /* stolen form gtk/gtkmessagedialog.c */ + hbox = gtk_hbox_new (FALSE, 12); + vbox = gtk_vbox_new (FALSE, 12); + + gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, + FALSE, 0); + + gtk_container_set_border_width(GTK_CONTAINER(dialog), 5); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); + gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), 14); + + /* add the table */ + list_store = gtk_list_store_new(QOUTE_NUM_ELEMS, + G_TYPE_BOOLEAN, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER); + g_list_foreach(body_list, (GFunc) list_add_quote_body, list_store); + list_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store)); + renderer = gtk_cell_renderer_toggle_new(); + g_signal_connect(renderer, "toggled", G_CALLBACK(cell_toggled_cb), + list_view); + column = gtk_tree_view_column_new_with_attributes(_("Add"), + renderer, + "active", QUOTE_INCLUDE, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column); + column = gtk_tree_view_column_new_with_attributes(_("Type"), + gtk_cell_renderer_text_new(), + "text", QUOTE_MIME_TYPE, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column); + column = gtk_tree_view_column_new_with_attributes(_("Mode"), + gtk_cell_renderer_text_new(), + "text", QUOTE_DISP_TYPE, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column); + column = gtk_tree_view_column_new_with_attributes(_("File name"), + gtk_cell_renderer_text_new(), + "text", QUOTE_FILENAME, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column); + + /* add, show & run */ + gtk_box_pack_start(GTK_BOX(vbox), list_view, FALSE, FALSE, 0); + gtk_widget_show_all(hbox); + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) { + GtkTreeIter iter; + + /* build & return a new list with the selected parts */ + gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list_store), &iter); + do { + gboolean use_in_quote; + + gtk_tree_model_get(GTK_TREE_MODEL(list_store), + &iter, + QUOTE_INCLUDE, + &use_in_quote, + -1); + if (use_in_quote) { + LibBalsaMessageBody *this_body; + + gtk_tree_model_get(GTK_TREE_MODEL(list_store), + &iter, + QUOTE_BODY, + &this_body, + -1); + result = g_list_append(result, this_body); + } + } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store), &iter)); + } + + /* clean up */ + g_object_unref(G_OBJECT(list_store)); + gtk_widget_destroy(dialog); + return result; +} + +static GString * +collect_for_quote(LibBalsaMessageBody *root, gchar * reply_prefix_str, + gint llen, gboolean ignore_html, gboolean flow, + LibBalsaCharsetFunc charset_cb, gpointer charset_cb_data) +{ + GList *body_list; + LibBalsaMessage *message = root->message; + GString *q_body; + GList *quote_list; + + libbalsa_message_body_ref(message, FALSE, FALSE); + + /* scan the message and collect text parts which might be included + * in the reply, and if there is only one return this part */ + if (!(body_list = scan_bodies(NULL, root, ignore_html, FALSE))) { + libbalsa_message_body_unref(message); + return NULL; + } else if (body_list->next == NULL) { + q_body = process_mime_part(message, + (LibBalsaMessageBody *) body_list->data, + reply_prefix_str, llen, FALSE, flow, + charset_cb, charset_cb_data); + g_list_free(body_list); + libbalsa_message_body_unref(message); + return q_body; + } + + /* if there is more than one part ask the user if all should be added */ + quote_list = quote_parts_select_dlg(body_list, NULL); + g_list_free(body_list); + + /* quote selected parts... */ + q_body = NULL; + for (body_list = quote_list; body_list; body_list = g_list_next(body_list)) { + LibBalsaMessageBody *this_body = (LibBalsaMessageBody *) body_list->data; + GString * this_part; + + this_part = process_mime_part(message, this_body, + reply_prefix_str, llen, FALSE, flow, + charset_cb, charset_cb_data); + if (!q_body) + q_body = this_part; + else { + if (q_body->str[q_body->len - 1] != '\n') + g_string_append_c(q_body, '\n'); + if (this_body->filename) + g_string_append_printf(q_body, "\n------%s \"%s\"------\n", + _("quoted attachment"), this_body->filename); + else + g_string_append_printf(q_body, "\n------%s------\n", + _("quoted attachment")); + g_string_append(q_body, this_part->str); + g_string_free(this_part, TRUE); + } + } + + /* clean up */ + g_list_free(quote_list); + libbalsa_message_body_unref(message); + return q_body; +} + + /* quote_body ----------------------------------------------------------- quotes properly the body of the message. Use GString to optimize memory usage. @@ -3369,11 +3654,14 @@ str = g_strdup_printf(_("On %s, %s wrote:\n"), date, personStr); else str = g_strdup_printf(_("%s wrote:\n"), personStr); - body = content2reply(root, - qtype == QUOTE_ALL ? balsa_app.quote_str : NULL, - bsmsg->flow ? -1 : balsa_app.wraplength, - balsa_app.reply_strip_html, bsmsg->flow, - sw_charset_cb, bsmsg); + + /* scan the message and collect text parts which might be included + * in the reply */ + body = collect_for_quote(root, + qtype == QUOTE_ALL ? balsa_app.quote_str : NULL, + bsmsg->flow ? -1 : balsa_app.wraplength, + balsa_app.reply_strip_html, bsmsg->flow, + sw_charset_cb, bsmsg); if (body) { gchar *buf; @@ -5285,7 +5573,7 @@ gtk_box_pack_start (GTK_BOX (dialog_vbox), hbox, TRUE, TRUE, 0); gtk_container_set_border_width (GTK_CONTAINER (hbox), 6); - image = gtk_image_new_from_stock ("gtk-dialog-question", GTK_ICON_SIZE_DIALOG); + image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG); gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0); gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0); @@ -5316,7 +5604,7 @@ dialog_action_area = GTK_DIALOG (no_subj_dialog)->action_area; gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area), GTK_BUTTONBOX_END); - cnclbutton = gtk_button_new_from_stock ("gtk-cancel"); + cnclbutton = gtk_button_new_from_stock (GTK_STOCK_CANCEL); gtk_dialog_add_action_widget (GTK_DIALOG (no_subj_dialog), cnclbutton, GTK_RESPONSE_CANCEL); GTK_WIDGET_SET_FLAGS (cnclbutton, GTK_CAN_DEFAULT); @@ -5332,7 +5620,7 @@ hbox = gtk_hbox_new (FALSE, 2); gtk_container_add (GTK_CONTAINER (alignment), hbox); - image = gtk_image_new_from_stock ("balsa_send", GTK_ICON_SIZE_BUTTON); + image = gtk_image_new_from_stock (BALSA_PIXMAP_SEND, GTK_ICON_SIZE_BUTTON); gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0); label = gtk_label_new_with_mnemonic (_("_Send"));
Attachment:
pgpYkieRPcTsH.pgp
Description: PGP signature