diff --git a/ChangeLog-gtk2.claws b/ChangeLog-gtk2.claws index 73584b1e0..949fa724f 100644 --- a/ChangeLog-gtk2.claws +++ b/ChangeLog-gtk2.claws @@ -1,3 +1,19 @@ +2005-10-08 [colin] 1.9.15cvs21 + + * src/folder.c + * src/folder.h + Add a processing_pending indicator, set on + folder_item_open and cleared after + folder_item_process_open + * src/folderview.c + * src/summaryview.c + wrap procmsg_msginfo_*_flags, and in the + wrapper check that there's no folder processing + pending. If there is, defer the flags change until + processing is done to avoid stepping over each + other's toes. + Freeze during processing, but not during scanning. + 2005-10-07 [colin] 1.9.15cvs20 * src/plugins/pgpcore/passphrase.c diff --git a/PATCHSETS b/PATCHSETS index f68c38fa2..d99e5bf65 100644 --- a/PATCHSETS +++ b/PATCHSETS @@ -857,3 +857,4 @@ ( cvs diff -u -r 1.1 -r 1.2 src/pixmaps/address.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/address_book.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/book.xpm; cvs diff -u -r 1.1.4.1 -r 1.1.4.2 src/pixmaps/check_spelling.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/checkbox_off.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/checkbox_on.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/close.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/complete.xpm; cvs diff -u -r 1.1.16.1 -r 1.1.16.2 src/pixmaps/continue.xpm; cvs diff -u -r 1.1.1.1 -r 1.1.1.2 src/pixmaps/deleted.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/down_arrow.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/exec.xpm; cvs diff -u -r 1.1.1.1 -r 1.1.1.2 src/pixmaps/forwarded.xpm; cvs diff -u -r 1.1.1.1.16.1 -r 1.1.1.1.16.2 src/pixmaps/group.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/ignorethread.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/interface.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/jpilot.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/ldap.xpm; cvs diff -u -r 1.1.1.1 -r 1.1.1.2 src/pixmaps/linewrap.xpm; cvs diff -u -r 1.1.4.1 -r 1.1.4.2 src/pixmaps/linewrapcurrent.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mail.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mail_attach.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mail_compose.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mail_forward.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mail_receive.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mail_receive_all.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mail_reply.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mail_reply_to_all.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mail_reply_to_author.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mail_send.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mail_send_queue.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mime_application.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mime_audio.xpm; cvs diff -u -r 1.2 -r 1.3 src/pixmaps/mime_image.xpm; cvs diff -u -r 1.1.4.1 -r 1.1.4.2 src/pixmaps/mime_message.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mime_text_enriched.xpm; cvs diff -u -r 1.2 -r 1.3 src/pixmaps/mime_text_html.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mime_text_plain.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/mime_unknown.xpm; cvs diff -u -r 1.2 -r 1.3 src/pixmaps/new.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/news_compose.xpm; cvs diff -u -r 1.1.4.1 -r 1.1.4.2 src/pixmaps/offline.xpm; cvs diff -u -r 1.1.4.1 -r 1.1.4.2 src/pixmaps/online.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/paste.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/preferences.xpm; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/pixmaps/privacy_emblem_encrypted.xpm; cvs diff -u -r 1.1.4.1 -r 1.1.4.2 src/pixmaps/privacy_expired.xpm; cvs diff -u -r 1.1.4.1 -r 1.1.4.2 src/pixmaps/privacy_failed.xpm; cvs diff -u -r 1.1.4.1 -r 1.1.4.2 src/pixmaps/privacy_passed.xpm; cvs diff -u -r 1.1.4.1 -r 1.1.4.2 src/pixmaps/privacy_signed.xpm; cvs diff -u -r 1.1.4.1 -r 1.1.4.2 src/pixmaps/privacy_unknown.xpm; cvs diff -u -r 1.1.4.1 -r 1.1.4.2 src/pixmaps/privacy_warn.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/properties.xpm; cvs diff -u -r 1.1.1.1 -r 1.1.1.2 src/pixmaps/replied.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/search.xpm; cvs diff -u -r 1.2.16.1 -r 1.2.16.2 src/pixmaps/unread.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/up_arrow.xpm; cvs diff -u -r 1.1 -r 1.2 src/pixmaps/vcard.xpm; ) > 1.9.15cvs18.patchset ( cvs diff -u -r 1.382.2.179 -r 1.382.2.180 src/compose.c; ) > 1.9.15cvs19.patchset ( cvs diff -u -r 1.1.2.4 -r 1.1.2.5 src/plugins/pgpcore/passphrase.c; ) > 1.9.15cvs20.patchset +( cvs diff -u -r 1.213.2.62 -r 1.213.2.63 src/folder.c; cvs diff -u -r 1.87.2.21 -r 1.87.2.22 src/folder.h; cvs diff -u -r 1.207.2.69 -r 1.207.2.70 src/folderview.c; cvs diff -u -r 1.395.2.132 -r 1.395.2.133 src/summaryview.c; ) > 1.9.15cvs21.patchset diff --git a/configure.ac b/configure.ac index 8420b31f8..fdb000388 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ MINOR_VERSION=9 MICRO_VERSION=15 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=20 +EXTRA_VERSION=21 EXTRA_RELEASE= EXTRA_GTK2_VERSION= diff --git a/src/folder.c b/src/folder.c index f5a5998f5..b060a17d9 100644 --- a/src/folder.c +++ b/src/folder.c @@ -1459,7 +1459,10 @@ static gint folder_sort_folder_list(gconstpointer a, gconstpointer b) return (gint_a - gint_b); } -void folder_item_process_open(FolderItem *item) +void folder_item_process_open (FolderItem *item, + void (*before_proc_func)(gpointer data), + void (*after_proc_func)(gpointer data), + gpointer data) { gchar *buf; if (item == NULL) @@ -1476,10 +1479,17 @@ void folder_item_process_open(FolderItem *item) item->path ? item->path : item->name); debug_print("%s\n", buf); g_free(buf); - + + if (before_proc_func) + before_proc_func(data); + folder_item_apply_processing(item); + if (after_proc_func) + after_proc_func(data); + debug_print("done.\n"); + item->processing_pending = FALSE; return; } @@ -1487,6 +1497,10 @@ gint folder_item_open(FolderItem *item) { g_return_val_if_fail(item->no_select == FALSE, -1); + /* caller of folder_item_open *must* call + * folder_item_process_open after ! */ + item->processing_pending = TRUE; + item->opened = TRUE; return 0; diff --git a/src/folder.h b/src/folder.h index 4487f239e..834320ecc 100644 --- a/src/folder.h +++ b/src/folder.h @@ -627,6 +627,7 @@ struct _FolderItem /* for faster search of special parents */ SpecialFolderItemType parent_stype; + gboolean processing_pending; }; struct _PersistPrefs @@ -811,5 +812,8 @@ void folder_item_set_batch (FolderItem *item, gboolean batch); gboolean folder_has_parent_of_type (FolderItem *item, SpecialFolderItemType type); void folder_synchronise (Folder *folder); gboolean folder_want_synchronise (Folder *folder); -void folder_item_process_open (FolderItem *item); +void folder_item_process_open (FolderItem *item, + void (*before_proc_func)(gpointer data), + void (*after_proc_func)(gpointer data), + gpointer data); #endif /* __FOLDER_H__ */ diff --git a/src/folderview.c b/src/folderview.c index 36052805c..47a4d140d 100644 --- a/src/folderview.c +++ b/src/folderview.c @@ -1791,6 +1791,20 @@ static gboolean folderview_key_pressed(GtkWidget *widget, GdkEventKey *event, return FALSE; } +static void summary_freeze_for_proc(gpointer data) +{ + FolderView *folderview = (FolderView *)data; + debug_print("freezing during processing...\n"); + gtk_clist_freeze(GTK_CLIST(folderview->summaryview->ctree)); +} + +static void summary_thaw_for_proc(gpointer data) +{ + FolderView *folderview = (FolderView *)data; + debug_print("thawing after processing\n"); + gtk_clist_thaw(GTK_CLIST(folderview->summaryview->ctree)); +} + gboolean folderview_process_open(gpointer data) { FolderView *folderview = (FolderView *)data; @@ -1808,7 +1822,10 @@ gboolean folderview_process_open(gpointer data) return FALSE; folder_item_update_freeze(); - folder_item_process_open(item); + folder_item_process_open(item, + summary_freeze_for_proc, + summary_thaw_for_proc, + folderview); folder_item_update_thaw(); return FALSE; diff --git a/src/summaryview.c b/src/summaryview.c index a2a327653..4520c7727 100644 --- a/src/summaryview.c +++ b/src/summaryview.c @@ -2435,6 +2435,96 @@ static void summary_display_msg(SummaryView *summaryview, GtkCTreeNode *row) summary_display_msg_full(summaryview, row, FALSE, FALSE); } +static gboolean defer_change(gpointer data); +typedef struct _ChangeData { + MsgInfo *info; + gint op; /* 0, 1, 2 for unset, set, change */ + MsgPermFlags set_flags; + MsgTmpFlags set_tmp_flags; + MsgPermFlags unset_flags; + MsgTmpFlags unset_tmp_flags; +} ChangeData; + +static void summary_msginfo_unset_flags(MsgInfo *msginfo, MsgPermFlags flags, MsgTmpFlags tmp_flags) +{ + if (!msginfo->folder || !msginfo->folder->processing_pending) { + debug_print("flags: doing unset now\n"); + procmsg_msginfo_unset_flags(msginfo, flags, tmp_flags); + } else { + ChangeData *unset_data = g_new0(ChangeData, 1); + unset_data->info = msginfo; + unset_data->op = 0; + unset_data->unset_flags = flags; + unset_data->unset_tmp_flags = tmp_flags; + debug_print("flags: deferring unset\n"); + g_timeout_add(100, defer_change, unset_data); + } +} + +static void summary_msginfo_set_flags(MsgInfo *msginfo, MsgPermFlags flags, MsgTmpFlags tmp_flags) +{ + if (!msginfo->folder || !msginfo->folder->processing_pending) { + debug_print("flags: doing set now\n"); + procmsg_msginfo_set_flags(msginfo, flags, tmp_flags); + } else { + ChangeData *set_data = g_new0(ChangeData, 1); + set_data->info = msginfo; + set_data->op = 1; + set_data->set_flags = flags; + set_data->set_tmp_flags = tmp_flags; + debug_print("flags: deferring set\n"); + g_timeout_add(100, defer_change, set_data); + } +} + +static void summary_msginfo_change_flags(MsgInfo *msginfo, + MsgPermFlags add_flags, MsgTmpFlags add_tmp_flags, + MsgPermFlags rem_flags, MsgTmpFlags rem_tmp_flags) +{ + if (!msginfo->folder || !msginfo->folder->processing_pending) { + debug_print("flags: doing change now\n"); + procmsg_msginfo_change_flags(msginfo, add_flags, add_tmp_flags, + rem_flags, rem_tmp_flags); + } else { + ChangeData *change_data = g_new0(ChangeData, 1); + change_data->info = msginfo; + change_data->op = 2; + change_data->set_flags = add_flags; + change_data->set_tmp_flags = add_tmp_flags; + change_data->unset_flags = rem_flags; + change_data->unset_tmp_flags = rem_tmp_flags; + debug_print("flags: deferring change\n"); + g_timeout_add(100, defer_change, change_data); + } +} + +gboolean defer_change(gpointer data) +{ + ChangeData *chg = (ChangeData *)data; + if (chg->info->folder && chg->info->folder->processing_pending) { + debug_print("flags: trying later\n"); + return TRUE; /* try again */ + } else { + debug_print("flags: finally doing it\n"); + switch(chg->op) { + case 0: + procmsg_msginfo_unset_flags(chg->info, chg->unset_flags, chg->unset_tmp_flags); + break; + case 1: + procmsg_msginfo_set_flags(chg->info, chg->set_flags, chg->set_tmp_flags); + break; + case 2: + procmsg_msginfo_change_flags(chg->info, chg->set_flags, chg->set_tmp_flags, + chg->unset_flags, chg->unset_tmp_flags); + break; + default: + g_warning("shouldn't happen\n"); + } + g_free(chg); + } + return FALSE; +} + static void msginfo_mark_as_read (SummaryView *summaryview, MsgInfo *msginfo, GtkCTreeNode *row) { @@ -2443,7 +2533,7 @@ static void msginfo_mark_as_read (SummaryView *summaryview, MsgInfo *msginfo, g_return_if_fail(row != NULL); if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)) { - procmsg_msginfo_unset_flags + summary_msginfo_unset_flags (msginfo, MSG_NEW | MSG_UNREAD, 0); summary_set_row_marks(summaryview, row); gtk_clist_thaw(GTK_CLIST(summaryview->ctree)); @@ -2819,7 +2909,7 @@ static void summary_mark_row(SummaryView *summaryview, GtkCTreeNode *row) summaryview->copied--; procmsg_msginfo_set_to_folder(msginfo, NULL); - procmsg_msginfo_change_flags(msginfo, MSG_MARKED, 0, MSG_DELETED, MSG_MOVE | MSG_COPY); + summary_msginfo_change_flags(msginfo, MSG_MARKED, 0, MSG_DELETED, MSG_MOVE | MSG_COPY); summary_set_row_marks(summaryview, row); debug_print("Message %s/%d is marked\n", msginfo->folder->path, msginfo->msgnum); } @@ -2842,7 +2932,7 @@ static void summary_lock_row(SummaryView *summaryview, GtkCTreeNode *row) changed = TRUE; } procmsg_msginfo_set_to_folder(msginfo, NULL); - procmsg_msginfo_change_flags(msginfo, MSG_LOCKED, 0, MSG_DELETED, MSG_MOVE | MSG_COPY); + summary_msginfo_change_flags(msginfo, MSG_LOCKED, 0, MSG_DELETED, MSG_MOVE | MSG_COPY); summary_set_row_marks(summaryview, row); debug_print("Message %d is locked\n", msginfo->msgnum); @@ -2857,7 +2947,7 @@ static void summary_unlock_row(SummaryView *summaryview, GtkCTreeNode *row) if (!MSG_IS_LOCKED(msginfo->flags)) return; procmsg_msginfo_set_to_folder(msginfo, NULL); - procmsg_msginfo_unset_flags(msginfo, MSG_LOCKED, 0); + summary_msginfo_unset_flags(msginfo, MSG_LOCKED, 0); summary_set_row_marks(summaryview, row); debug_print("Message %d is unlocked\n", msginfo->msgnum); } @@ -2888,7 +2978,7 @@ static void summary_mark_row_as_read(SummaryView *summaryview, if(!(MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags))) return; - procmsg_msginfo_unset_flags(msginfo, MSG_NEW | MSG_UNREAD, 0); + summary_msginfo_unset_flags(msginfo, MSG_NEW | MSG_UNREAD, 0); summary_set_row_marks(summaryview, row); debug_print("Message %d is marked as read\n", msginfo->msgnum); @@ -2968,11 +3058,11 @@ static void summary_mark_row_as_unread(SummaryView *summaryview, msginfo = gtk_ctree_node_get_row_data(ctree, row); if (MSG_IS_DELETED(msginfo->flags)) { procmsg_msginfo_set_to_folder(msginfo, NULL); - procmsg_msginfo_unset_flags(msginfo, MSG_DELETED, 0); + summary_msginfo_unset_flags(msginfo, MSG_DELETED, 0); summaryview->deleted--; } - procmsg_msginfo_set_flags(msginfo, MSG_UNREAD, 0); + summary_msginfo_set_flags(msginfo, MSG_UNREAD, 0); debug_print("Message %d is marked as unread\n", msginfo->msgnum); @@ -3065,7 +3155,7 @@ static void summary_delete_row(SummaryView *summaryview, GtkCTreeNode *row) summaryview->copied--; procmsg_msginfo_set_to_folder(msginfo, NULL); - procmsg_msginfo_change_flags(msginfo, MSG_DELETED, 0, MSG_MARKED, MSG_MOVE | MSG_COPY); + summary_msginfo_change_flags(msginfo, MSG_DELETED, 0, MSG_MARKED, MSG_MOVE | MSG_COPY); summaryview->deleted++; if (!prefs_common.immediate_exec && @@ -3201,7 +3291,7 @@ static void summary_unmark_row(SummaryView *summaryview, GtkCTreeNode *row) summaryview->copied--; procmsg_msginfo_set_to_folder(msginfo, NULL); - procmsg_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, MSG_MOVE | MSG_COPY); + summary_msginfo_unset_flags(msginfo, MSG_MARKED | MSG_DELETED, MSG_MOVE | MSG_COPY); summary_set_row_marks(summaryview, row); debug_print("Message %s/%d is unmarked\n", @@ -3242,10 +3332,10 @@ static void summary_move_row_to(SummaryView *summaryview, GtkCTreeNode *row, summaryview->copied--; } if (!MSG_IS_MOVE(msginfo->flags)) { - procmsg_msginfo_change_flags(msginfo, 0, MSG_MOVE, MSG_DELETED, MSG_COPY); + summary_msginfo_change_flags(msginfo, 0, MSG_MOVE, MSG_DELETED, MSG_COPY); summaryview->moved++; } else { - procmsg_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_COPY); + summary_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_COPY); } if (!prefs_common.immediate_exec) { @@ -3324,10 +3414,10 @@ static void summary_copy_row_to(SummaryView *summaryview, GtkCTreeNode *row, } if (!MSG_IS_COPY(msginfo->flags)) { - procmsg_msginfo_change_flags(msginfo, 0, MSG_COPY, MSG_DELETED, MSG_MOVE); + summary_msginfo_change_flags(msginfo, 0, MSG_COPY, MSG_DELETED, MSG_MOVE); summaryview->copied++; } else { - procmsg_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_MOVE); + summary_msginfo_unset_flags(msginfo, MSG_DELETED, MSG_MOVE); } if (!prefs_common.immediate_exec) { summary_set_row_marks(summaryview, row); @@ -3740,7 +3830,7 @@ static void summary_execute_copy_func(GtkCTree *ctree, GtkCTreeNode *node, summaryview->mlist = g_slist_prepend(summaryview->mlist, msginfo); - procmsg_msginfo_unset_flags(msginfo, 0, MSG_COPY); + summary_msginfo_unset_flags(msginfo, 0, MSG_COPY); summary_set_row_marks(summaryview, node); } } @@ -4195,7 +4285,7 @@ static void summary_set_row_colorlabel(SummaryView *summaryview, GtkCTreeNode *r msginfo = gtk_ctree_node_get_row_data(ctree, row); - procmsg_msginfo_change_flags(msginfo, MSG_COLORLABEL_TO_FLAGS(labelcolor), 0, + summary_msginfo_change_flags(msginfo, MSG_COLORLABEL_TO_FLAGS(labelcolor), 0, MSG_CLABEL_FLAG_MASK, 0); } @@ -4754,7 +4844,7 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row, break; case S_COL_LOCKED: if (MSG_IS_LOCKED(msginfo->flags)) { - procmsg_msginfo_unset_flags(msginfo, MSG_LOCKED, 0); + summary_msginfo_unset_flags(msginfo, MSG_LOCKED, 0); summary_set_row_marks(summaryview, row); } else @@ -5171,7 +5261,7 @@ static void news_flag_crosspost(MsgInfo *msginfo) g_hash_table_lookup_extended(mff->newsart, line->str, &key, &value)) { debug_print(" <%s>", (gchar *)value); if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)) { - procmsg_msginfo_change_flags(msginfo, + summary_msginfo_change_flags(msginfo, mff->account->crosspost_col, 0, MSG_NEW | MSG_UNREAD, 0); } g_hash_table_remove(mff->newsart, key); @@ -5189,7 +5279,7 @@ static void summary_ignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpoin msginfo = gtk_ctree_node_get_row_data(ctree, row); - procmsg_msginfo_change_flags(msginfo, MSG_IGNORE_THREAD, 0, MSG_NEW | MSG_UNREAD, 0); + summary_msginfo_change_flags(msginfo, MSG_IGNORE_THREAD, 0, MSG_NEW | MSG_UNREAD, 0); summary_set_row_marks(summaryview, row); debug_print("Message %d is marked as ignore thread\n", @@ -5219,7 +5309,7 @@ static void summary_unignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpo msginfo = gtk_ctree_node_get_row_data(ctree, row); - procmsg_msginfo_unset_flags(msginfo, MSG_IGNORE_THREAD, 0); + summary_msginfo_unset_flags(msginfo, MSG_IGNORE_THREAD, 0); summary_set_row_marks(summaryview, row); debug_print("Message %d is marked as unignore thread\n",