2006-03-20 [colin] 2.0.0cvs159
[claws.git] / src / summaryview.c
index 7d55de6df5ca184f9fee158d5a9022dc7153fb5a..0e509cb31743f0209a001cc3c68f43bbe14e3fa8 100644 (file)
@@ -87,6 +87,7 @@
 #include "partial_download.h"
 #include "timing.h"
 #include "gedit-print.h"
+#include "log.h"
 
 #define SUMMARY_COL_MARK_WIDTH         10
 #define SUMMARY_COL_STATUS_WIDTH       13
@@ -118,6 +119,8 @@ static GdkPixmap *ignorethreadxpm;
 static GdkBitmap *ignorethreadxpmmask;
 static GdkPixmap *lockedxpm;
 static GdkBitmap *lockedxpmmask;
+static GdkPixmap *spamxpm;
+static GdkBitmap *spamxpmmask;
 
 static GdkPixmap *clipxpm;
 static GdkBitmap *clipxpmmask;
@@ -137,7 +140,7 @@ static void summary_set_marks_func  (GtkCTree               *ctree,
                                         GtkCTreeNode           *node,
                                         gpointer                data);
 
-static void summary_set_menu_sensitive (SummaryView            *summaryview);
+void summary_set_menu_sensitive        (SummaryView            *summaryview);
 
 static void summary_set_hide_read_msgs_menu (SummaryView *summaryview,
                                             guint action);
@@ -234,9 +237,6 @@ static void summary_unthread_for_exec_func  (GtkCTree       *ctree,
 void summary_simplify_subject(SummaryView *summaryview, gchar * rexp,
                              GSList * mlist);
 
-#if 0
-void summary_processing(SummaryView *summaryview, GSList * mlist);
-#endif
 static void summary_filter_func                (MsgInfo *msginfo);
 
 static void summary_colorlabel_menu_item_activate_cb
@@ -245,7 +245,8 @@ static void summary_colorlabel_menu_item_activate_cb
 static void summary_colorlabel_menu_item_activate_item_cb
                                          (GtkMenuItem  *label_menu_item,
                                           gpointer      data);
-static void summary_colorlabel_menu_create(SummaryView *summaryview);
+static void summary_colorlabel_menu_create(SummaryView *summaryview,
+                                          gboolean  refresh);
 
 static GtkWidget *summary_ctree_create (SummaryView    *summaryview);
 
@@ -437,6 +438,10 @@ static GtkItemFactoryEntry summary_popup_entries[] =
        {N_("/_Mark/Mark all read"),    NULL, summary_mark_all_read, 0, NULL},
        {N_("/_Mark/Ignore thread"),    NULL, summary_ignore_thread, 0, NULL},
        {N_("/_Mark/Unignore thread"),  NULL, summary_unignore_thread, 0, NULL},
+       {N_("/_Mark/---"),              NULL, NULL, 0, "<Separator>"},
+       {N_("/_Mark/Mark as _spam"),    NULL, summary_mark_as_spam, 1, NULL},
+       {N_("/_Mark/Mark as _ham"),     NULL, summary_mark_as_spam, 0, NULL},
+       {N_("/_Mark/---"),              NULL, NULL, 0, "<Separator>"},
        {N_("/_Mark/Lock"),             NULL, summary_msgs_lock, 0, NULL},
        {N_("/_Mark/Unlock"),           NULL, summary_msgs_unlock, 0, NULL},
        {N_("/Color la_bel"),           NULL, NULL,             0, NULL},
@@ -720,6 +725,8 @@ void summary_init(SummaryView *summaryview)
                         &gpgsignedxpm, &gpgsignedxpmmask);
        stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_CLIP_GPG_SIGNED,
                         &clipgpgsignedxpm, &clipgpgsignedxpmmask);
+       stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_SPAM,
+                        &spamxpm, &spamxpmmask);
 
        summary_set_fonts(summaryview);
 
@@ -743,75 +750,11 @@ void summary_init(SummaryView *summaryview)
 
        summary_clear_list(summaryview);
        summary_set_column_titles(summaryview);
-       summary_colorlabel_menu_create(summaryview);
+       summary_colorlabel_menu_create(summaryview, FALSE);
        summary_set_menu_sensitive(summaryview);
 
 }
 
-#if 0
-GtkCTreeNode * summary_find_next_important_score(SummaryView *summaryview,
-                                                GtkCTreeNode *current_node)
-{
-       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
-       GtkCTreeNode *node;
-       MsgInfo *msginfo;
-       gint best_score = MIN_SCORE;
-       GtkCTreeNode *best_node = NULL;
-
-       if (current_node)
-               /*node = current_node;*/
-               node = GTK_CTREE_NODE_NEXT(current_node);
-       else
-               node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
-
-       for (; node != NULL; node = GTK_CTREE_NODE_NEXT(node)) {
-               msginfo = gtk_ctree_node_get_row_data(ctree, node);
-               if (msginfo->score >= summaryview->important_score)
-                       break;
-               if (msginfo->score > best_score) {
-                       best_score = msginfo->score;
-                       best_node = node;
-               }
-       }
-
-       if (node != NULL)
-               return node;
-       else
-               return best_node;
-}
-
-GtkCTreeNode * summary_find_prev_important_score(SummaryView *summaryview,
-                                                GtkCTreeNode *current_node)
-{
-       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
-       GtkCTreeNode *node;
-       MsgInfo *msginfo;
-       gint best_score = MIN_SCORE;
-       GtkCTreeNode *best_node = NULL;
-
-       if (current_node)
-               /*node = current_node;*/
-               node = GTK_CTREE_NODE_PREV(current_node);
-       else
-               node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
-
-       for (; node != NULL; node = GTK_CTREE_NODE_PREV(node)) {
-               msginfo = gtk_ctree_node_get_row_data(ctree, node);
-               if (msginfo->score >= summaryview->important_score)
-                       break;
-               if (msginfo->score > best_score) {
-                       best_score = msginfo->score;
-                       best_node = node;
-               }
-       }
-
-       if (node != NULL)
-               return node;
-       else
-               return best_node;
-}
-#endif
-
 #define CURRENTLY_DISPLAYED(m) \
 ( (m->msgnum == displayed_msgnum) \
   && (!g_ascii_strcasecmp(m->folder->name,item->name)) )
@@ -1017,11 +960,16 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 
        if (quicksearch_is_active(summaryview->quicksearch)) {
                GSList *not_killed;
-               int n = 0;
+               gint num = 0, total = summaryview->folder_item->total_msgs;
+               statusbar_print_all(_("Searching in %s... \n"), 
+                       summaryview->folder_item->path ? 
+                       summaryview->folder_item->path : "(null)");
                not_killed = NULL;
                for (cur = mlist ; cur != NULL && cur->data != NULL ; cur = g_slist_next(cur)) {
                        MsgInfo * msginfo = (MsgInfo *) cur->data;
 
+                       statusbar_progress_all(num++,total, 50);
+
                        if (!msginfo->hidden && quicksearch_match(summaryview->quicksearch, msginfo))
                                not_killed = g_slist_prepend(not_killed, msginfo);
                        else
@@ -1031,6 +979,9 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                                break;
                        }
                }
+               statusbar_progress_all(0,0,0);
+               statusbar_pop_all();
+               
                hidden_removed = TRUE;
                if (quicksearch_is_running(summaryview->quicksearch)) {
                        /* only scan subfolders when quicksearch changed,
@@ -1292,7 +1243,7 @@ GSList *summary_get_msg_list(SummaryView *summaryview)
        return mlist;
 }
 
-static void summary_set_menu_sensitive(SummaryView *summaryview)
+void summary_set_menu_sensitive(SummaryView *summaryview)
 {
        GtkItemFactory *ifactory = summaryview->popupfactory;
        SensitiveCond state;
@@ -1327,6 +1278,8 @@ static void summary_set_menu_sensitive(SummaryView *summaryview)
                {"/Mark/Ignore thread"          , M_TARGET_EXIST},
                {"/Mark/Lock"                   , M_TARGET_EXIST},
                {"/Mark/Unlock"                 , M_TARGET_EXIST},
+               {"/Mark/Mark as spam"           , M_TARGET_EXIST|M_CAN_LEARN_SPAM},
+               {"/Mark/Mark as ham"            , M_TARGET_EXIST|M_CAN_LEARN_SPAM},
                {"/Color label"                 , M_TARGET_EXIST},
 
                {"/Add sender to address book"  , M_SINGLE_TARGET_EXIST},
@@ -2738,7 +2691,7 @@ static void summary_display_msg_full(SummaryView *summaryview,
        GTK_EVENTS_FLUSH();
 
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
-
+       
        if (new_window) {
                MessageView *msgview;
 
@@ -2943,6 +2896,9 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row)
        if (MSG_IS_IGNORE_THREAD(flags)) {
                gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_STATUS],
                                          ignorethreadxpm, ignorethreadxpmmask);
+       } else if (MSG_IS_SPAM(flags)) {
+               gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_STATUS],
+                                         spamxpm, spamxpmmask);
        } else if (MSG_IS_NEW(flags)) {
                gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_STATUS],
                                          newxpm, newxpmmask);
@@ -2999,15 +2955,6 @@ static void summary_set_row_marks(SummaryView *summaryview, GtkCTreeNode *row)
                }
                        gtk_ctree_node_set_foreground
                                (ctree, row, &summaryview->color_marked);
-#if 0
-       } else if ((global_scoring ||
-                 summaryview->folder_item->prefs->scoring) &&
-                (msginfo->score >= summaryview->important_score) &&
-                (MSG_IS_MARKED(msginfo->flags) || MSG_IS_MOVE(msginfo->flags) || MSG_IS_COPY(msginfo->flags))) {
-               gtk_ctree_node_set_text(ctree, row, S_COL_MARK, "!");
-               gtk_ctree_node_set_foreground(ctree, row,
-                                             &summaryview->color_important);
-#endif
        } else {
                gtk_ctree_node_set_text(ctree, row, col_pos[S_COL_MARK], "");
        }
@@ -3201,6 +3148,56 @@ void summary_mark_all_read(SummaryView *summaryview)
        summary_status_show(summaryview);
 }
 
+void summary_mark_as_spam(SummaryView *summaryview, guint action, GtkWidget *widget)
+{
+       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
+       GList *cur;
+       gboolean is_spam = action;
+       GSList *msgs = NULL;
+       gboolean immediate_exec = prefs_common.immediate_exec;
+       gboolean moved = FALSE;
+       prefs_common.immediate_exec = FALSE;
+
+       START_LONG_OPERATION(summaryview);
+
+       for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next) {
+               GtkCTreeNode *row = GTK_CTREE_NODE(cur->data);
+               MsgInfo *msginfo = gtk_ctree_node_get_row_data(ctree, row);
+               msgs = g_slist_prepend(msgs, msginfo);
+       }
+       
+       if (procmsg_spam_learner_learn(NULL, msgs, is_spam) == 0) {
+               for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next) {
+                       GtkCTreeNode *row = GTK_CTREE_NODE(cur->data);
+                       MsgInfo *msginfo = gtk_ctree_node_get_row_data(ctree, row);
+                       if (is_spam) {
+                               summary_msginfo_change_flags(msginfo, MSG_SPAM, 0, MSG_NEW|MSG_UNREAD, 0);
+                               if (procmsg_spam_get_folder() != summaryview->folder_item) {
+                                       summary_move_row_to(summaryview, row, procmsg_spam_get_folder());
+                                       moved = TRUE;
+                               }
+                       } else {
+                               summary_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
+                       }
+               }
+       } else {
+               log_error(_("An error happened while learning.\n"));
+       }
+
+       g_slist_free(msgs);
+       
+       prefs_common.immediate_exec = immediate_exec;
+
+       END_LONG_OPERATION(summaryview);
+
+       if (prefs_common.immediate_exec && moved) {
+               summary_execute(summaryview);
+       }
+
+       summary_status_show(summaryview);       
+}
+
+
 static void summary_mark_row_as_unread(SummaryView *summaryview,
                                       GtkCTreeNode *row)
 {
@@ -3735,7 +3732,7 @@ void summary_save_as(SummaryView *summaryview)
        if (GTK_CLIST(ctree)->selection->next) {
                GList *item;
                for (item = GTK_CLIST(ctree)->selection->next; item != NULL; item=item->next) {
-                       msginfo = gtk_ctree_node_get_row_data(ctree, (GtkCTreeNode*)item->data);
+                       msginfo = gtk_ctree_node_get_row_data(ctree, GTK_CTREE_NODE(item->data));
                        if (!msginfo) break;
                        src = procmsg_get_message_file(msginfo);
                        if (append_file(src, dest, TRUE) < 0)
@@ -3838,6 +3835,8 @@ gboolean summary_execute(SummaryView *summaryview)
 
        gtk_clist_freeze(clist);
 
+       main_window_cursor_wait(summaryview->mainwin);
+
        if (summaryview->threaded)
                summary_unthread_for_exec(summaryview);
 
@@ -3906,7 +3905,9 @@ gboolean summary_execute(SummaryView *summaryview)
        gtk_ctree_node_moveto(ctree, summaryview->selected, 0, 0.5, 0);
 
        summary_unlock(summaryview);
-       
+
+       main_window_cursor_normal(summaryview->mainwin);
+
        if (move_val < 0) 
                summary_show(summaryview, summaryview->folder_item);
        return TRUE;
@@ -3928,8 +3929,9 @@ static gint summary_execute_move(SummaryView *summaryview)
                        procmsg_msginfo_free((MsgInfo *)cur->data);
                g_slist_free(summaryview->mlist);
                summaryview->mlist = NULL;
+               return val;
        }
-       return val;
+       return 0;
 }
 
 static void summary_execute_move_func(GtkCTree *ctree, GtkCTreeNode *node,
@@ -4478,6 +4480,7 @@ static void summary_colorlabel_menu_item_activate_item_cb(GtkMenuItem *menu_item
        if (!sel) return;
 
        menu = GTK_MENU_SHELL(summaryview->colorlabel_menu);
+       
        g_return_if_fail(menu != NULL);
 
        Xalloca(items, (N_COLOR_LABELS + 1) * sizeof(GtkWidget *), return);
@@ -4522,7 +4525,7 @@ static void summary_colorlabel_menu_item_activate_item_cb(GtkMenuItem *menu_item
                          GINT_TO_POINTER(0));
 }
 
-static void summary_colorlabel_menu_create(SummaryView *summaryview)
+static void summary_colorlabel_menu_create(SummaryView *summaryview, gboolean refresh)
 {
        GtkWidget *label_menuitem;
        GtkWidget *menu;
@@ -4551,13 +4554,19 @@ static void summary_colorlabel_menu_create(SummaryView *summaryview)
        g_object_set_data(G_OBJECT(item), "summaryview", summaryview);
        gtk_widget_show(item);
 
+       gtk_widget_add_accelerator(item, "activate", 
+                                  summaryview->popupfactory->accel_group, 
+                                  GDK_0, GDK_CONTROL_MASK,
+                                  GTK_ACCEL_LOCKED | GTK_ACCEL_VISIBLE);
+
        item = gtk_menu_item_new();
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
        gtk_widget_show(item);
 
        /* create pixmap/label menu items */
        for (i = 0; i < N_COLOR_LABELS; i++) {
-               item = colorlabel_create_check_color_menu_item(i);
+               item = colorlabel_create_check_color_menu_item(
+                       i, refresh, SUMMARY_COLORMENU);
                gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
                g_signal_connect(G_OBJECT(item), "activate",
                                 G_CALLBACK(summary_colorlabel_menu_item_activate_cb),
@@ -4635,11 +4644,6 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
        gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_DOTTED);
        gtk_ctree_set_expander_style(GTK_CTREE(ctree),
                                     GTK_CTREE_EXPANDER_SQUARE);
-#if 0
-       gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_NONE);
-       gtk_ctree_set_expander_style(GTK_CTREE(ctree),
-                                    GTK_CTREE_EXPANDER_TRIANGLE);
-#endif
        gtk_ctree_set_indent(GTK_CTREE(ctree), 12);
        g_object_set_data(G_OBJECT(ctree), "summaryview", (gpointer)summaryview); 
 
@@ -5009,6 +5013,10 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
        g_return_if_fail(msginfo != NULL);
 
+       toolbar_set_learn_button
+               (summaryview->mainwin->toolbar,
+                MSG_IS_SPAM(msginfo->flags)?LEARN_HAM:LEARN_SPAM);
+
        switch (column < 0 ? column : summaryview->col_state[column].type) {
        case S_COL_MARK:
                if (!MSG_IS_DELETED(msginfo->flags) &&
@@ -5025,6 +5033,11 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row,
                if (MSG_IS_UNREAD(msginfo->flags)) {
                        summary_mark_row_as_read(summaryview, row);
                        summary_status_show(summaryview);
+               } else if (MSG_IS_SPAM(msginfo->flags)) {
+                               if (procmsg_spam_learner_learn(msginfo, NULL, FALSE) == 0)
+                                       summary_msginfo_unset_flags(msginfo, MSG_SPAM, 0);
+                               else
+                                       log_error(_("An error happened while learning.\n"));
                } else if (!MSG_IS_REPLIED(msginfo->flags) &&
                         !MSG_IS_FORWARDED(msginfo->flags)) {
                        marked_unread = TRUE;
@@ -5673,6 +5686,7 @@ void summary_reflect_prefs_pixmap_theme(SummaryView *summaryview)
        stock_pixmap_gdk(ctree, STOCK_PIXMAP_KEY, &keyxpm, &keyxpmmask);
        stock_pixmap_gdk(ctree, STOCK_PIXMAP_GPG_SIGNED, &gpgsignedxpm, &gpgsignedxpmmask);
        stock_pixmap_gdk(ctree, STOCK_PIXMAP_CLIP_GPG_SIGNED, &clipgpgsignedxpm, &clipgpgsignedxpmmask);
+       stock_pixmap_gdk(ctree, STOCK_PIXMAP_SPAM, &spamxpm, &spamxpmmask);
 
        pixmap = stock_pixmap_widget(summaryview->hbox, STOCK_PIXMAP_DIR_OPEN);
        gtk_box_pack_start(GTK_BOX(summaryview->hbox), pixmap, FALSE, FALSE, 4);
@@ -5692,6 +5706,22 @@ void summary_reflect_prefs_pixmap_theme(SummaryView *summaryview)
        summary_set_column_titles(summaryview);
 }
 
+void summary_reflect_prefs_custom_colors(SummaryView *summaryview)
+{
+       GtkMenuShell *menu;
+       GList *cur;
+
+       /* re-create colorlabel submenu */
+       menu = GTK_MENU_SHELL(summaryview->colorlabel_menu);
+       g_return_if_fail(menu != NULL);
+
+       /* clear items. get item pointers. */
+       for (cur = menu->children; cur != NULL && cur->data != NULL; cur = cur->next) {
+               gtk_menu_item_remove_submenu(GTK_MENU_ITEM(cur->data));
+       }
+       summary_colorlabel_menu_create(summaryview, TRUE);
+}
+
 /*
  * Harvest addresses for selected messages in summary view.
  */
@@ -5755,15 +5785,6 @@ void summary_set_prefs_from_folderitem(SummaryView *summaryview, FolderItem *ite
        summaryview->thread_collapsed = item->thread_collapsed;
 
        /* Scoring */
-#if 0
-       if (global_scoring || item->prefs->scoring) {
-               summaryview->important_score = prefs_common.important_score;
-               if (item->prefs->important_score >
-                   summaryview->important_score)
-                       summaryview->important_score =
-                               item->prefs->important_score;
-       }
-#endif
 }
 
 void summary_save_prefs_to_folderitem(SummaryView *summaryview, FolderItem *item)