fix recurring unread state bug
[claws.git] / src / summaryview.c
index ee8f682024fd8d9dc020abed47f205a328b910ec..4202a60b3e2eb053f29525c2ba1f38d6fcd40944 100644 (file)
@@ -89,6 +89,7 @@
 #include "pixmaps/forwarded.xpm"
 #include "pixmaps/clip.xpm"
 #include "pixmaps/ignorethread.xpm"
+#include "pixmaps/locked.xpm"
 
 #define STATUSBAR_PUSH(mainwin, str) \
 { \
 
 #define SUMMARY_COL_MARK_WIDTH         10
 #define SUMMARY_COL_UNREAD_WIDTH       13
+#define SUMMARY_COL_LOCKED_WIDTH       13
 #define SUMMARY_COL_MIME_WIDTH         10
 
 static GdkFont *boldfont;
@@ -135,6 +137,8 @@ static GdkPixmap *forwardedxpm;
 static GdkBitmap *forwardedxpmmask;
 static GdkPixmap *ignorethreadxpm;
 static GdkBitmap *ignorethreadxpmmask;
+static GdkPixmap *lockedxpm;
+static GdkBitmap *lockedxpmmask;
 
 static GdkPixmap *clipxpm;
 static GdkBitmap *clipxpmmask;
@@ -202,6 +206,8 @@ static void summary_set_row_marks   (SummaryView            *summaryview,
 /* message handling */
 static void summary_mark_row           (SummaryView            *summaryview,
                                         GtkCTreeNode           *row);
+static void summary_lock_row           (SummaryView            *summaryview,
+                                        GtkCTreeNode           *row);
 static void summary_mark_row_as_read   (SummaryView            *summaryview,
                                         GtkCTreeNode           *row);
 static void summary_mark_row_as_unread (SummaryView            *summaryview,
@@ -244,6 +250,7 @@ static void summary_unthread_for_exec_func  (GtkCTree       *ctree,
                                                 GtkCTreeNode   *node,
                                                 gpointer        data);
 
+void summary_processing(SummaryView *summaryview, GSList * mlist);
 static void summary_filter_func                (GtkCTree               *ctree,
                                         GtkCTreeNode           *node,
                                         gpointer                data);
@@ -321,6 +328,8 @@ static void summary_subject_clicked (GtkWidget              *button,
                                         SummaryView            *summaryview);
 static void summary_score_clicked      (GtkWidget              *button,
                                         SummaryView            *summaryview);
+static void summary_locked_clicked     (GtkWidget              *button,
+                                        SummaryView            *summaryview);
 
 static void summary_start_drag         (GtkWidget        *widget, 
                                         int button,
@@ -362,14 +371,12 @@ static gint summary_cmp_by_subject        (GtkCList               *clist,
 static gint summary_cmp_by_score       (GtkCList               *clist,
                                         gconstpointer           ptr1,
                                         gconstpointer           ptr2);
+static gint summary_cmp_by_locked      (GtkCList *clist,
+                                        gconstpointer ptr1, gconstpointer ptr2);
 static gint summary_cmp_by_label       (GtkCList               *clist,
                                         gconstpointer           ptr1,
                                         gconstpointer           ptr2);
 
-#if MARK_ALL_READ
-static void summary_mark_all_read (SummaryView *summaryview);                                   
-#endif
-
 GtkTargetEntry summary_drag_types[1] =
 {
        {"text/plain", GTK_TARGET_SAME_APP, TARGET_DUMMY}
@@ -429,7 +436,8 @@ static const gchar *const col_label[N_SUMMARY_COLS] = {
        N_("Date"),     /* S_COL_DATE    */
        N_("Size"),     /* S_COL_SIZE    */
        N_("No."),      /* S_COL_NUMBER  */
-       N_("Score")     /* S_COL_SCORE   */
+       N_("Score"),    /* S_COL_SCORE   */
+       N_("L")         /* S_COL_LOCKED  */
 };
 
 SummaryView *summary_create(void)
@@ -535,6 +543,7 @@ void summary_init(SummaryView *summaryview)
                      forwarded_xpm);
        PIXMAP_CREATE(summaryview->ctree, ignorethreadxpm, ignorethreadxpmmask,
                      ignorethread_xpm);
+       PIXMAP_CREATE(summaryview->ctree, lockedxpm, lockedxpmmask, locked_xpm);                      
        PIXMAP_CREATE(summaryview->ctree, clipxpm, clipxpmmask, clip_xpm);
        PIXMAP_CREATE(summaryview->hbox, folderxpm, folderxpmmask,
                      dir_open_xpm);
@@ -699,12 +708,9 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item,
                }
                folder_update_op_count();
        }
-       else if (!summaryview->filtering_happened) {
-               summary_write_cache(summaryview);
-       }
-
-       summaryview->filtering_happened = FALSE;
-
+        
+       summary_write_cache(summaryview);
+        
        summaryview->folderview->opened = selected_node;
 
        gtk_clist_freeze(GTK_CLIST(ctree));
@@ -746,6 +752,8 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item,
 
        mlist = item->folder->get_msg_list(item->folder, item, !update_cache);
 
+       summary_processing(summaryview, mlist);
+
        for(cur = mlist ; cur != NULL ; cur = g_slist_next(cur)) {
                MsgInfo * msginfo = (MsgInfo *) cur->data;
 
@@ -1299,7 +1307,8 @@ static GtkCTreeNode *summary_find_prev_msg(SummaryView *summaryview,
 
        for (; node != NULL; node = GTK_CTREE_NODE_PREV(node)) {
                msginfo = gtk_ctree_node_get_row_data(ctree, node);
-               if (!MSG_IS_DELETED(msginfo->flags)) break;
+               if (!MSG_IS_DELETED(msginfo->flags))
+                       break;
        }
 
        return node;
@@ -1319,7 +1328,8 @@ static GtkCTreeNode *summary_find_next_msg(SummaryView *summaryview,
 
        for (; node != NULL; node = gtkut_ctree_node_next(ctree, node)) {
                msginfo = gtk_ctree_node_get_row_data(ctree, node);
-               if (!MSG_IS_DELETED(msginfo->flags)) break;
+               if (!MSG_IS_DELETED(msginfo->flags))
+                       break;
        }
 
        return node;
@@ -1821,6 +1831,9 @@ void summary_sort(SummaryView *summaryview, SummarySortType type)
        case SORT_BY_SCORE:
                cmp_func = (GtkCListCompareFunc)summary_cmp_by_score;
                break;
+       case SORT_BY_LOCKED:
+               cmp_func = (GtkCListCompareFunc)summary_cmp_by_locked;
+               break;
        case SORT_BY_LABEL:
                cmp_func = (GtkCListCompareFunc)summary_cmp_by_label;
                break;
@@ -2132,7 +2145,7 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[],
        text[col_pos[S_COL_SCORE]]  = itos_buf(col_score, msginfo->threadscore);
 #else
        text[col_pos[S_COL_SCORE]]  = itos_buf(col_score, msginfo->score);
-#endif
+#endif 
 
        if (msginfo->date_t) {
                procheader_date_get_localtime(date_modified,
@@ -2219,13 +2232,6 @@ static void summary_display_msg(SummaryView *summaryview, GtkCTreeNode *row,
                summaryview->newmsgs--;
        if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags))
                summaryview->unread--;
-       if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)) {
-               MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD);
-               CHANGE_FLAGS(msginfo);
-               summary_set_row_marks(summaryview, row);
-               gtk_clist_thaw(GTK_CLIST(ctree));
-               summary_status_show(summaryview);
-       }
 
        if (new_window) {
                MessageView *msgview;
@@ -2249,6 +2255,14 @@ static void summary_display_msg(SummaryView *summaryview, GtkCTreeNode *row,
                gtkut_ctree_node_move_if_on_the_edge(ctree, row);
        }
 
+       if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)) {
+               MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD);
+               CHANGE_FLAGS(msginfo);
+               summary_set_row_marks(summaryview, row);
+               gtk_clist_thaw(GTK_CLIST(ctree));
+               summary_status_show(summaryview);
+       }
+
        if (GTK_WIDGET_VISIBLE(summaryview->headerwin->window))
                header_window_show(summaryview->headerwin, msginfo);
 
@@ -2490,6 +2504,14 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row)
                gtk_ctree_node_set_text(ctree, row, col_pos[S_COL_MARK], NULL);
        }
 
+       if (MSG_IS_LOCKED(flags)) {
+               gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_LOCKED],
+                                         lockedxpm, lockedxpmmask);
+       }
+       else {
+               gtk_ctree_node_set_text(ctree, row, col_pos[S_COL_LOCKED], NULL);
+       }
+
        if (MSG_IS_MIME(flags)) {
                gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_MIME],
                                          clipxpm, clipxpmmask);
@@ -2546,6 +2568,38 @@ static void summary_mark_row(SummaryView *summaryview, GtkCTreeNode *row)
        debug_print(_("Message %d is marked\n"), msginfo->msgnum);
 }
 
+static void summary_lock_row(SummaryView *summaryview, GtkCTreeNode *row)
+{
+       /* almost verbatim summary_mark_row(); may want a menu action? */
+       gboolean changed = FALSE;
+       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
+       MsgInfo *msginfo;
+
+       msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       if (MSG_IS_DELETED(msginfo->flags))
+               summaryview->deleted--;
+       if (MSG_IS_MOVE(msginfo->flags)) {
+               summaryview->moved--;
+               changed = TRUE;
+       }
+       if (MSG_IS_COPY(msginfo->flags)) {
+               summaryview->copied--;
+               changed = TRUE;
+       }
+       if (changed && !prefs_common.immediate_exec) {
+               msginfo->to_folder->op_count--;
+               if (msginfo->to_folder->op_count == 0)
+                       folderview_update_item(msginfo->to_folder, 0);
+       }
+       msginfo->to_folder = NULL;
+       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_DELETED);
+       MSG_UNSET_TMP_FLAGS(msginfo->flags, MSG_MOVE | MSG_COPY);
+       MSG_SET_PERM_FLAGS(msginfo->flags, MSG_LOCKED);
+       CHANGE_FLAGS(msginfo);
+       summary_set_row_marks(summaryview, row);
+       debug_print(_("Message %d is locked\n"), msginfo->msgnum);
+}
+
 void summary_mark(SummaryView *summaryview)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
@@ -2656,6 +2710,8 @@ static void summary_delete_row(SummaryView *summaryview, GtkCTreeNode *row)
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
 
+       if (MSG_IS_LOCKED(msginfo->flags)) return;
+
        if (MSG_IS_DELETED(msginfo->flags)) return;
 
        if (MSG_IS_MOVE(msginfo->flags)) {
@@ -3497,9 +3553,65 @@ static void summary_unthread_for_exec_func(GtkCTree *ctree, GtkCTreeNode *node,
        }
 }
 
+void summary_processing(SummaryView *summaryview, GSList * mlist)
+{
+       GSList * processing_list;
+       FolderItem * folder_item;
+       GSList * cur;
+       gchar * id;
+       gchar * buf;
+
+       folder_item = summaryview->folder_item;
+       if (folder_item == NULL)
+               return;
+
+       processing_list = folder_item->prefs->processing;
+
+       if (processing_list == NULL)
+               return;
+
+       summary_lock(summaryview);
+       
+       buf = g_strdup_printf(_("Processing (%s)..."), folder_item->path);
+       debug_print(buf);
+       STATUSBAR_PUSH(summaryview->mainwin, buf);
+       g_free(buf);
+
+       main_window_cursor_wait(summaryview->mainwin);
+
+       summaryview->folder_table = g_hash_table_new(NULL, NULL);
+
+       for(cur = mlist ; cur != NULL ; cur = cur->next) {
+               MsgInfo * msginfo;
+
+               msginfo = (MsgInfo *) cur->data;
+               filter_msginfo_move_or_delete(processing_list, msginfo,
+                                             summaryview->folder_table);
+       }
+       
+       folder_item_scan_foreach(summaryview->folder_table);
+       folderview_update_item_foreach(summaryview->folder_table);
+       
+       g_hash_table_destroy(summaryview->folder_table);
+       summaryview->folder_table = NULL;
+       
+       if (prefs_common.immediate_exec) {
+               summary_unlock(summaryview);
+               summary_execute(summaryview);
+               summary_lock(summaryview);
+       } else
+               summary_status_show(summaryview);
+
+       debug_print(_("done.\n"));
+       STATUSBAR_POP(summaryview->mainwin);
+       main_window_cursor_normal(summaryview->mainwin);
+
+       summary_unlock(summaryview);
+}
+
 void summary_filter(SummaryView *summaryview)
 {
-       if (!prefs_common.fltlist && !prefs_filtering) {
+       if (!prefs_common.fltlist && !global_processing) {
                alertpanel_error(_("No filter rules defined."));
                return;
        }
@@ -3512,7 +3624,7 @@ void summary_filter(SummaryView *summaryview)
 
        gtk_clist_freeze(GTK_CLIST(summaryview->ctree));
 
-       if (prefs_filtering == NULL) {
+       if (global_processing == NULL) {
                gtk_ctree_pre_recursive(GTK_CTREE(summaryview->ctree), NULL,
                                        GTK_CTREE_FUNC(summary_filter_func),
                                        summaryview);
@@ -3559,7 +3671,7 @@ static void summary_filter_func(GtkCTree *ctree, GtkCTreeNode *node,
        gchar *file;
        FolderItem *dest;
 
-       if (prefs_filtering == NULL) {
+       if (global_processing == NULL) {
                /* old filtering */
                file = procmsg_get_message_file_path(msginfo);
                dest = filter_get_dest_folder(prefs_common.fltlist, file);
@@ -3570,7 +3682,7 @@ static void summary_filter_func(GtkCTree *ctree, GtkCTreeNode *node,
                        summary_move_row_to(summaryview, node, dest);
        }
        else
-               filter_msginfo_move_or_delete(prefs_filtering, msginfo,
+               filter_msginfo_move_or_delete(global_processing, msginfo,
                                              summaryview->folder_table);
 }
 
@@ -3786,6 +3898,8 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
                                           GTK_JUSTIFY_CENTER);
        gtk_clist_set_column_justification(GTK_CLIST(ctree), col_pos[S_COL_UNREAD],
                                           GTK_JUSTIFY_CENTER);
+       gtk_clist_set_column_justification(GTK_CLIST(ctree), col_pos[S_COL_LOCKED],
+                                          GTK_JUSTIFY_CENTER);
        gtk_clist_set_column_justification(GTK_CLIST(ctree), col_pos[S_COL_MIME],
                                           GTK_JUSTIFY_CENTER);
        gtk_clist_set_column_justification(GTK_CLIST(ctree), col_pos[S_COL_SIZE],
@@ -3798,6 +3912,8 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
                                   SUMMARY_COL_MARK_WIDTH);
        gtk_clist_set_column_width(GTK_CLIST(ctree), col_pos[S_COL_UNREAD],
                                   SUMMARY_COL_UNREAD_WIDTH);
+       gtk_clist_set_column_width(GTK_CLIST(ctree), col_pos[S_COL_LOCKED],
+                                  SUMMARY_COL_LOCKED_WIDTH);
        gtk_clist_set_column_width(GTK_CLIST(ctree), col_pos[S_COL_MIME],
                                   SUMMARY_COL_MIME_WIDTH);
        gtk_clist_set_column_width(GTK_CLIST(ctree), col_pos[S_COL_SUBJECT],
@@ -3847,6 +3963,7 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
        CLIST_BUTTON_SIGNAL_CONNECT(S_COL_FROM   , summary_from_clicked);
        CLIST_BUTTON_SIGNAL_CONNECT(S_COL_SUBJECT, summary_subject_clicked);
        CLIST_BUTTON_SIGNAL_CONNECT(S_COL_SCORE,   summary_score_clicked);
+       CLIST_BUTTON_SIGNAL_CONNECT(S_COL_LOCKED,  summary_locked_clicked);
 
 #undef CLIST_BUTTON_SIGNAL_CONNECT
 
@@ -4205,6 +4322,15 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
                        summary_status_show(summaryview);
                }
                break;
+       case S_COL_LOCKED:
+               if (MSG_IS_LOCKED(msginfo->flags)) {
+                       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_LOCKED);
+                       CHANGE_FLAGS(msginfo);
+                       summary_set_row_marks(summaryview, row);
+               }
+               else
+                       summary_lock_row(summaryview, row);
+               break;
        default:
                break;
        }
@@ -4340,6 +4466,12 @@ static void summary_score_clicked(GtkWidget *button,
        summary_sort(summaryview, SORT_BY_SCORE);
 }
 
+static void summary_locked_clicked(GtkWidget *button,
+                                 SummaryView *summaryview)
+{
+       summary_sort(summaryview, SORT_BY_LOCKED);
+}
+
 static void summary_size_clicked(GtkWidget *button, SummaryView *summaryview)
 {
        summary_sort(summaryview, SORT_BY_SIZE);
@@ -4537,6 +4669,15 @@ static gint summary_cmp_by_score(GtkCList *clist,
                return summary_cmp_by_date(clist, ptr1, ptr2);
 }
 
+static gint summary_cmp_by_locked(GtkCList *clist,
+                                 gconstpointer ptr1, gconstpointer ptr2)
+{
+       MsgInfo *msginfo1 = ((GtkCListRow *)ptr1)->data;
+       MsgInfo *msginfo2 = ((GtkCListRow *)ptr2)->data;
+
+       return MSG_IS_LOCKED(msginfo1->flags) - MSG_IS_LOCKED(msginfo2->flags);
+}
+
 static void summary_ignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpointer data)
 {
        SummaryView *summaryview = (SummaryView *) data;
@@ -4598,6 +4739,68 @@ static void summary_unignore_thread(SummaryView *summaryview)
 
        summary_status_show(summaryview);
 }
+
+
+static gboolean processing_apply_func(GNode *node, gpointer data)
+{
+       FolderItem *item;
+       GSList * processing;
+       SummaryView * summaryview = (SummaryView *) data;
+       
+       if (node == NULL)
+               return FALSE;
+
+       item = node->data;
+       /* prevent from the warning */
+       if (item->path == NULL)
+               return FALSE;
+       processing = item->prefs->processing;
+
+       if (processing != NULL) {
+               gchar * buf;
+               GSList * mlist;
+               GSList * cur;
+
+               buf = g_strdup_printf(_("Processing (%s)..."), item->path);
+               debug_print(buf);
+               STATUSBAR_PUSH(summaryview->mainwin, buf);
+               g_free(buf);
+
+               mlist = item->folder->get_msg_list(item->folder, item,
+                                                  TRUE);
+               
+               for(cur = mlist ; cur != NULL ; cur = cur->next) {
+                       MsgInfo * msginfo;
+                       
+                       msginfo = (MsgInfo *) cur->data;
+                       filter_msginfo_move_or_delete(processing, msginfo,
+                                                     NULL);
+                       procmsg_msginfo_free(msginfo);
+               }
+
+               g_slist_free(mlist);
+               
+               STATUSBAR_POP(summaryview->mainwin);
+       }
+
+
+       return FALSE;
+}
+
+void processing_apply(SummaryView * summaryview)
+{
+       GList * cur;
+
+       for (cur = folder_get_list() ; cur != NULL ; cur = g_list_next(cur)) {
+               Folder *folder;
+
+               folder = (Folder *) cur->data;
+               g_node_traverse(folder->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
+                               processing_apply_func, summaryview);
+       }
+}
+
+
 /*
  * End of Source.
  */