2007-07-27 [paul] 2.10.0cvs74
[claws.git] / src / summaryview.c
index 125fcae53bab98c62d0ca7a113ee62c368518707..7e2a1e392e86ad6c5edf3a6beb24ede4a08ade65 100644 (file)
@@ -4,7 +4,7 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -13,8 +13,8 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * 
  */
 
 #include "defs.h"
@@ -125,6 +125,8 @@ static GdkPixmap *forwardedxpm;
 static GdkBitmap *forwardedxpmmask;
 static GdkPixmap *ignorethreadxpm;
 static GdkBitmap *ignorethreadxpmmask;
+static GdkPixmap *watchthreadxpm;
+static GdkBitmap *watchthreadxpmmask;
 static GdkPixmap *lockedxpm;
 static GdkBitmap *lockedxpmmask;
 static GdkPixmap *spamxpm;
@@ -449,20 +451,26 @@ GtkTargetEntry summary_drag_types[2] =
 static GtkItemFactoryEntry summary_popup_entries[] =
 {
        {N_("/_Reply"),                 "<control>R", summary_reply_cb, COMPOSE_REPLY, NULL},
+#ifndef MAEMO
        {N_("/Repl_y to"),              NULL, NULL,             0, "<Branch>"},
        {N_("/Repl_y to/_all"),         "<shift><control>R", summary_reply_cb,  COMPOSE_REPLY_TO_ALL, NULL},
        {N_("/Repl_y to/_sender"),      NULL, summary_reply_cb, COMPOSE_REPLY_TO_SENDER, NULL},
        {N_("/Repl_y to/mailing _list"),
                                        "<control>L", summary_reply_cb, COMPOSE_REPLY_TO_LIST, NULL},
        {"/---",                        NULL, NULL,             0, "<Separator>"},
+#endif
        {N_("/_Forward"),               "<control><alt>F", summary_reply_cb, COMPOSE_FORWARD_INLINE, NULL},
+#ifndef MAEMO
        {N_("/For_ward as attachment"), NULL, summary_reply_cb, COMPOSE_FORWARD_AS_ATTACH, NULL},
        {N_("/Redirect"),               NULL, summary_reply_cb, COMPOSE_REDIRECT, NULL},
+#endif
        {"/---",                        NULL, NULL,             0, "<Separator>"},
        {N_("/M_ove..."),               "<control>O", summary_move_to,  0, NULL},
        {N_("/_Copy..."),               "<shift><control>O", summary_copy_to,   0, NULL},
        {N_("/Move to _trash"),         "<control>D", summary_delete_trash,     0, NULL},
+#ifndef MAEMO
        {N_("/_Delete..."),             NULL, summary_delete, 0, NULL},
+#endif
        {"/---",                        NULL, NULL,             0, "<Separator>"},
        {N_("/_Mark"),                  NULL, NULL,             0, "<Branch>"},
        {N_("/_Mark/_Mark"),            NULL, summary_mark,     0, NULL},
@@ -473,6 +481,8 @@ 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/Watch thread"),     NULL, summary_watch_thread, 0, NULL},
+       {N_("/_Mark/Unwatch thread"),   NULL, summary_unwatch_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},
@@ -483,8 +493,10 @@ static GtkItemFactoryEntry summary_popup_entries[] =
        {N_("/Ta_gs"),                  NULL, NULL,             0, NULL},
 
        {"/---",                        NULL, NULL,             0, "<Separator>"},
+#ifndef MAEMO
        {N_("/Add sender to address boo_k"),
                                        NULL, summary_add_address_cb, 0, NULL},
+#endif
        {N_("/Create f_ilter rule"),    NULL, NULL,             0, "<Branch>"},
        {N_("/Create f_ilter rule/_Automatically"),
                                        NULL, summary_create_filter_cb, FILTER_BY_AUTO, NULL},
@@ -494,6 +506,7 @@ static GtkItemFactoryEntry summary_popup_entries[] =
                                        NULL, summary_create_filter_cb, FILTER_BY_TO, NULL},
        {N_("/Create f_ilter rule/by _Subject"),
                                        NULL, summary_create_filter_cb, FILTER_BY_SUBJECT, NULL},
+#ifndef MAEMO
        {N_("/Create processing rule"), NULL, NULL,             0, "<Branch>"},
        {N_("/Create processing rule/_Automatically"),
                                        NULL, summary_create_processing_cb, FILTER_BY_AUTO, NULL},
@@ -503,15 +516,20 @@ static GtkItemFactoryEntry summary_popup_entries[] =
                                        NULL, summary_create_processing_cb, FILTER_BY_TO, NULL},
        {N_("/Create processing rule/by _Subject"),
                                        NULL, summary_create_processing_cb, FILTER_BY_SUBJECT, NULL},
+#endif
        {"/---",                        NULL, NULL,             0, "<Separator>"},
        {N_("/_View"),                  NULL, NULL,             0, "<Branch>"},
        {N_("/_View/Open in new _window"),
                                        "<control><alt>N", summary_open_msg,    0, NULL},
        {N_("/_View/Message _source"),  "<control>U", summary_view_source, 0, NULL},
+#ifndef MAEMO
        {N_("/_View/All _headers"),     "<control>H", summary_show_all_header_cb, 0, "<ToggleItem>"},
+#endif
        {"/---",                        NULL, NULL,             0, "<Separator>"},
        {N_("/_Save as..."),            "<control>S", summary_save_as,   0, NULL},
+#ifndef MAEMO
        {N_("/_Print..."),              "<control>P", summary_print,   0, NULL},
+#endif
 };  /* see also list in menu_connect_identical_items() in menu.c if this changes */
 
 static const gchar *const col_label[N_SUMMARY_COLS] = {
@@ -813,16 +831,23 @@ void summary_relayout(SummaryView *summaryview)
                gtk_box_pack_start(GTK_BOX(summaryview->stat_box2), summaryview->statlabel_msgs, FALSE, FALSE, 4);
                gtk_widget_show_all(summaryview->stat_box);
                gtk_widget_show_all(summaryview->stat_box2);
-               if (prefs_common.layout_mode == SMALL_LAYOUT)
+               if (prefs_common.layout_mode == SMALL_LAYOUT) {
                        gtk_widget_hide(summaryview->toggle_eventbox);
-               else
+                       gtk_widget_hide(summaryview->statlabel_msgs);
+               } else {
                        gtk_widget_show(summaryview->toggle_eventbox);
+                       gtk_widget_show(summaryview->statlabel_msgs);
+               }
                        
                break;
        }
        gtk_widget_unref(summaryview->hbox_l);
        gtk_widget_unref(summaryview->statlabel_msgs);
        quicksearch_relayout(summaryview->quicksearch);
+       if (prefs_common.show_searchbar)
+               quicksearch_show(summaryview->quicksearch);
+       else
+               quicksearch_hide(summaryview->quicksearch);
 }
 
 static void summary_set_fonts(SummaryView *summaryview)
@@ -908,6 +933,8 @@ void summary_init(SummaryView *summaryview)
                         &lockedxpm, &lockedxpmmask);
        stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_IGNORETHREAD,
                         &ignorethreadxpm, &ignorethreadxpmmask);
+       stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_WATCHTHREAD,
+                        &watchthreadxpm, &watchthreadxpmmask);
        stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_CLIP_KEY,
                         &clipkeyxpm, &clipkeyxpmmask);
        stock_pixmap_gdk(summaryview->ctree, STOCK_PIXMAP_KEY,
@@ -1552,19 +1579,25 @@ void summary_set_menu_sensitive(SummaryView *summaryview)
                SensitiveCond cond;
        } entry[] = {
                {"/Reply"                       , M_HAVE_ACCOUNT|M_TARGET_EXIST},
+#ifndef MAEMO
                {"/Reply to"                    , M_HAVE_ACCOUNT|M_TARGET_EXIST},
                {"/Reply to/all"                , M_HAVE_ACCOUNT|M_TARGET_EXIST},
                {"/Reply to/sender"             , M_HAVE_ACCOUNT|M_TARGET_EXIST},
                {"/Reply to/mailing list"       , M_HAVE_ACCOUNT|M_TARGET_EXIST},
+#endif
 
                {"/Forward"                     , M_HAVE_ACCOUNT|M_TARGET_EXIST},
+#ifndef MAEMO
                {"/Forward as attachment"       , M_HAVE_ACCOUNT|M_TARGET_EXIST},
                {"/Redirect"                    , M_HAVE_ACCOUNT|M_TARGET_EXIST},
+#endif
 
                {"/Move..."                     , M_TARGET_EXIST|M_ALLOW_DELETE|M_NOT_NEWS},
                {"/Copy..."                     , M_TARGET_EXIST|M_EXEC},
                {"/Move to trash"               , M_TARGET_EXIST|M_ALLOW_DELETE|M_NOT_NEWS},
+#ifndef MAEMO
                {"/Delete..."                   , M_TARGET_EXIST|M_ALLOW_DELETE},
+#endif
 
                {"/Mark"                        , M_TARGET_EXIST},
                {"/Mark/Mark"                   , M_TARGET_EXIST},
@@ -1580,16 +1613,24 @@ void summary_set_menu_sensitive(SummaryView *summaryview)
                {"/Color label"                 , M_TARGET_EXIST},
                {"/Tags"                        , M_TARGET_EXIST},
 
+#ifndef MAEMO
                {"/Add sender to address book"  , M_SINGLE_TARGET_EXIST},
+#endif
                {"/Create filter rule"          , M_SINGLE_TARGET_EXIST|M_UNLOCKED},
+#ifndef MAEMO
                {"/Create processing rule"      , M_SINGLE_TARGET_EXIST|M_UNLOCKED},
+#endif
 
                {"/View"                        , M_SINGLE_TARGET_EXIST},
                {"/View/Open in new window"     , M_SINGLE_TARGET_EXIST},
                {"/View/Message source"         , M_SINGLE_TARGET_EXIST},
+#ifndef MAEMO
                {"/View/All headers"            , M_SINGLE_TARGET_EXIST},
+#endif
                {"/Save as..."                  , M_TARGET_EXIST},
+#ifndef MAEMO
                {"/Print..."                    , M_TARGET_EXIST},
+#endif
                {NULL, 0}
        };
 
@@ -1604,6 +1645,7 @@ void summary_set_menu_sensitive(SummaryView *summaryview)
 
 
        summary_lock(summaryview);
+#ifndef MAEMO
        menuitem = gtk_item_factory_get_widget(ifactory, "/View/All headers");
        if (summaryview->messageview 
        &&  summaryview->messageview->mimeview
@@ -1611,6 +1653,7 @@ void summary_set_menu_sensitive(SummaryView *summaryview)
                gtk_check_menu_item_set_active
                        (GTK_CHECK_MENU_ITEM(menuitem),
                         summaryview->messageview->mimeview->textview->show_all_headers);
+#endif
        summary_unlock(summaryview);
 }
 
@@ -2409,22 +2452,47 @@ static void summary_status_show(SummaryView *summaryview)
                itstr = g_strdup("");
        }
                
-       str = g_strconcat(n_selected ? itos(n_selected) : "",
-                                       itstr, sel, spc, del, mv, cp, NULL);
-       gtk_label_set_text(GTK_LABEL(summaryview->statlabel_select), str);
-       g_free(str);
-       g_free(sel);
-       g_free(del);
-       g_free(mv);
-       g_free(cp);
-       g_free(itstr);
-
-       str = g_strdup_printf(_("%d new, %d unread, %d total (%s)"),
-
-                                     n_new, n_unread, n_total,
-                                     to_human_readable(n_size));
-       gtk_label_set_text(GTK_LABEL(summaryview->statlabel_msgs), str);
-       g_free(str);
+       if (prefs_common.layout_mode != SMALL_LAYOUT) {
+               str = g_strconcat(n_selected ? itos(n_selected) : "",
+                                               itstr, sel, spc, del, mv, cp, NULL);
+               g_free(sel);
+               g_free(del);
+               g_free(mv);
+               g_free(cp);
+               g_free(itstr);
+               
+               gtk_label_set_text(GTK_LABEL(summaryview->statlabel_select), str);
+               g_free(str);
+
+               str = g_strdup_printf(_("%d new, %d unread, %d total (%s)"),
+
+                                             n_new, n_unread, n_total,
+                                             to_human_readable(n_size));
+
+               gtk_label_set_text(GTK_LABEL(summaryview->statlabel_msgs), str);
+               g_free(str);
+       } else {
+               gchar *ssize, *tsize;
+               if (n_selected) {
+                       ssize = g_strdup(to_human_readable(sel_size));
+                       tsize = g_strdup(to_human_readable(n_size));
+                       str = g_strdup_printf(_("%d/%d selected (%s/%s), %d unread"),
+                               n_selected, n_total, ssize, tsize, n_unread);
+                       g_free(ssize);
+                       g_free(tsize);
+               } else
+                       str = g_strdup_printf(_("%d new, %d unread, %d total (%s)"),
+                               n_new, n_unread, n_total, to_human_readable(n_size));
+               g_free(sel);
+               g_free(del);
+               g_free(mv);
+               g_free(cp);
+               g_free(itstr);
+               
+               gtk_label_set_text(GTK_LABEL(summaryview->statlabel_select), str);
+               g_free(str);
+       }
+
        toolbar_main_set_sensitive(summaryview->mainwin);
 }
 
@@ -2452,8 +2520,7 @@ static void summary_set_column_titles(SummaryView *summaryview)
                SORT_BY_NUMBER,
                SORT_BY_SCORE,
                SORT_BY_LOCKED,
-               SORT_BY_TAGS,
-               SORT_BY_THREAD_DATE
+               SORT_BY_TAGS
        };
 
        for (pos = 0; pos < N_SUMMARY_COLS; pos++) {
@@ -2589,7 +2656,10 @@ void summary_reflect_prefs(void)
        }
 
        summary_set_column_titles(summaryview);
-       summary_show(summaryview, summaryview->folder_item);
+       summary_relayout(summaryview);
+       
+       if (summaryview->folder_item)
+               summary_show(summaryview, summaryview->folder_item);
 }
 
 void summary_sort(SummaryView *summaryview,
@@ -2705,7 +2775,7 @@ static void summary_find_thread_age(GNode *gnode)
 {
        MsgInfo *msginfo = (MsgInfo *)gnode->data;
        time_t most_recent;
-       gchar b[256],b2[256];
+
        if (!msginfo)
                return;
        most_recent = msginfo->thread_date = msginfo->date_t;
@@ -3426,6 +3496,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_WATCH_THREAD(flags)) {
+               gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_STATUS],
+                                         watchthreadxpm, watchthreadxpmmask);
        } else if (MSG_IS_SPAM(flags)) {
                gtk_ctree_node_set_pixmap(ctree, row, col_pos[S_COL_STATUS],
                                          spamxpm, spamxpmmask);
@@ -4369,6 +4442,17 @@ void summary_print(SummaryView *summaryview)
        gchar *p;
 #endif
        GList *cur;
+       gchar *msg = g_strdup_printf(_("You are about to print %d "
+                                      "messages, one by one. Do you "
+                                      "want to continue?"), 
+                                      g_list_length(clist->selection));
+       if (g_list_length(clist->selection) > 9
+       &&  alertpanel(_("Warning"), msg, GTK_STOCK_CANCEL, "+" GTK_STOCK_YES, NULL)
+           != G_ALERTALTERNATE) {
+               g_free(msg);
+               return;
+       }
+       g_free(msg);
 
        if (clist->selection == NULL) return;
 #ifndef USE_GNOMEPRINT
@@ -5351,6 +5435,11 @@ static void summary_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item,
                                        g_direct_hash,
                                        g_direct_equal,
                                        NULL, NULL);
+       GHashTable *menu_allsel_table = g_hash_table_new_full(
+                                       g_direct_hash,
+                                       g_direct_equal,
+                                       NULL, NULL);
+       gint sel_len;
        SummaryView *summaryview = (SummaryView *)data;
        g_return_if_fail(summaryview != NULL);
 
@@ -5374,11 +5463,13 @@ static void summary_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item,
                                (GTK_CHECK_MENU_ITEM(cur->data), FALSE);
                                
                        g_hash_table_insert(menu_table, GINT_TO_POINTER(id), GTK_CHECK_MENU_ITEM(cur->data));
+                       g_hash_table_insert(menu_allsel_table, GINT_TO_POINTER(id), GINT_TO_POINTER(0));
                }
        }
 
        /* iterate all messages and set the state of the appropriate
         * items */
+       sel_len = 0;
        for (; sel != NULL; sel = sel->next) {
                MsgInfo *msginfo;
                GSList *tags = NULL;
@@ -5387,33 +5478,49 @@ static void summary_tags_menu_item_activate_item_cb(GtkMenuItem *menu_item,
                msginfo = gtk_ctree_node_get_row_data
                        (GTK_CTREE(summaryview->ctree),
                         GTK_CTREE_NODE(sel->data));
+               sel_len++;
                if (msginfo) {
                        tags =  msginfo->tags;
                        if (!tags)
                                continue;
 
                        for (; tags; tags = tags->next) {
+                               gint num_checked = GPOINTER_TO_INT(g_hash_table_lookup(menu_allsel_table, tags->data));
                                id = GPOINTER_TO_INT(tags->data);
                                item = g_hash_table_lookup(menu_table, GINT_TO_POINTER(tags->data));
-                               if (item && !item->active)
+                               if (item && !item->active) {
                                        gtk_check_menu_item_set_active
                                                (item, TRUE);
+                               }
+                               num_checked++;
+                               g_hash_table_replace(menu_allsel_table, tags->data, GINT_TO_POINTER(num_checked));
                        }
                }
        }
 
+       for (cur = menu->children; cur != NULL && cur->data != NULL; cur = cur->next) {
+               if (GTK_IS_CHECK_MENU_ITEM(cur->data)) {
+                       gint id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cur->data),
+                               "tag_id"));
+                       gint num_checked = GPOINTER_TO_INT(g_hash_table_lookup(menu_allsel_table, GINT_TO_POINTER(id)));
+                       if (num_checked < sel_len && num_checked > 0)
+                               gtk_check_menu_item_set_inconsistent(GTK_CHECK_MENU_ITEM(cur->data), TRUE);
+                       else
+                               gtk_check_menu_item_set_inconsistent(GTK_CHECK_MENU_ITEM(cur->data), FALSE);
+               }
+       }
        g_hash_table_destroy(menu_table);
+       g_hash_table_destroy(menu_allsel_table);
        /* reset "dont_toggle" state */
        g_object_set_data(G_OBJECT(menu), "dont_toggle",
                          GINT_TO_POINTER(0));
 
 }
 
-static void summary_tags_menu_item_new_tag_activate_cb(GtkWidget *widget,
+static void summary_tags_menu_item_apply_tags_activate_cb(GtkWidget *widget,
                                                     gpointer data)
 {
        SummaryView *summaryview;
-       gint id;
 
        summaryview = g_object_get_data(G_OBJECT(widget), "summaryview");
        g_return_if_fail(summaryview != NULL);
@@ -5422,12 +5529,8 @@ static void summary_tags_menu_item_new_tag_activate_cb(GtkWidget *widget,
        if (g_object_get_data(G_OBJECT(summaryview->tags_menu),
                                "dont_toggle"))
                return;
-
-       id = prefs_tags_create_new(summaryview->mainwin);
-       if (id != -1) {
-               summary_set_tag(summaryview, id, NULL);
-               main_window_reflect_tags_changes(mainwindow_get_mainwindow());
-       }
+       
+       tag_apply_open(summary_get_selection(summaryview));     
 }
 
 static void summary_tags_menu_create(SummaryView *summaryview, gboolean refresh)
@@ -5472,14 +5575,20 @@ static void summary_tags_menu_create(SummaryView *summaryview, gboolean refresh)
                gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
                gtk_widget_show(item);
        }
-       item = gtk_menu_item_new_with_label(_("New tag..."));
+
+       item = gtk_menu_item_new_with_label(_("Apply tags..."));
+       gtk_widget_add_accelerator(item, "activate", 
+                  summaryview->popupfactory->accel_group, 
+                  GDK_T, GDK_CONTROL_MASK|GDK_SHIFT_MASK,
+                  GTK_ACCEL_LOCKED | GTK_ACCEL_VISIBLE);
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
        g_signal_connect(G_OBJECT(item), "activate",
-                        G_CALLBACK(summary_tags_menu_item_new_tag_activate_cb),
+                        G_CALLBACK(summary_tags_menu_item_apply_tags_activate_cb),
                         NULL);
        g_object_set_data(G_OBJECT(item), "summaryview",
                          summaryview);
        gtk_widget_show(item);
+
        g_slist_free(orig);
        gtk_widget_show(menu);
        gtk_menu_item_set_submenu(GTK_MENU_ITEM(label_menuitem), menu);
@@ -5519,6 +5628,9 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
        ctree = gtk_sctree_new_with_titles
                (N_SUMMARY_COLS, col_pos[S_COL_SUBJECT], titles);
 
+       if (prefs_common.show_col_headers == FALSE)
+               gtk_clist_column_titles_hide(GTK_CLIST(ctree));
+
        gtk_clist_set_selection_mode(GTK_CLIST(ctree), GTK_SELECTION_EXTENDED);
        gtk_clist_set_column_justification(GTK_CLIST(ctree), col_pos[S_COL_MARK],
                                           GTK_JUSTIFY_CENTER);
@@ -5878,6 +5990,7 @@ static gboolean summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
        case GDK_y:
        case GDK_t:
        case GDK_l:
+       case GDK_o:
        case GDK_c:
        case GDK_a:
                if ((event->state & (GDK_MOD1_MASK|GDK_CONTROL_MASK)) == 0) {
@@ -6590,6 +6703,7 @@ static void summary_ignore_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpoin
        msginfo = gtk_ctree_node_get_row_data(ctree, row);
        g_return_if_fail(msginfo);
 
+       summary_msginfo_unset_flags(msginfo, MSG_WATCH_THREAD, 0);
        summary_msginfo_change_flags(msginfo, MSG_IGNORE_THREAD, 0, MSG_NEW | MSG_UNREAD, 0);
 
        summary_set_row_marks(summaryview, row);
@@ -6676,6 +6790,100 @@ void summary_toggle_ignore_thread(SummaryView *summaryview)
                summary_ignore_thread(summaryview);
 }
 
+static void summary_watch_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpointer data)
+{
+       SummaryView *summaryview = (SummaryView *) data;
+       MsgInfo *msginfo;
+
+       msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
+
+       summary_msginfo_change_flags(msginfo, MSG_WATCH_THREAD, 0, MSG_IGNORE_THREAD, 0);
+
+       summary_set_row_marks(summaryview, row);
+       debug_print("Message %d is marked as watch thread\n",
+           msginfo->msgnum);
+}
+
+void summary_watch_thread(SummaryView *summaryview)
+{
+       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
+       GList *cur;
+       gboolean froze = FALSE;
+
+       START_LONG_OPERATION(summaryview, FALSE);
+       for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
+               gtk_ctree_pre_recursive(ctree, GTK_CTREE_NODE(cur->data), 
+                                       GTK_CTREE_FUNC(summary_watch_thread_func), 
+                                       summaryview);
+
+       END_LONG_OPERATION(summaryview);
+
+       summary_status_show(summaryview);
+}
+
+static void summary_unwatch_thread_func(GtkCTree *ctree, GtkCTreeNode *row, gpointer data)
+{
+       SummaryView *summaryview = (SummaryView *) data;
+       MsgInfo *msginfo;
+
+       msginfo = gtk_ctree_node_get_row_data(ctree, row);
+       g_return_if_fail(msginfo);
+
+       summary_msginfo_unset_flags(msginfo, MSG_WATCH_THREAD, 0);
+
+       summary_set_row_marks(summaryview, row);
+       debug_print("Message %d is marked as unwatch thread\n",
+           msginfo->msgnum);
+}
+
+void summary_unwatch_thread(SummaryView *summaryview)
+{
+       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
+       GList *cur;
+       gboolean froze = FALSE;
+
+       START_LONG_OPERATION(summaryview, FALSE);
+       for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
+               gtk_ctree_pre_recursive(ctree, GTK_CTREE_NODE(cur->data), 
+                                       GTK_CTREE_FUNC(summary_unwatch_thread_func), 
+                                       summaryview);
+
+       END_LONG_OPERATION(summaryview);
+
+       summary_status_show(summaryview);
+}
+
+static void summary_check_watch_thread_func
+               (GtkCTree *ctree, GtkCTreeNode *row, gpointer data)
+{
+       MsgInfo *msginfo;
+       gint *found_watch = (gint *) data;
+
+       if (*found_watch) return;
+       else {
+               msginfo = gtk_ctree_node_get_row_data(ctree, row);
+               *found_watch = msginfo && MSG_IS_WATCH_THREAD(msginfo->flags);
+       }               
+}
+
+void summary_toggle_watch_thread(SummaryView *summaryview)
+{
+       GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
+       GList *cur;
+       gint found_watch = 0;
+
+       for (cur = GTK_CLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
+               gtk_ctree_pre_recursive(ctree, GTK_CTREE_NODE(cur->data),
+                                       GTK_CTREE_FUNC(summary_check_watch_thread_func),
+                                       &found_watch);
+
+       if (found_watch) 
+               summary_unwatch_thread(summaryview);
+       else 
+               summary_watch_thread(summaryview);
+}
+
 void summary_toggle_show_read_messages(SummaryView *summaryview)
 {
        FolderItemUpdateData source;
@@ -6719,6 +6927,7 @@ void summary_reflect_prefs_pixmap_theme(SummaryView *summaryview)
        stock_pixmap_gdk(ctree, STOCK_PIXMAP_CLIP, &clipxpm, &clipxpmmask);
        stock_pixmap_gdk(ctree, STOCK_PIXMAP_LOCKED, &lockedxpm, &lockedxpmmask);
        stock_pixmap_gdk(ctree, STOCK_PIXMAP_IGNORETHREAD, &ignorethreadxpm, &ignorethreadxpmmask);
+       stock_pixmap_gdk(ctree, STOCK_PIXMAP_WATCHTHREAD, &watchthreadxpm, &watchthreadxpmmask);
        stock_pixmap_gdk(ctree, STOCK_PIXMAP_CLIP_KEY, &clipkeyxpm, &clipkeyxpmmask);
        stock_pixmap_gdk(ctree, STOCK_PIXMAP_KEY, &keyxpm, &keyxpmmask);
        stock_pixmap_gdk(ctree, STOCK_PIXMAP_GPG_SIGNED, &gpgsignedxpm, &gpgsignedxpmmask);