diff options
-rw-r--r-- | mail/ChangeLog | 41 | ||||
-rw-r--r-- | mail/folder-browser.c | 162 | ||||
-rw-r--r-- | mail/folder-browser.h | 5 | ||||
-rw-r--r-- | mail/mail-callbacks.c | 83 | ||||
-rw-r--r-- | mail/mail-vfolder.c | 5 | ||||
-rw-r--r-- | mail/mail-vfolder.h | 2 |
6 files changed, 219 insertions, 79 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog index 9373a4c68c..96cc14e7d9 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,5 +1,46 @@ 2002-03-26 Not Zed <NotZed@Ximian.com> + * mail-callbacks.c (addrbook_sender): Changed to get the address + from the messageinfo of the current selected message rather than + from the current_message. + (requeue_mail_reply): Only re-queue if we got a message, could + potentially cause an infinite loop trying to get a message it + can't. + (reply_to_sender, reply_to_list, reply_to_all): Always pass NULL + as the msg to mail_replay, this forces mail_reply to always load + the message anew. Fixes FIXME's and popup behaviour. Basically + this and stuff below fixes #8542. Its probably not the nicest + way, but it works. + (mark_as_important): Use the flags properly, we can set all flags + to any combination of on or off as we want, so we just need to + call set_flags once, thats why its set flags and not set_option. + (toggle_flags): Fixed the logic here also, so we dont have to call + set_message_flags more than once, and also implement a true toggle + for any number of simultaneous flags (whilst simplifying code). + + * mail-vfolder.c (vfolder_gui_add_from_mlist): Removed the 'msg' + parameter, its not used, fixed callers. + + * folder-browser.c (on_right_click): Lookup the mlist from + messageinfo, and change the 'no selected' logic slightly, fixes + most of #8542. + (filter_data_free): Free filter data struct. + (vfolder_type_got_message): Actually create vfolder once we have + the message we need to use for it. Code could probably be changed + to use messageinfo instead. + (vfolder_type_uid): Lookup a message based on uid, and use that to + create a vfolder based on type. + (vfolder_subject_uid, vfolder_sender_uid, vfolder_receipient_uid, + vfolder_mlist_uid): Callbacks for the popup menu, used to create + rules based on the uid rather than the message, which it loads as + required. + (filter_type_got_message, filter_*_uid): Similar to vfolder + stuff above. + (filter_menu[]): Changed callbacks to popup specific ones, not + folderbrowser specific ones used by bonobo. + (on_right_click): Initialise callback data for the filter submenu + so it can look up messages for callback implementation. + * local-config.glade: New version from anna, with fixed widget names. diff --git a/mail/folder-browser.c b/mail/folder-browser.c index 24f3b12a8c..afa530b11a 100644 --- a/mail/folder-browser.c +++ b/mail/folder-browser.c @@ -1273,6 +1273,7 @@ folder_browser_charset_changed (BonoboUIComponent *component, } } +/* external api to vfolder/filter on X, based on current message */ void vfolder_subject (GtkWidget *w, FolderBrowser *fb) { @@ -1301,7 +1302,7 @@ vfolder_mlist (GtkWidget *w, FolderBrowser *fb) name = header_raw_check_mailing_list(&((CamelMimePart *)fb->mail_display->current_message)->headers); if (name) { g_strstrip (name); - vfolder_gui_add_from_mlist(fb->mail_display->current_message, name, fb->uri); + vfolder_gui_add_from_mlist(name, fb->uri); g_free(name); } } @@ -1338,6 +1339,84 @@ filter_mlist (GtkWidget *w, FolderBrowser *fb) } } +/* ************************************************************ */ + +/* popup api to vfolder/filter on X, based on current selection */ +struct _filter_data { + CamelFolder *folder; + char *uid; + int type; + char *uri; + char *mlist; +}; + +static void +filter_data_free(struct _filter_data *fdata) +{ + g_free(fdata->uid); + g_free(fdata->uri); + if (fdata->folder) + camel_object_unref((CamelObject *)fdata->folder); + g_free(fdata->mlist); + g_free(fdata); +} + +static void +vfolder_type_got_message(CamelFolder *folder, char *uid, CamelMimeMessage *msg, void *d) +{ + struct _filter_data *data = d; + + if (msg) + vfolder_gui_add_from_message(msg, data->type, data->uri); + + filter_data_free(data); +} + +static void +vfolder_type_uid(struct _filter_data *fdata, int type) +{ + struct _filter_data *data; + + /* sigh, we need to copy this because the menu will free the one we got passed in */ + data = g_malloc0(sizeof(*data)); + data->type = type; + data->uri = fdata->uri; + fdata->uri = NULL; + mail_get_message(fdata->folder, fdata->uid, vfolder_type_got_message, data, mail_thread_new); +} + +static void vfolder_subject_uid (GtkWidget *w, struct _filter_data *fdata) { vfolder_type_uid(fdata, AUTO_SUBJECT); } +static void vfolder_sender_uid(GtkWidget *w, struct _filter_data *fdata) { vfolder_type_uid(fdata, AUTO_FROM); } +static void vfolder_recipient_uid(GtkWidget *w, struct _filter_data *fdata) { vfolder_type_uid(fdata, AUTO_TO); } +static void vfolder_mlist_uid(GtkWidget *w, struct _filter_data *fdata) { vfolder_gui_add_from_mlist(fdata->mlist, fdata->uri); } + +static void +filter_type_got_message(CamelFolder *folder, char *uid, CamelMimeMessage *msg, void *d) +{ + struct _filter_data *data = d; + + if (msg) + filter_gui_add_from_message(msg, data->type); + + filter_data_free(data); +} + +static void +filter_type_uid(struct _filter_data *fdata, int type) +{ + struct _filter_data *data; + + /* sigh, we need to copy this because the menu will free the one we got passed in */ + data = g_malloc0(sizeof(*data)); + data->type = type; + mail_get_message(fdata->folder, fdata->uid, filter_type_got_message, data, mail_thread_new); +} + +static void filter_subject_uid (GtkWidget *w, struct _filter_data *fdata) { filter_type_uid(fdata, AUTO_SUBJECT); } +static void filter_sender_uid(GtkWidget *w, struct _filter_data *fdata) { filter_type_uid(fdata, AUTO_FROM); } +static void filter_recipient_uid(GtkWidget *w, struct _filter_data *fdata) { filter_type_uid(fdata, AUTO_TO); } +static void filter_mlist_uid(GtkWidget *w, struct _filter_data *fdata) { filter_gui_add_from_mlist(fdata->mlist); } + void hide_none(GtkWidget *w, FolderBrowser *fb) { @@ -1493,17 +1572,17 @@ enum { #define MLIST_FILTER (8) static EPopupMenu filter_menu[] = { - { N_("VFolder on _Subject"), NULL, GTK_SIGNAL_FUNC (vfolder_subject), NULL, NULL, SELECTION_SET }, - { N_("VFolder on Se_nder"), NULL, GTK_SIGNAL_FUNC (vfolder_sender), NULL, NULL, SELECTION_SET }, - { N_("VFolder on _Recipients"), NULL, GTK_SIGNAL_FUNC (vfolder_recipient), NULL, NULL, SELECTION_SET }, - { N_("VFolder on Mailing _List"), NULL, GTK_SIGNAL_FUNC (vfolder_mlist), NULL, NULL, SELECTION_SET | IS_MAILING_LIST }, + { N_("VFolder on _Subject"), NULL, GTK_SIGNAL_FUNC (vfolder_subject_uid), NULL, NULL, SELECTION_SET }, + { N_("VFolder on Se_nder"), NULL, GTK_SIGNAL_FUNC (vfolder_sender_uid), NULL, NULL, SELECTION_SET }, + { N_("VFolder on _Recipients"), NULL, GTK_SIGNAL_FUNC (vfolder_recipient_uid), NULL, NULL, SELECTION_SET }, + { N_("VFolder on Mailing _List"), NULL, GTK_SIGNAL_FUNC (vfolder_mlist_uid), NULL, NULL, SELECTION_SET | IS_MAILING_LIST }, E_POPUP_SEPARATOR, - { N_("Filter on Sub_ject"), NULL, GTK_SIGNAL_FUNC (filter_subject), NULL, NULL, SELECTION_SET }, - { N_("Filter on Sen_der"), NULL, GTK_SIGNAL_FUNC (filter_sender), NULL, NULL, SELECTION_SET }, - { N_("Filter on Re_cipients"), NULL, GTK_SIGNAL_FUNC (filter_recipient), NULL, NULL, SELECTION_SET }, - { N_("Filter on _Mailing List"), NULL, GTK_SIGNAL_FUNC (filter_mlist), NULL, NULL, SELECTION_SET | IS_MAILING_LIST }, + { N_("Filter on Sub_ject"), NULL, GTK_SIGNAL_FUNC (filter_subject_uid), NULL, NULL, SELECTION_SET }, + { N_("Filter on Sen_der"), NULL, GTK_SIGNAL_FUNC (filter_sender_uid), NULL, NULL, SELECTION_SET }, + { N_("Filter on Re_cipients"), NULL, GTK_SIGNAL_FUNC (filter_recipient_uid), NULL, NULL, SELECTION_SET }, + { N_("Filter on _Mailing List"), NULL, GTK_SIGNAL_FUNC (filter_mlist_uid), NULL, NULL, SELECTION_SET | IS_MAILING_LIST }, E_POPUP_TERMINATOR }; @@ -1683,33 +1762,15 @@ on_right_click (ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event int i; char *mlist = NULL; GtkMenu *menu; + struct _filter_data *fdata = NULL; if (fb->folder != sent_folder) { enable_mask |= CAN_RESEND; hide_mask |= CAN_RESEND; } - - if (fb->mail_display->current_message == NULL) { - enable_mask |= SELECTION_SET; - } else { - char *mname, *p, c, *o; - - mname = header_raw_check_mailing_list (&((CamelMimePart *)fb->mail_display->current_message)->headers); - /* Escape the mailing list name before showing it */ - if (mname) { - mlist = alloca (strlen (mname)+2); - p = mname; - o = mlist; - while ((c = *p++)) { - if (c == '_') - *o++ = '_'; - *o++ = c; - } - *o = 0; - g_free (mname); - } - } - + + enable_mask |= SELECTION_SET; + /* get a list of uids */ uids = g_ptr_array_new (); message_list_foreach (fb->message_list, enumerate_msg, uids); @@ -1731,6 +1792,35 @@ on_right_click (ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event info = camel_folder_get_message_info (fb->folder, uids->pdata[i]); if (info == NULL) continue; + + if (i == 0 && uids->len == 1) { + const char *mname, *p; + char c, *o; + + /* used by filter/vfolder from X callbacks */ + fdata = g_malloc0(sizeof(*fdata)); + fdata->uid = g_strdup(uids->pdata[i]); + fdata->uri = g_strdup(fb->uri); + fdata->folder = fb->folder; + camel_object_ref((CamelObject *)fdata->folder); + + enable_mask &= ~SELECTION_SET; + mname = camel_message_info_mlist(info); + if (mname && mname[0]) { + fdata->mlist = g_strdup(mname); + + /* Escape the mailing list name before showing it */ + mlist = alloca (strlen (mname)+2); + p = mname; + o = mlist; + while ((c = *p++)) { + if (c == '_') + *o++ = '_'; + *o++ = c; + } + *o = 0; + } + } if (info->flags & CAMEL_MESSAGE_SEEN) have_seen = TRUE; @@ -1874,12 +1964,16 @@ on_right_click (ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event } setup_popup_icons (); + + for (i=0;i<sizeof(filter_menu)/sizeof(filter_menu[0]);i++) + filter_menu[i].closure = fdata; menu = e_popup_menu_create (context_menu, enable_mask, hide_mask, fb); e_auto_kill_popup_menu_on_hide (menu); - gtk_object_set_data_full (GTK_OBJECT (menu), "colour_closures", - (GtkDestroyNotify) closures, colour_closures_free); + gtk_object_set_data_full (GTK_OBJECT (menu), "colour_closures", closures, (GtkDestroyNotify)colour_closures_free); + if (fdata) + gtk_object_set_data_full(GTK_OBJECT(menu), "filter_data", fdata, (GtkDestroyNotify)filter_data_free); if (event->type == GDK_KEY_PRESS) { struct cmpf_data closure; @@ -1901,7 +1995,7 @@ on_right_click (ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event for (i = 0; i < 5; i++) { g_free (label_menu[i + 2].name); } - + return TRUE; } diff --git a/mail/folder-browser.h b/mail/folder-browser.h index 5b21efc036..464f1414f6 100644 --- a/mail/folder-browser.h +++ b/mail/folder-browser.h @@ -57,7 +57,7 @@ struct _FolderBrowser { char *new_uid; /* place to save the next uid during idle timeout */ char *loaded_uid; /* what we have loaded */ guint loading_id, seen_id; - + /* a folder we are expunging, dont use other than to compare the pointer value */ CamelFolder *expunging; @@ -89,6 +89,9 @@ struct _FolderBrowser { struct _MailAsyncEvent *async_event; int get_id; /* for getting folder op */ + + /* info used by popup for filter/vfolder */ + struct _popup_filter_data *popup; }; typedef struct { diff --git a/mail/mail-callbacks.c b/mail/mail-callbacks.c index 1dfffd2fbb..736002c915 100644 --- a/mail/mail-callbacks.c +++ b/mail/mail-callbacks.c @@ -1029,7 +1029,8 @@ requeue_mail_reply (CamelFolder *folder, char *uid, CamelMimeMessage *msg, void { int mode = GPOINTER_TO_INT (data); - mail_reply (folder, msg, uid, mode); + if (msg != NULL) + mail_reply (folder, msg, uid, mode); } void @@ -1076,13 +1077,10 @@ reply_to_sender (GtkWidget *widget, gpointer user_data) { FolderBrowser *fb = FOLDER_BROWSER (user_data); - /* FIXME: make this always load the message based on cursor */ - if (FOLDER_BROWSER_IS_DESTROYED (fb) || !check_send_configuration (fb)) return; - mail_reply (fb->folder, fb->mail_display->current_message, - fb->message_list->cursor_uid, REPLY_SENDER); + mail_reply(fb->folder, NULL, fb->message_list->cursor_uid, REPLY_SENDER); } void @@ -1093,10 +1091,7 @@ reply_to_list (GtkWidget *widget, gpointer user_data) if (FOLDER_BROWSER_IS_DESTROYED (fb) || !check_send_configuration (fb)) return; - /* FIXME: make this always load the message based on cursor */ - - mail_reply (fb->folder, fb->mail_display->current_message, - fb->message_list->cursor_uid, REPLY_LIST); + mail_reply (fb->folder, NULL, fb->message_list->cursor_uid, REPLY_LIST); } void @@ -1107,10 +1102,7 @@ reply_to_all (GtkWidget *widget, gpointer user_data) if (FOLDER_BROWSER_IS_DESTROYED (fb) || !check_send_configuration (fb)) return; - /* FIXME: make this always load the message based on cursor */ - - mail_reply (fb->folder, fb->mail_display->current_message, - fb->message_list->cursor_uid, REPLY_ALL); + mail_reply(fb->folder, NULL, fb->message_list->cursor_uid, REPLY_ALL); } void @@ -1502,27 +1494,26 @@ void addrbook_sender (GtkWidget *widget, gpointer user_data) { FolderBrowser *fb = FOLDER_BROWSER (user_data); - CamelMimeMessage *msg = NULL; - const CamelInternetAddress *addr; - gchar *addr_str; + const char *addr_str; + CamelMessageInfo *info; GtkWidget *win; GtkWidget *control; GtkWidget *socket; - - /* FIXME: make this use the cursor message id */ - + GPtrArray *uids; + int i; + if (FOLDER_BROWSER_IS_DESTROYED (fb)) return; - - msg = fb->mail_display->current_message; - if (msg == NULL) - return; - - addr = camel_mime_message_get_from (msg); - if (addr == NULL) - return; - - addr_str = camel_address_format (CAMEL_ADDRESS (addr)); + + uids = g_ptr_array_new(); + message_list_foreach(fb->message_list, enumerate_msg, uids); + if (uids->len != 1) + goto done; + + info = camel_folder_get_message_info(fb->folder, uids->pdata[0]); + if (info == NULL + || (addr_str = camel_message_info_from(info)) == NULL) + goto done; win = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (win), _("Sender")); @@ -1544,6 +1535,11 @@ addrbook_sender (GtkWidget *widget, gpointer user_data) gtk_container_add (GTK_CONTAINER (win), control); gtk_widget_show_all (win); + +done: + for (i=0; i < uids->len; i++) + g_free(uids->pdata[i]); + g_ptr_array_free(uids, TRUE); } void @@ -1712,18 +1708,24 @@ toggle_flags (FolderBrowser *fb, guint32 mask) message_list_foreach (fb->message_list, enumerate_msg, uids); camel_folder_freeze (fb->folder); for (i = 0; i < uids->len; i++) { - int flags; - - flags = camel_folder_get_message_flags (fb->folder, uids->pdata[i]); + guint32 flags; - if (flags & mask) - camel_folder_set_message_flags (fb->folder, uids->pdata[i], mask, 0); - else { - if ((mask & CAMEL_MESSAGE_FLAGGED) && (flags & CAMEL_MESSAGE_DELETED)) - camel_folder_set_message_flags (fb->folder, uids->pdata[i], CAMEL_MESSAGE_DELETED, 0); - camel_folder_set_message_flags (fb->folder, uids->pdata[i], mask, mask); + flags = ~(camel_folder_get_message_flags (fb->folder, uids->pdata[i])); + + /* if we're flagging a message important, always undelete it too */ + if (mask & flags & CAMEL_MESSAGE_FLAGGED) { + flags &= ~CAMEL_MESSAGE_DELETED; + mask |= CAMEL_MESSAGE_DELETED; } - + + /* if we're flagging a message deleted, always mark it seen too */ + if (mask & flags & CAMEL_MESSAGE_DELETED) { + flags |= CAMEL_MESSAGE_SEEN; + mask |= CAMEL_MESSAGE_SEEN; + } + + camel_folder_set_message_flags (fb->folder, uids->pdata[i], mask, flags); + g_free (uids->pdata[i]); } camel_folder_thaw (fb->folder); @@ -1777,8 +1779,7 @@ mark_all_as_seen (BonoboUIComponent *uih, void *user_data, const char *path) void mark_as_important (BonoboUIComponent *uih, void *user_data, const char *path) { - flag_messages (FOLDER_BROWSER (user_data), CAMEL_MESSAGE_DELETED, 0); - flag_messages (FOLDER_BROWSER (user_data), CAMEL_MESSAGE_FLAGGED, CAMEL_MESSAGE_FLAGGED); + flag_messages (FOLDER_BROWSER (user_data), CAMEL_MESSAGE_FLAGGED|CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_FLAGGED); } void diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c index 44d0556fee..0c2ee4e2f7 100644 --- a/mail/mail-vfolder.c +++ b/mail/mail-vfolder.c @@ -919,11 +919,12 @@ vfolder_gui_add_from_message(CamelMimeMessage *msg, int flags, const char *sourc } void -vfolder_gui_add_from_mlist(CamelMimeMessage *msg, const char *mlist, const char *source) +vfolder_gui_add_from_mlist(const char *mlist, const char *source) { VfolderRule *rule; - g_return_if_fail (msg != NULL); + g_return_if_fail (mlist != NULL); + g_return_if_fail (source != NULL); rule = (VfolderRule*)vfolder_rule_from_mlist(context, mlist, source); vfolder_gui_add_rule(rule); diff --git a/mail/mail-vfolder.h b/mail/mail-vfolder.h index 9561185c4a..6de0ff52b6 100644 --- a/mail/mail-vfolder.h +++ b/mail/mail-vfolder.h @@ -19,7 +19,7 @@ FilterPart *vfolder_create_part (const char *name); FilterRule *vfolder_clone_rule (FilterRule *in); void vfolder_gui_add_rule (VfolderRule *rule); void vfolder_gui_add_from_message (CamelMimeMessage *msg, int flags, const char *source); -void vfolder_gui_add_from_mlist (CamelMimeMessage *msg, const char *mlist, const char *source); +void vfolder_gui_add_from_mlist (const char *mlist, const char *source); /* add a uri that is now (un)available to vfolders in a transient manner */ void mail_vfolder_add_uri(CamelStore *store, const char *uri, int remove); |