talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit 022540892042ca15e8c4c9a69111e1d2a5ed6113
parent 18d70d17c2d89b7c6f2f40a48e3bda14fbf97531
Author: Colin Leroy <colin@colino.net>
Date:   Mon, 30 Mar 2009 17:20:02 +0000

2009-03-30 [colin]	3.7.1cvs30

	* src/folder.c
	* src/folder.h
	* src/imap.c
	* src/mainwindow.c
	* src/mainwindow.h
	* src/prefs_account.c
	* src/prefs_account.h
	* src/summaryview.c
	* src/summaryview.h
		Fix bug 1866, 'Claws should make use of the IMAP 'deleted' flag'
		Add an option on the Receive page of IMAP account preferences:
		"Move deleted mails to trash and expunge immediately". This
		option defaults to TRUE to avoid changing the existing behaviour.
		Setting it to FALSE prevents automatic expunging.
		Also, add Tools/Expunge and View/Hide deleted messages menu items
		(View/Hide deleted message being a per-folder setting, and behaving,
		like View/Hide read messages).

Diffstat:
MChangeLog | 20++++++++++++++++++++
MPATCHSETS | 1+
Mconfigure.ac | 2+-
Msrc/folder.c | 41+++++++++++++++++++++++++++++++++++++----
Msrc/folder.h | 5+++++
Msrc/imap.c | 30+++++++++++++++++++-----------
Msrc/mainwindow.c | 29+++++++++++++++++++++++++++++
Msrc/mainwindow.h | 3++-
Msrc/prefs_account.c | 25+++++++++++++++++++++++--
Msrc/prefs_account.h | 1+
Msrc/summaryview.c | 330++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Msrc/summaryview.h | 3+++
12 files changed, 420 insertions(+), 70 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,23 @@ +2009-03-30 [colin] 3.7.1cvs30 + + * src/folder.c + * src/folder.h + * src/imap.c + * src/mainwindow.c + * src/mainwindow.h + * src/prefs_account.c + * src/prefs_account.h + * src/summaryview.c + * src/summaryview.h + Fix bug 1866, 'Claws should make use of the IMAP 'deleted' flag' + Add an option on the Receive page of IMAP account preferences: + "Move deleted mails to trash and expunge immediately". This + option defaults to TRUE to avoid changing the existing behaviour. + Setting it to FALSE prevents automatic expunging. + Also, add Tools/Expunge and View/Hide deleted messages menu items + (View/Hide deleted message being a per-folder setting, and behaving, + like View/Hide read messages). + 2009-03-30 [colin] 3.7.1cvs29 * src/imap.c diff --git a/PATCHSETS b/PATCHSETS @@ -3769,3 +3769,4 @@ ( cvs diff -u -r 1.179.2.244 -r 1.179.2.245 src/imap.c; ) > 3.7.1cvs27.patchset ( cvs diff -u -r 1.213.2.191 -r 1.213.2.192 src/folder.c; ) > 3.7.1cvs28.patchset ( cvs diff -u -r 1.179.2.245 -r 1.179.2.246 src/imap.c; ) > 3.7.1cvs29.patchset +( cvs diff -u -r 1.213.2.192 -r 1.213.2.193 src/folder.c; cvs diff -u -r 1.87.2.59 -r 1.87.2.60 src/folder.h; cvs diff -u -r 1.179.2.246 -r 1.179.2.247 src/imap.c; cvs diff -u -r 1.274.2.300 -r 1.274.2.301 src/mainwindow.c; cvs diff -u -r 1.39.2.55 -r 1.39.2.56 src/mainwindow.h; cvs diff -u -r 1.105.2.151 -r 1.105.2.152 src/prefs_account.c; cvs diff -u -r 1.49.2.42 -r 1.49.2.43 src/prefs_account.h; cvs diff -u -r 1.395.2.409 -r 1.395.2.410 src/summaryview.c; cvs diff -u -r 1.68.2.51 -r 1.68.2.52 src/summaryview.h; ) > 3.7.1cvs30.patchset diff --git a/configure.ac b/configure.ac @@ -11,7 +11,7 @@ MINOR_VERSION=7 MICRO_VERSION=1 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=29 +EXTRA_VERSION=30 EXTRA_RELEASE= EXTRA_GTK2_VERSION= diff --git a/src/folder.c b/src/folder.c @@ -570,6 +570,8 @@ void folder_item_set_xml(Folder *folder, FolderItem *item, XMLTag *tag) item->threaded = *attr->value == '1' ? TRUE : FALSE; else if (!strcmp(attr->name, "hidereadmsgs")) item->hide_read_msgs = *attr->value == '1' ? TRUE : FALSE; + else if (!strcmp(attr->name, "hidedelmsgs")) + item->hide_del_msgs = *attr->value == '1' ? TRUE : FALSE; else if (!strcmp(attr->name, "reqretrcpt")) item->ret_rcpt = *attr->value == '1' ? TRUE : FALSE; else if (!strcmp(attr->name, "sort_key")) { @@ -653,6 +655,7 @@ XMLTag *folder_item_get_xml(Folder *folder, FolderItem *item) xml_tag_add_attr(tag, xml_attr_new("thread_collapsed", item->thread_collapsed ? "1" : "0")); xml_tag_add_attr(tag, xml_attr_new("threaded", item->threaded ? "1" : "0")); xml_tag_add_attr(tag, xml_attr_new("hidereadmsgs", item->hide_read_msgs ? "1" : "0")); + xml_tag_add_attr(tag, xml_attr_new("hidedelmsgs", item->hide_del_msgs ? "1" : "0")); if (item->ret_rcpt) xml_tag_add_attr(tag, xml_attr_new("reqretrcpt", "1")); @@ -3154,6 +3157,7 @@ static FolderItem *folder_item_move_recursive(FolderItem *src, FolderItem *dest, new_item->threaded = src->threaded; new_item->ret_rcpt = src->ret_rcpt; new_item->hide_read_msgs = src->hide_read_msgs; + new_item->hide_del_msgs = src->hide_del_msgs; new_item->sort_key = src->sort_key; new_item->sort_type = src->sort_type; @@ -3398,7 +3402,9 @@ static gint do_copy_msgs(FolderItem *dest, GSList *msglist, gboolean remove_sour item->folder->klass->remove_msg(item->folder, msginfo->folder, msginfo->msgnum); - remove_msginfo_from_cache(item, msginfo); + if (!item->folder->account || item->folder->account->imap_use_trash) { + remove_msginfo_from_cache(item, msginfo); + } } } } @@ -3594,9 +3600,11 @@ gint folder_item_remove_msg(FolderItem *item, gint num) } ret = folder->klass->remove_msg(folder, item, num); - if (msginfo != NULL) { - remove_msginfo_from_cache(item, msginfo); - procmsg_msginfo_free(msginfo); + if (!item->folder->account || item->folder->account->imap_use_trash) { + if (msginfo != NULL) { + remove_msginfo_from_cache(item, msginfo); + procmsg_msginfo_free(msginfo); + } } return ret; @@ -3652,6 +3660,29 @@ gint folder_item_remove_msgs(FolderItem *item, GSList *msglist) return ret; } +gint folder_item_expunge(FolderItem *item) +{ + Folder *folder = item->folder; + gint result = 0; + if (folder == NULL) + return -1; + if (folder->klass->expunge) { + GSList *msglist = folder_item_get_msg_list(item); + GSList *cur; + result = folder->klass->expunge(folder, item); + if (result == 0) { + for (cur = msglist; cur; cur = cur->next) { + MsgInfo *msginfo = (MsgInfo *)cur->data; + if (MSG_IS_DELETED(msginfo->flags)) { + remove_msginfo_from_cache(item, msginfo); + } + } + } + procmsg_msg_list_free(msglist); + } + return result; +} + gint folder_item_remove_all_msg(FolderItem *item) { Folder *folder; @@ -4188,6 +4219,7 @@ static void folder_item_restore_persist_prefs(FolderItem *item, GHashTable *ppta item->threaded = pp->threaded; item->ret_rcpt = pp->ret_rcpt; item->hide_read_msgs = pp->hide_read_msgs; + item->hide_del_msgs = pp->hide_del_msgs; item->sort_key = pp->sort_key; item->sort_type = pp->sort_type; } @@ -4213,6 +4245,7 @@ static void folder_get_persist_prefs_recursive(GNode *node, GHashTable *pptable) pp->threaded = item->threaded; pp->ret_rcpt = item->ret_rcpt; pp->hide_read_msgs = item->hide_read_msgs; + pp->hide_del_msgs = item->hide_del_msgs; pp->sort_key = item->sort_key; pp->sort_type = item->sort_type; g_hash_table_insert(pptable, id, pp); diff --git a/src/folder.h b/src/folder.h @@ -521,6 +521,8 @@ struct _FolderClass FolderItem *item, MsgInfoList *msglist, GRelation *relation); + gint (*expunge) (Folder *folder, + FolderItem *item); /** * Remove all messages in a \ c FolderItem * @@ -669,6 +671,7 @@ struct _FolderItem guint hide_read_msgs : 1; /* hide read messages */ guint ret_rcpt : 1; /* return receipt */ guint search_match : 1; + guint hide_del_msgs : 1; /* hide deleted messages */ gint op_count; guint opened : 1; /* opened by summary view */ @@ -707,6 +710,7 @@ struct _PersistPrefs guint threaded : 1; guint hide_read_msgs : 1; /* CLAWS */ guint ret_rcpt : 1; /* CLAWS */ + guint hide_del_msgs : 1; /* CLAWS */ }; struct _FolderUpdateData @@ -856,6 +860,7 @@ gint folder_item_remove_msg (FolderItem *item, gint num); gint folder_item_remove_msgs (FolderItem *item, GSList *msglist); +gint folder_item_expunge (FolderItem *item); gint folder_item_remove_all_msg (FolderItem *item); void folder_item_change_msg_flags (FolderItem *item, MsgInfo *msginfo, diff --git a/src/imap.c b/src/imap.c @@ -229,6 +229,8 @@ static gint imap_remove_msgs (Folder *folder, FolderItem *dest, MsgInfoList *msglist, GRelation *relation); +static gint imap_expunge (Folder *folder, + FolderItem *dest); static gint imap_remove_all_msg (Folder *folder, FolderItem *item); @@ -382,7 +384,7 @@ static gint imap_cmd_store (IMAPSession *session, IMAPFlags flags, GSList *tags, int do_add); -static gint imap_cmd_expunge (IMAPSession *session); +static gint imap_cmd_expunge (IMAPSession *session, gboolean force); static void imap_path_separator_subst (gchar *str, gchar separator); @@ -476,6 +478,7 @@ FolderClass *imap_get_class(void) imap_class.copy_msgs = imap_copy_msgs; imap_class.remove_msg = imap_remove_msg; imap_class.remove_msgs = imap_remove_msgs; + imap_class.expunge = imap_expunge; imap_class.remove_all_msg = imap_remove_all_msg; imap_class.is_msg_changed = imap_is_msg_changed; imap_class.change_flags = imap_change_flags; @@ -1995,7 +1998,7 @@ static gint imap_do_remove_msgs(Folder *folder, FolderItem *dest, return ok; } } /* else we just need to expunge */ - ok = imap_cmd_expunge(session); + ok = imap_cmd_expunge(session, folder->account->imap_use_trash); if (ok != MAILIMAP_NO_ERROR) { log_warning(LOG_PROTOCOL, _("can't expunge\n")); g_free(destdir); @@ -3861,10 +3864,13 @@ static gint imap_cmd_store(IMAPSession *session, return MAILIMAP_NO_ERROR; } -static gint imap_cmd_expunge(IMAPSession *session) +static gint imap_cmd_expunge(IMAPSession *session, gboolean do_expunge) { int r; + if (!do_expunge) + return MAILIMAP_NO_ERROR; + if (prefs_common.work_offline && !inc_offline_should_override(FALSE, _("Claws Mail needs network access in order " @@ -3881,6 +3887,15 @@ static gint imap_cmd_expunge(IMAPSession *session) return MAILIMAP_NO_ERROR; } +gint imap_expunge(Folder *folder, FolderItem *item) +{ + IMAPSession *session = imap_session_get(folder); + if (session == NULL) + return -1; + + return imap_cmd_expunge(session, TRUE); +} + static void imap_path_separator_subst(gchar *str, gchar separator) { gchar *p; @@ -4471,15 +4486,8 @@ static gint imap_remove_msg(Folder *folder, FolderItem *item, gint uid) return ok; } - if (!session->uidplus) { - ok = imap_cmd_expunge(session); - } else { - gchar *uidstr; + ok = imap_cmd_expunge(session, folder->account->imap_use_trash); - uidstr = g_strdup_printf("%u", uid); - ok = imap_cmd_expunge(session); - g_free(uidstr); - } if (ok != MAILIMAP_NO_ERROR) { log_warning(LOG_PROTOCOL, _("can't expunge\n")); return ok; diff --git a/src/mainwindow.c b/src/mainwindow.c @@ -249,6 +249,8 @@ static void set_decode_cb (GtkAction *action, GtkRadioAction *current, gpointer static void hide_read_messages (GtkAction *action, gpointer data); +static void hide_del_messages (GtkAction *action, + gpointer data); static void thread_cb (GtkAction *action, gpointer data); @@ -278,6 +280,8 @@ static void process_cb (GtkAction *action, gpointer data); static void execute_summary_cb (GtkAction *action, gpointer data); +static void expunge_summary_cb (GtkAction *action, + gpointer data); static void update_summary_cb (GtkAction *action, gpointer data); @@ -697,6 +701,7 @@ static GtkActionEntry mainwin_entries[] = /* {"Tools/---", NULL, "---", NULL, NULL, NULL }, */ {"Tools/Execute", NULL, N_("E_xecute"), "X", NULL, G_CALLBACK(execute_summary_cb) }, + {"Tools/Expunge", NULL, N_("Exp_unge"), "<control>E", NULL, G_CALLBACK(expunge_summary_cb) }, #ifdef USE_GNUTLS /* {"Tools/---", NULL, "---", NULL, NULL, NULL }, */ {"Tools/SSLCertificates", NULL, N_("SSL cer_tificates"), NULL, NULL, G_CALLBACK(ssl_manager_open_cb) }, @@ -747,6 +752,7 @@ static GtkToggleActionEntry mainwin_toggle_entries[] = { {"View/ShowHide/ColumnHeaders", NULL, N_("Column headers"), NULL, NULL, G_CALLBACK(toggle_col_headers_cb) }, /* toggle */ {"View/ThreadView", NULL, N_("Th_read view"), "<control>T", NULL, G_CALLBACK(thread_cb) }, /* toggle */ {"View/HideReadMessages", NULL, N_("_Hide read messages"), NULL, NULL, G_CALLBACK(hide_read_messages) }, /* toggle */ + {"View/HideDelMessages", NULL, N_("Hide deleted messages"), NULL, NULL, G_CALLBACK(hide_del_messages) }, /* toggle */ #ifndef MAEMO {"View/FullScreen", NULL, N_("_Fullscreen"), "F11", NULL, G_CALLBACK(toggle_fullscreen_cb) }, /* toggle */ #endif @@ -1697,6 +1703,7 @@ MainWindow *main_window_create() MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/View", "ExpandThreads", "View/ExpandThreads", GTK_UI_MANAGER_MENUITEM) MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/View", "CollapseThreads", "View/CollapseThreads", GTK_UI_MANAGER_MENUITEM) MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/View", "HideReadMessages", "View/HideReadMessages", GTK_UI_MANAGER_MENUITEM) + MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/View", "HideDelMessages", "View/HideDelMessages", GTK_UI_MANAGER_MENUITEM) MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/View", "Separator3", "View/---", GTK_UI_MANAGER_SEPARATOR) MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/View", "Goto", "View/Goto", GTK_UI_MANAGER_MENU) @@ -1904,6 +1911,7 @@ MainWindow *main_window_create() MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/Tools", "Separator5", "Tools/---", GTK_UI_MANAGER_SEPARATOR) MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/Tools", "Execute", "Tools/Execute", GTK_UI_MANAGER_MENUITEM) + MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/Tools", "Expunge", "Tools/Expunge", GTK_UI_MANAGER_MENUITEM) #ifdef USE_GNUTLS MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/Tools", "Separator6", "Tools/---", GTK_UI_MANAGER_SEPARATOR) MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/Tools", "SSLCertificates", "Tools/SSLCertificates", GTK_UI_MANAGER_MENUITEM) @@ -3116,6 +3124,9 @@ SensitiveCond main_window_get_current_state(MainWindow *mainwin) if (imap_cancel_all_enabled()) state |= M_INC_ACTIVE; + if (mainwin->summaryview->deleted > 0) + state |= M_DELETED_EXISTS; + if (mainwin->summaryview->deleted > 0 || mainwin->summaryview->moved > 0 || mainwin->summaryview->copied > 0) @@ -3170,6 +3181,7 @@ void main_window_set_menu_sensitive(MainWindow *mainwin) {"Menu/View/ExpandThreads" , M_MSG_EXIST|M_SUMMARY_ISLIST}, {"Menu/View/CollapseThreads" , M_MSG_EXIST|M_SUMMARY_ISLIST}, {"Menu/View/HideReadMessages" , M_HIDE_READ_MSG|M_SUMMARY_ISLIST}, + {"Menu/View/HideDelMessages" , M_SUMMARY_ISLIST}, {"Menu/View/Goto/Prev" , M_MSG_EXIST}, {"Menu/View/Goto/Next" , M_MSG_EXIST}, {"Menu/View/Goto/PrevUnread" , M_MSG_EXIST}, @@ -3229,6 +3241,7 @@ void main_window_set_menu_sensitive(MainWindow *mainwin) {"Menu/Tools/ListUrls" , M_TARGET_EXIST}, {"Menu/Tools/Actions" , M_TARGET_EXIST|M_ACTIONS_EXIST}, {"Menu/Tools/Execute" , M_DELAY_EXEC}, + {"Menu/Tools/Expunge" , M_DELETED_EXISTS}, {"Menu/Tools/ForgetSessionPasswords" , M_SESSION_PASSWORDS}, {"Menu/Tools/DeleteDuplicates/SelFolder" , M_MSG_EXIST|M_ALLOW_DELETE}, @@ -4497,6 +4510,16 @@ static void hide_read_messages (GtkAction *action, gpointer data) summary_toggle_show_read_messages(mainwin->summaryview); } +static void hide_del_messages (GtkAction *action, gpointer data) +{ + MainWindow *mainwin = (MainWindow *)data; + GtkWidget *menuitem = gtk_ui_manager_get_widget(mainwin->ui_manager, "/Menu/View/HideDelMessages"); + if (!mainwin->summaryview->folder_item + || g_object_get_data(G_OBJECT(menuitem), "dont_toggle")) + return; + summary_toggle_show_del_messages(mainwin->summaryview); +} + static void thread_cb(GtkAction *action, gpointer data) { MainWindow *mainwin = (MainWindow *)data; @@ -4650,6 +4673,12 @@ static void execute_summary_cb(GtkAction *action, gpointer data) summary_execute(mainwin->summaryview); } +static void expunge_summary_cb(GtkAction *action, gpointer data) +{ + MainWindow *mainwin = (MainWindow *)data; + summary_expunge(mainwin->summaryview); +} + static void update_summary_cb(GtkAction *action, gpointer data) { MainWindow *mainwin = (MainWindow *)data; diff --git a/src/mainwindow.h b/src/mainwindow.h @@ -64,7 +64,8 @@ typedef enum M_IN_MSGLIST = 1 << 23, M_HAVE_MULTI_ACCOUNT = 1 << 24, M_FOLDER_SELECTED = 1 << 25, - M_SESSION_PASSWORDS = 1 << 26 + M_SESSION_PASSWORDS = 1 << 26, + M_DELETED_EXISTS = 1 << 27 } SensitiveCond; typedef enum diff --git a/src/prefs_account.c b/src/prefs_account.c @@ -148,6 +148,7 @@ typedef struct ReceivePage GtkWidget *imapdir_entry; GtkWidget *subsonly_checkbtn; GtkWidget *low_bandwidth_checkbtn; + GtkWidget *imap_use_trash_checkbtn; GtkWidget *frame_maxarticle; GtkWidget *maxarticle_label; @@ -490,6 +491,10 @@ static PrefParam receive_param[] = { &receive_page.low_bandwidth_checkbtn, prefs_set_data_from_toggle, prefs_set_toggle}, + {"imap_use_trash", "TRUE", &tmp_ac_prefs.imap_use_trash, P_BOOL, + &receive_page.imap_use_trash_checkbtn, + prefs_set_data_from_toggle, prefs_set_toggle}, + {NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL} }; @@ -1354,6 +1359,7 @@ static void receive_create_widget_func(PrefsPage * _page, GtkWidget *imapdir_entry; GtkWidget *subsonly_checkbtn; GtkWidget *low_bandwidth_checkbtn; + GtkWidget *imap_use_trash_checkbtn; GtkWidget *local_frame; GtkWidget *local_vbox; GtkWidget *local_hbox; @@ -1572,6 +1578,15 @@ static void receive_create_widget_func(PrefsPage * _page, CLAWS_SET_TIP(low_bandwidth_checkbtn, _("This mode uses less bandwidth, but can be slower with some servers.")); + hbox1 = gtk_hbox_new (FALSE, 8); + gtk_widget_show (hbox1); + gtk_box_pack_start (GTK_BOX (vbox2), hbox1, FALSE, FALSE, 4); + + PACK_CHECK_BUTTON (hbox1, imap_use_trash_checkbtn, + _("Move deleted mails to trash and expunge immediately")); + CLAWS_SET_TIP(imap_use_trash_checkbtn, + _("Moves deleted mails to trash instead of using the \\Deleted flag without expunging. ")); + PACK_CHECK_BUTTON (vbox1, filter_on_recv_checkbtn, _("Filter messages on receiving")); @@ -1603,9 +1618,10 @@ static void receive_create_widget_func(PrefsPage * _page, page->imap_auth_type_optmenu = optmenu; page->imapdir_label = imapdir_label; - page->imapdir_entry = imapdir_entry; + page->imapdir_entry = imapdir_entry; page->subsonly_checkbtn = subsonly_checkbtn; - page->low_bandwidth_checkbtn = low_bandwidth_checkbtn; + page->low_bandwidth_checkbtn = low_bandwidth_checkbtn; + page->imap_use_trash_checkbtn = imap_use_trash_checkbtn; page->local_frame = local_frame; page->local_inbox_label = local_inbox_label; page->local_inbox_entry = local_inbox_entry; @@ -4073,6 +4089,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data) gtk_widget_hide(receive_page.imapdir_entry); gtk_widget_hide(receive_page.subsonly_checkbtn); gtk_widget_hide(receive_page.low_bandwidth_checkbtn); + gtk_widget_hide(receive_page.imap_use_trash_checkbtn); break; case A_LOCAL: gtk_widget_show(send_page.msgid_checkbtn); @@ -4167,6 +4184,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data) gtk_widget_hide(receive_page.imapdir_entry); gtk_widget_hide(receive_page.subsonly_checkbtn); gtk_widget_hide(receive_page.low_bandwidth_checkbtn); + gtk_widget_hide(receive_page.imap_use_trash_checkbtn); break; case A_IMAP4: #ifndef HAVE_LIBETPAN @@ -4270,6 +4288,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data) gtk_widget_show(receive_page.imapdir_entry); gtk_widget_show(receive_page.subsonly_checkbtn); gtk_widget_show(receive_page.low_bandwidth_checkbtn); + gtk_widget_show(receive_page.imap_use_trash_checkbtn); break; case A_NONE: gtk_widget_show(send_page.msgid_checkbtn); @@ -4362,6 +4381,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data) gtk_widget_hide(receive_page.imapdir_entry); gtk_widget_hide(receive_page.subsonly_checkbtn); gtk_widget_hide(receive_page.low_bandwidth_checkbtn); + gtk_widget_hide(receive_page.imap_use_trash_checkbtn); break; case A_POP3: default: @@ -4460,6 +4480,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data) gtk_widget_hide(receive_page.imapdir_entry); gtk_widget_hide(receive_page.subsonly_checkbtn); gtk_widget_hide(receive_page.low_bandwidth_checkbtn); + gtk_widget_hide(receive_page.imap_use_trash_checkbtn); break; } diff --git a/src/prefs_account.h b/src/prefs_account.h @@ -183,6 +183,7 @@ struct _PrefsAccount gchar *imap_dir; gboolean imap_subsonly; gboolean low_bandwidth; + gboolean imap_use_trash; gboolean set_sent_folder; gchar *sent_folder; diff --git a/src/summaryview.c b/src/summaryview.c @@ -124,6 +124,8 @@ guint summary_get_msgnum (SummaryView *summaryview, static void summary_set_hide_read_msgs_menu (SummaryView *summaryview, guint action); +static void summary_set_hide_del_msgs_menu (SummaryView *summaryview, + guint action); static GtkCMCTreeNode *summary_find_prev_msg (SummaryView *summaryview, @@ -205,6 +207,7 @@ static void summary_execute_delete (SummaryView *summaryview); static void summary_execute_delete_func (GtkCMCTree *ctree, GtkCMCTreeNode *node, gpointer data); +static void summary_execute_expunge (SummaryView *summaryview); static void summary_thread_init (SummaryView *summaryview); @@ -1204,6 +1207,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item) item?folder_item_parent(item):0x0, item?item->no_select:FALSE); summary_set_hide_read_msgs_menu(summaryview, FALSE); + summary_set_hide_del_msgs_menu(summaryview, FALSE); summary_clear_all(summaryview); summaryview->folder_item = item; summary_thaw(summaryview); @@ -1244,28 +1248,37 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item) mlist = folder_item_get_msg_list(item); } - if (summaryview->folder_item->hide_read_msgs && + if ((summaryview->folder_item->hide_read_msgs || summaryview->folder_item->hide_del_msgs) && quicksearch_is_active(summaryview->quicksearch) == FALSE) { GSList *not_killed; - summary_set_hide_read_msgs_menu(summaryview, TRUE); + summary_set_hide_read_msgs_menu(summaryview, summaryview->folder_item->hide_read_msgs); + summary_set_hide_del_msgs_menu(summaryview, summaryview->folder_item->hide_del_msgs); not_killed = NULL; for(cur = mlist ; cur != NULL && cur->data != NULL ; cur = g_slist_next(cur)) { MsgInfo * msginfo = (MsgInfo *) cur->data; if (!msginfo->hidden) { - if (MSG_IS_UNREAD(msginfo->flags) && - !MSG_IS_IGNORE_THREAD(msginfo->flags)) - not_killed = g_slist_prepend(not_killed, msginfo); - else if (MSG_IS_MARKED(msginfo->flags) || - MSG_IS_LOCKED(msginfo->flags)) - not_killed = g_slist_prepend(not_killed, msginfo); - else if (is_refresh && - (msginfo->msgnum == selected_msgnum || - msginfo->msgnum == displayed_msgnum)) - not_killed = g_slist_prepend(not_killed, msginfo); - else + if (MSG_IS_DELETED(msginfo->flags) && summaryview->folder_item->hide_del_msgs) { procmsg_msginfo_free(msginfo); + continue; + } + if (summaryview->folder_item->hide_read_msgs) { + if (MSG_IS_UNREAD(msginfo->flags) && + !MSG_IS_IGNORE_THREAD(msginfo->flags)) + not_killed = g_slist_prepend(not_killed, msginfo); + else if (MSG_IS_MARKED(msginfo->flags) || + MSG_IS_LOCKED(msginfo->flags)) + not_killed = g_slist_prepend(not_killed, msginfo); + else if (is_refresh && + (msginfo->msgnum == selected_msgnum || + msginfo->msgnum == displayed_msgnum)) + not_killed = g_slist_prepend(not_killed, msginfo); + else + procmsg_msginfo_free(msginfo); + } else { + not_killed = g_slist_prepend(not_killed, msginfo); + } } else procmsg_msginfo_free(msginfo); } @@ -1274,6 +1287,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item) mlist = not_killed; } else { summary_set_hide_read_msgs_menu(summaryview, FALSE); + summary_set_hide_del_msgs_menu(summaryview, FALSE); } if (quicksearch_is_active(summaryview->quicksearch)) { @@ -2431,6 +2445,7 @@ static void summary_status_show(SummaryView *summaryview) } if (summaryview->folder_item->hide_read_msgs + || summaryview->folder_item->hide_del_msgs || quicksearch_is_active(summaryview->quicksearch)) { rowlist = GTK_CMCLIST(summaryview->ctree)->row_list; for (cur = rowlist; cur != NULL && cur->data != NULL; cur = cur->next) { @@ -4125,9 +4140,11 @@ static void summary_delete_row(SummaryView *summaryview, GtkCMCTreeNode *row) summaryview->deleted++; if (!prefs_common.immediate_exec && - !folder_has_parent_of_type(summaryview->folder_item, F_TRASH)) + !folder_has_parent_of_type(summaryview->folder_item, F_TRASH)) { summary_set_row_marks(summaryview, row); - + } else if (summaryview->folder_item->folder->account && !summaryview->folder_item->folder->account->imap_use_trash) { + summary_set_row_marks(summaryview, row); + } debug_print("Message %s/%d is set to delete\n", msginfo->folder->path, msginfo->msgnum); } @@ -4176,18 +4193,20 @@ void summary_delete(SummaryView *summaryview) if (!summaryview->folder_item) return; - if (!prefs_common.live_dangerously) { - gchar *buf = NULL; - int num = g_list_length(GTK_CMCLIST(summaryview->ctree)->selection); - buf = g_strdup_printf(ngettext( - "Do you really want to delete the selected message?", - "Do you really want to delete the %d selected messages?", num), - num); - aval = alertpanel(_("Delete message(s)"), - buf, - GTK_STOCK_CANCEL, "+"GTK_STOCK_DELETE, NULL); - g_free(buf); - if (aval != G_ALERTALTERNATE) return; + if (!summaryview->folder_item->folder->account || summaryview->folder_item->folder->account->imap_use_trash) { + if (!prefs_common.live_dangerously) { + gchar *buf = NULL; + int num = g_list_length(GTK_CMCLIST(summaryview->ctree)->selection); + buf = g_strdup_printf(ngettext( + "Do you really want to delete the selected message?", + "Do you really want to delete the %d selected messages?", num), + num); + aval = alertpanel(_("Delete message(s)"), + buf, + GTK_STOCK_CANCEL, "+"GTK_STOCK_DELETE, NULL); + g_free(buf); + if (aval != G_ALERTALTERNATE) return; + } } for (cur = GTK_CMCLIST(ctree)->selection; cur != NULL && cur->data != NULL; @@ -4244,7 +4263,8 @@ void summary_delete_trash(SummaryView *summaryview) to_folder = summaryview->folder_item->folder->trash; if (to_folder == NULL || to_folder == summaryview->folder_item - || folder_has_parent_of_type(summaryview->folder_item, F_TRASH)) + || folder_has_parent_of_type(summaryview->folder_item, F_TRASH) + || (summaryview->folder_item->folder->account && !summaryview->folder_item->folder->account->imap_use_trash)) summary_delete(summaryview); else summary_move_selected_to(summaryview, to_folder); @@ -4321,6 +4341,8 @@ static void summary_move_row_to(SummaryView *summaryview, GtkCMCTreeNode *row, if (!prefs_common.immediate_exec) { summary_set_row_marks(summaryview, row); + } else if (msginfo->folder->folder->account && !msginfo->folder->folder->account->imap_use_trash) { + summary_set_row_marks(summaryview, row); } debug_print("Message %d is set to move to %s\n", @@ -4811,14 +4833,129 @@ gboolean summary_execute(SummaryView *summaryview) return TRUE; } +gboolean summary_expunge(SummaryView *summaryview) +{ + GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree); + GtkCMCList *clist = GTK_CMCLIST(summaryview->ctree); + GtkCMCTreeNode *node, *next; + GtkCMCTreeNode *new_selected = NULL; + + if (!summaryview->folder_item) return FALSE; + + if (summary_is_locked(summaryview)) return FALSE; + + summary_lock(summaryview); + + summary_freeze(summaryview); + + main_window_cursor_wait(summaryview->mainwin); + + if (summaryview->threaded) + summary_unthread_for_exec(summaryview); + + folder_item_update_freeze(); + summary_execute_expunge(summaryview); + + node = GTK_CMCTREE_NODE(clist->row_list); + for (; node != NULL; node = next) { + next = gtkut_ctree_node_next(ctree, node); + if (gtk_cmctree_node_get_row_data(ctree, node) != NULL) continue; + + if (node == summaryview->displayed) { + messageview_clear(summaryview->messageview); + summaryview->displayed = NULL; + } + if (GTK_CMCTREE_ROW(node)->children != NULL) { + next = NULL; + if (GTK_CMCTREE_ROW(node)->sibling) { + next = GTK_CMCTREE_ROW(node)->sibling; + } else { + GtkCMCTreeNode *parent = NULL; + for (parent = GTK_CMCTREE_ROW(node)->parent; parent != NULL; + parent = GTK_CMCTREE_ROW(parent)->parent) { + if (GTK_CMCTREE_ROW(parent)->sibling) { + next = GTK_CMCTREE_ROW(parent)->sibling; + } + } + } + } + + if (!new_selected && + gtkut_ctree_node_is_selected(ctree, node)) { + summary_unselect_all(summaryview); + new_selected = summary_find_next_msg(summaryview, node); + if (!new_selected) + new_selected = summary_find_prev_msg + (summaryview, node); + } + + gtk_sctree_remove_node((GtkSCTree *)ctree, node); + } + + folder_item_update_thaw(); + + if (new_selected) { + summary_unlock(summaryview); + gtk_sctree_select + (GTK_SCTREE(ctree), new_selected); + summary_lock(summaryview); + } + + if (summaryview->threaded) { + summary_thread_build(summaryview); + summary_thread_init(summaryview); + } + + summary_thaw(summaryview); + + summaryview->selected = clist->selection ? + GTK_CMCTREE_NODE(clist->selection->data) : NULL; + + if (!GTK_CMCLIST(summaryview->ctree)->row_list) { + menu_set_insensitive_all + (GTK_MENU_SHELL(summaryview->popupmenu)); + gtk_widget_grab_focus(summaryview->folderview->ctree); + } else + gtk_widget_grab_focus(summaryview->ctree); + + summary_update_status(summaryview); + summary_status_show(summaryview); + + gtk_cmctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0); + + summary_unlock(summaryview); + + main_window_cursor_normal(summaryview->mainwin); + + return TRUE; +} + +static void summary_set_deleted_func(GtkCMCTree *ctree, GtkCMCTreeNode *node, + gpointer data) +{ + SummaryView *summaryview = data; + MsgInfo *msginfo; + + msginfo = GTKUT_CTREE_NODE_GET_ROW_DATA(node); + + if (msginfo && MSG_IS_MOVE(msginfo->flags)) { + msginfo->flags.tmp_flags &= ~ MSG_MOVE; + msginfo->flags.perm_flags |= MSG_DELETED; + summary_set_row_marks(summaryview, node); + summaryview->moved--; + summaryview->deleted++; + } +} + static gint summary_execute_move(SummaryView *summaryview) { GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree); GSList *cur; gint val = -1; /* search moving messages and execute */ + gtk_cmctree_pre_recursive(ctree, NULL, summary_execute_move_func, - summaryview); + summaryview); if (summaryview->mlist) { hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, @@ -4828,8 +4965,14 @@ static gint summary_execute_move(SummaryView *summaryview) hooks_register_hook(MSGINFO_UPDATE_HOOKLIST, summary_update_msg, (gpointer) summaryview); - for (cur = summaryview->mlist; cur != NULL && cur->data != NULL; cur = cur->next) - procmsg_msginfo_free((MsgInfo *)cur->data); + if (!summaryview->folder_item->folder->account || summaryview->folder_item->folder->account->imap_use_trash) { + for (cur = summaryview->mlist; cur != NULL && cur->data != NULL; cur = cur->next) + procmsg_msginfo_free((MsgInfo *)cur->data); + } + if (summaryview->folder_item->folder->account && !summaryview->folder_item->folder->account->imap_use_trash) { + gtk_cmctree_pre_recursive(ctree, NULL, summary_set_deleted_func, + summaryview); + } g_slist_free(summaryview->mlist); summaryview->mlist = NULL; return val; @@ -4848,20 +4991,23 @@ static void summary_execute_move_func(GtkCMCTree *ctree, GtkCMCTreeNode *node, if (msginfo && MSG_IS_MOVE(msginfo->flags) && msginfo->to_folder) { summaryview->mlist = g_slist_prepend(summaryview->mlist, msginfo); - gtk_cmctree_node_set_row_data(ctree, node, NULL); - - if (msginfo->msgid && *msginfo->msgid && - node == g_hash_table_lookup(summaryview->msgid_table, - msginfo->msgid)) - g_hash_table_remove(summaryview->msgid_table, - msginfo->msgid); - if (prefs_common.thread_by_subject && - msginfo->subject && *msginfo->subject && - node == subject_table_lookup(summaryview->subject_table, - msginfo->subject)) { - subject_table_remove(summaryview->subject_table, - msginfo->subject); - } + if (!summaryview->folder_item->folder->account || + summaryview->folder_item->folder->account->imap_use_trash) { + gtk_cmctree_node_set_row_data(ctree, node, NULL); + + if (msginfo->msgid && *msginfo->msgid && + node == g_hash_table_lookup(summaryview->msgid_table, + msginfo->msgid)) + g_hash_table_remove(summaryview->msgid_table, + msginfo->msgid); + if (prefs_common.thread_by_subject && + msginfo->subject && *msginfo->subject && + node == subject_table_lookup(summaryview->subject_table, + msginfo->subject)) { + subject_table_remove(summaryview->subject_table, + msginfo->subject); + } + } } } @@ -4910,9 +5056,10 @@ static void summary_execute_delete(SummaryView *summaryview) GSList *cur; /* search deleting messages and execute */ - gtk_cmctree_pre_recursive - (ctree, NULL, summary_execute_delete_func, summaryview); - + if (!summaryview->folder_item->folder->account || summaryview->folder_item->folder->account->imap_use_trash) { + gtk_cmctree_pre_recursive + (ctree, NULL, summary_execute_delete_func, summaryview); + } if (!summaryview->mlist) return; hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, @@ -4924,9 +5071,10 @@ static void summary_execute_delete(SummaryView *summaryview) summaryview->msginfo_update_callback_id = hooks_register_hook(MSGINFO_UPDATE_HOOKLIST, summary_update_msg, (gpointer) summaryview); - for (cur = summaryview->mlist; cur != NULL && cur->data != NULL; cur = cur->next) - procmsg_msginfo_free((MsgInfo *)cur->data); - + if (!summaryview->folder_item->folder->account || summaryview->folder_item->folder->account->imap_use_trash) { + for (cur = summaryview->mlist; cur != NULL && cur->data != NULL; cur = cur->next) + procmsg_msginfo_free((MsgInfo *)cur->data); + } g_slist_free(summaryview->mlist); summaryview->mlist = NULL; } @@ -4960,6 +5108,58 @@ static void summary_execute_delete_func(GtkCMCTree *ctree, GtkCMCTreeNode *node, } } +static void summary_execute_expunge_func(GtkCMCTree *ctree, GtkCMCTreeNode *node, + gpointer data) +{ + SummaryView *summaryview = data; + MsgInfo *msginfo; + + msginfo = GTKUT_CTREE_NODE_GET_ROW_DATA(node); + + if (msginfo && MSG_IS_DELETED(msginfo->flags)) { + summaryview->mlist = + g_slist_prepend(summaryview->mlist, msginfo); + gtk_cmctree_node_set_row_data(ctree, node, NULL); + + if (msginfo->msgid && *msginfo->msgid && + node == g_hash_table_lookup(summaryview->msgid_table, + msginfo->msgid)) { + g_hash_table_remove(summaryview->msgid_table, + msginfo->msgid); + } + if (prefs_common.thread_by_subject && + msginfo->subject && *msginfo->subject && + node == subject_table_lookup(summaryview->subject_table, + msginfo->subject)) { + subject_table_remove(summaryview->subject_table, + msginfo->subject); + } + } +} + +static void summary_execute_expunge(SummaryView *summaryview) +{ + GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree); + GSList *cur; + + gtk_cmctree_pre_recursive + (ctree, NULL, summary_execute_expunge_func, summaryview); + + hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST, + summaryview->msginfo_update_callback_id); + + folder_item_expunge(summaryview->folder_item); + + summaryview->msginfo_update_callback_id = + hooks_register_hook(MSGINFO_UPDATE_HOOKLIST, + summary_update_msg, (gpointer) summaryview); + for (cur = summaryview->mlist; cur != NULL && cur->data != NULL; cur = cur->next) + procmsg_msginfo_free((MsgInfo *)cur->data); + + g_slist_free(summaryview->mlist); + summaryview->mlist = NULL; +} + /* thread functions */ static void summary_thread_build(SummaryView *summaryview) @@ -7379,6 +7579,21 @@ void summary_toggle_show_read_messages(SummaryView *summaryview) summary_show(summaryview, summaryview->folder_item); } +void summary_toggle_show_del_messages(SummaryView *summaryview) +{ + FolderItemUpdateData source; + if (summaryview->folder_item->hide_del_msgs) + summaryview->folder_item->hide_del_msgs = 0; + else + summaryview->folder_item->hide_del_msgs = 1; + + source.item = summaryview->folder_item; + source.update_flags = F_ITEM_UPDATE_NAME; + source.msg = NULL; + hooks_invoke(FOLDER_ITEM_UPDATE_HOOKLIST, &source); + summary_show(summaryview, summaryview->folder_item); +} + static void summary_set_hide_read_msgs_menu (SummaryView *summaryview, guint action) { @@ -7392,6 +7607,19 @@ static void summary_set_hide_read_msgs_menu (SummaryView *summaryview, GINT_TO_POINTER(0)); } +static void summary_set_hide_del_msgs_menu (SummaryView *summaryview, + guint action) +{ + GtkWidget *widget; + + widget = gtk_ui_manager_get_widget(summaryview->mainwin->ui_manager, "/Menu/View/HideDelMessages"); + g_object_set_data(G_OBJECT(widget), "dont_toggle", + GINT_TO_POINTER(1)); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(widget), action); + g_object_set_data(G_OBJECT(widget), "dont_toggle", + GINT_TO_POINTER(0)); +} + void summary_reflect_prefs_pixmap_theme(SummaryView *summaryview) { GtkWidget *ctree = summaryview->ctree; diff --git a/src/summaryview.h b/src/summaryview.h @@ -236,6 +236,7 @@ void summary_delete_trash (SummaryView *summaryview); void summary_cancel (SummaryView *summaryview); gboolean summary_execute (SummaryView *summaryview); +gboolean summary_expunge (SummaryView *summaryview); void summary_attract_by_subject (SummaryView *summaryview); @@ -299,6 +300,8 @@ void summary_set_column_order (SummaryView *summaryview); void summary_toggle_show_read_messages (SummaryView *summaryview); +void summary_toggle_show_del_messages + (SummaryView *summaryview); void summary_toggle_view_real (SummaryView *summaryview);