Fix marking all as (un)read recursively when the confirmation
[claws.git] / src / folderview.c
index 22b84096629b1327089a774ebcc87a519fd51251..d48a8de9a5e3bdad0f9682b04c28002ae4cb9a00 100644 (file)
@@ -121,9 +121,7 @@ static GdkPixbuf *m_queueopenhrmxpm;
 static GdkPixbuf *m_draftsxpm;
 static GdkPixbuf *m_draftsopenxpm;
 static GdkPixbuf *m_foldersubsxpm;
-static GdkPixbuf *m_foldersubsopenxpm;
 static GdkPixbuf *m_foldernoselectxpm;
-static GdkPixbuf *m_foldernoselectopenxpm;
 
 static GdkPixbuf *newxpm;
 static GdkPixbuf *unreadxpm;
@@ -171,14 +169,19 @@ static void folderview_col_resized        (GtkCMCList     *clist,
                                         gint            width,
                                         FolderView     *folderview);
 
-static void mark_all_read_handler      (GtkAction      *action,
+static void mark_all_read_unread_handler       (GtkAction      *action,
                                         gpointer        data,
-                                        gboolean        recursive);
+                                        gboolean        recursive,
+                                        gboolean        read);
 
 static void mark_all_read_cb            (GtkAction     *action,
                                         gpointer        data);
+static void mark_all_unread_cb            (GtkAction   *action,
+                                        gpointer        data);
 static void mark_all_read_recursive_cb  (GtkAction     *action,
                                         gpointer        data);
+static void mark_all_unread_recursive_cb  (GtkAction   *action,
+                                        gpointer        data);
 
 static void folderview_empty_trash_cb  (GtkAction      *action,
                                         gpointer        data);
@@ -240,16 +243,18 @@ GHashTable *folderview_popups;
 
 static GtkActionEntry folderview_common_popup_entries[] = 
 {
-       {"FolderViewPopup",                     NULL, "FolderViewPopup" },
-       {"FolderViewPopup/MarkAllRead",         NULL, N_("Mark all re_ad"), NULL, NULL, G_CALLBACK(mark_all_read_cb) },
-       {"FolderViewPopup/MarkAllReadRec",      NULL, N_("Mark all read recursi_vely"), NULL, NULL, G_CALLBACK(mark_all_read_recursive_cb) },
-       {"FolderViewPopup/---",                 NULL, "---" },
-       {"FolderViewPopup/RunProcessing",       NULL, N_("R_un processing rules"), NULL, NULL, G_CALLBACK(folderview_run_processing_cb) },
-       {"FolderViewPopup/SearchFolder",        NULL, N_("_Search folder..."), NULL, NULL, G_CALLBACK(folderview_search_cb) },
-       {"FolderViewPopup/Properties",          NULL, N_("_Properties..."), NULL, NULL, G_CALLBACK(folderview_property_cb) },
-       {"FolderViewPopup/Processing",          NULL, N_("Process_ing..."), NULL, NULL, G_CALLBACK(folderview_processing_cb) },
-       {"FolderViewPopup/EmptyTrash",          NULL, N_("Empty _trash..."), NULL, NULL, G_CALLBACK(folderview_empty_trash_cb) },
-       {"FolderViewPopup/SendQueue",           NULL, N_("Send _queue..."), NULL, NULL, G_CALLBACK(folderview_send_queue_cb) },
+       {"FolderViewPopup",                  NULL, "FolderViewPopup", NULL, NULL , NULL},
+       {"FolderViewPopup/MarkAllRead",      NULL, N_("Mark all re_ad"), NULL, NULL, G_CALLBACK(mark_all_read_cb) },
+       {"FolderViewPopup/MarkAllUnread",    NULL, N_("Mark all u_nread"), NULL, NULL, G_CALLBACK(mark_all_unread_cb) },
+       {"FolderViewPopup/MarkAllReadRec",   NULL, N_("Mark all read recursi_vely"), NULL, NULL, G_CALLBACK(mark_all_read_recursive_cb) },
+       {"FolderViewPopup/MarkAllUnreadRec", NULL, N_("Mark all unread recursi_vely"), NULL, NULL, G_CALLBACK(mark_all_unread_recursive_cb) },
+       {"FolderViewPopup/---",              NULL, "---", NULL, NULL , NULL},
+       {"FolderViewPopup/RunProcessing",    NULL, N_("R_un processing rules"), NULL, NULL, G_CALLBACK(folderview_run_processing_cb) },
+       {"FolderViewPopup/SearchFolder",     NULL, N_("_Search folder..."), NULL, NULL, G_CALLBACK(folderview_search_cb) },
+       {"FolderViewPopup/Properties",       NULL, N_("_Properties..."), NULL, NULL, G_CALLBACK(folderview_property_cb) },
+       {"FolderViewPopup/Processing",       NULL, N_("Process_ing..."), NULL, NULL, G_CALLBACK(folderview_processing_cb) },
+       {"FolderViewPopup/EmptyTrash",       NULL, N_("Empty _trash..."), NULL, NULL, G_CALLBACK(folderview_empty_trash_cb) },
+       {"FolderViewPopup/SendQueue",        NULL, N_("Send _queue..."), NULL, NULL, G_CALLBACK(folderview_send_queue_cb) },
        
 };
 
@@ -683,9 +688,7 @@ void folderview_init(FolderView *folderview)
        stock_pixbuf_gdk(STOCK_PIXMAP_QUEUE_OPEN_HRM_MARK, &m_queueopenhrmxpm);
        stock_pixbuf_gdk(STOCK_PIXMAP_DRAFTS_CLOSE_MARK, &m_draftsxpm);
        stock_pixbuf_gdk(STOCK_PIXMAP_DRAFTS_OPEN_MARK, &m_draftsopenxpm);
-       stock_pixbuf_gdk(STOCK_PIXMAP_DIR_SUBS_OPEN_MARK, &m_foldersubsopenxpm);
        stock_pixbuf_gdk(STOCK_PIXMAP_DIR_SUBS_CLOSE_MARK, &m_foldersubsxpm);
-       stock_pixbuf_gdk(STOCK_PIXMAP_DIR_NOSELECT_OPEN_MARK, &m_foldernoselectopenxpm);
        stock_pixbuf_gdk(STOCK_PIXMAP_DIR_NOSELECT_CLOSE_MARK, &m_foldernoselectxpm);
 
        normal_font = pango_font_description_from_string(NORMAL_FONT);
@@ -829,33 +832,53 @@ void folderview_select(FolderView *folderview, FolderItem *item)
 
 static void mark_all_read_cb(GtkAction *action, gpointer data)
 {
-       mark_all_read_handler(action, data, FALSE);
+       mark_all_read_unread_handler(action, data, FALSE, TRUE);
+}
+
+static void mark_all_unread_cb(GtkAction *action, gpointer data)
+{
+       mark_all_read_unread_handler(action, data, FALSE, FALSE);
 }
 
 static void mark_all_read_recursive_cb(GtkAction *action, gpointer data)
 {
-       mark_all_read_handler(action, data, TRUE);
+       mark_all_read_unread_handler(action, data, TRUE, TRUE);
+}
+
+static void mark_all_unread_recursive_cb(GtkAction *action, gpointer data)
+{
+       mark_all_read_unread_handler(action, data, TRUE, FALSE);
 }
 
-static void mark_all_read_handler(GtkAction *action, gpointer data, gboolean recursive)
+static void mark_all_read_unread_handler(GtkAction *action, gpointer data,
+                                               gboolean recursive, gboolean read)
 {
        FolderView *folderview = (FolderView *)data;
        FolderItem *item;
        AlertValue val;
        gchar *message;
+       gchar *title;
        
        item = folderview_get_selected_item(folderview);
        if (item == NULL)
                return;
 
-       message = recursive? _("Do you really want to mark all mails in this "
-                              "folder and its sub-folders as read?") :
-                            _("Do you really want to mark all mails in this "
-                              "folder as read?");
-       if (folderview->summaryview->folder_item != item &&
-           prefs_common.ask_mark_all_read) {
-               val = alertpanel_full(_("Mark all as read"),
-                         message, GTK_STOCK_NO, GTK_STOCK_YES, NULL,
+       if (read) {
+               title = _("Mark all as read");
+               message = recursive? _("Do you really want to mark all mails in this "
+                                                       "folder and its sub-folders as read?") :
+                                                       _("Do you really want to mark all mails in this "
+                                                       "folder as read?");
+       } else {
+               title = _("Mark all as unread");
+               message = recursive? _("Do you really want to mark all mails in this "
+                                                       "folder and its sub-folders as unread?") :
+                                                       _("Do you really want to mark all mails in this "
+                                                       "folder as unread?");
+       }
+       if (prefs_common.ask_mark_all_read) {
+               val = alertpanel_full(title, message,
+                         GTK_STOCK_NO, GTK_STOCK_YES, NULL,
                          TRUE, NULL, ALERT_QUESTION, G_ALERTDEFAULT);
 
                if ((val & ~G_ALERTDISABLE) != G_ALERTALTERNATE)
@@ -870,11 +893,17 @@ static void mark_all_read_handler(GtkAction *action, gpointer data, gboolean rec
        else
                summary_freeze(folderview->summaryview);
                
-       if (recursive)
-               folderutils_mark_all_read_recursive(item);
-       else
-               folderutils_mark_all_read(item);
-       
+       if (read) {
+               if (recursive)
+                       folderutils_mark_all_read_recursive(item);
+               else
+                       folderutils_mark_all_read(item);
+       } else {
+               if (recursive)
+                       folderutils_mark_all_unread_recursive(item);
+               else
+                       folderutils_mark_all_unread(item);
+       }
        if (folderview->summaryview->folder_item != item && !recursive)
                summary_unlock(folderview->summaryview);
        else
@@ -902,7 +931,8 @@ static void folderview_select_node(FolderView *folderview, GtkCMCTreeNode *node)
        if ((folderview->summaryview->folder_item &&
            folderview->summaryview->folder_item->total_msgs > 0) ||
             prefs_common.layout_mode == SMALL_LAYOUT)
-               summary_grab_focus(folderview->summaryview);
+               summary_select_node(folderview->summaryview,
+                                   folderview->summaryview->selected, -1);
        else
                gtk_widget_grab_focus(folderview->ctree);
 }
@@ -946,6 +976,10 @@ static GtkCMCTreeNode *folderview_find_next_with_flag(GtkCMCTree *ctree,
                        if(item->marked_msgs > 0)
                                return node;
                        break;
+               default:
+                       if(item->total_msgs > 0)
+                               return node;
+                       break;
                }
        }
 
@@ -953,13 +987,11 @@ static GtkCMCTreeNode *folderview_find_next_with_flag(GtkCMCTree *ctree,
 }
 
 void folderview_select_next_with_flag(FolderView *folderview,
-                                     MsgPermFlags flag,
-                                     gboolean force_open)
+                                     MsgPermFlags flag)
 {
        GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
        GtkCMCTreeNode *node = NULL;
        EntryAction last_summary_select_prio = prefs_common.summary_select_prio[0];
-       gboolean last_open = prefs_common.always_show_msg;
        
        switch (flag) {
        case MSG_UNREAD:
@@ -971,8 +1003,10 @@ void folderview_select_next_with_flag(FolderView *folderview,
        case MSG_MARKED:
                prefs_common.summary_select_prio[0] = ACTION_MARKED;
                break;
+       default:
+               prefs_common.summary_select_prio[0] = ACTION_FIRST_LIST;
+               break;
        }
-       prefs_common.always_show_msg = force_open ? OPENMSG_ALWAYS : last_open;
 
        node = folderview_find_next_with_flag(ctree, folderview->opened, flag);
        if (node != NULL) {
@@ -992,7 +1026,6 @@ void folderview_select_next_with_flag(FolderView *folderview,
 
 out:
        prefs_common.summary_select_prio[0] = last_summary_select_prio;
-       prefs_common.always_show_msg = last_open;
 }
 
 FolderItem *folderview_get_selected_item(FolderView *folderview)
@@ -1355,6 +1388,48 @@ static gboolean folderview_have_unread_children(FolderView *folderview,
        return folderview_have_unread_children_sub(folderview, item, FALSE);
 }
 
+static gboolean folderview_have_read_children_sub(FolderView *folderview,
+                                                   FolderItem *item, 
+                                                   gboolean in_sub)
+{
+       GNode *node = NULL;
+       
+       if (!item || !item->folder || !item->folder->node) {
+               return FALSE;
+       }                       
+
+       node = item->folder->node;
+       
+       node = g_node_find(node, G_PRE_ORDER, G_TRAVERSE_ALL, item);
+       node = node->children;
+
+       if (in_sub &&
+           (((item->total_msgs > 0) &&
+               (item->unread_msgs != (item->total_msgs - item->ignored_msgs))))) {
+               return TRUE;
+       }
+
+       while (node != NULL) {
+               if (node && node->data) {
+                       FolderItem *next_item = (FolderItem*) node->data;
+                       node = node->next;
+                       if (folderview_have_read_children_sub(folderview, 
+                                                               next_item, 
+                                                               TRUE)) {
+                               return TRUE;
+                       }
+               }
+       }
+
+       return FALSE;
+}
+
+static gboolean folderview_have_read_children(FolderView *folderview,
+                                               FolderItem *item)
+{
+       return folderview_have_read_children_sub(folderview, item, FALSE);
+}
+
 static gboolean folderview_have_matching_children_sub(FolderView *folderview,
                                                      FolderItem *item,
                                                      gboolean in_sub)
@@ -1512,10 +1587,10 @@ static void folderview_update_node(FolderView *folderview, GtkCMCTreeNode *node)
                    FOLDER_TYPE(item->folder) == F_IMAP &&
                    item->folder->account->imap_subsonly) {
                        xpm = mark?m_foldersubsxpm:foldersubsxpm;
-                       openxpm = mark?m_foldersubsopenxpm:foldersubsopenxpm;
+                       openxpm = foldersubsopenxpm;
                } else if (item->no_select) {
                        xpm = mark?m_foldernoselectxpm:foldernoselectxpm;
-                       openxpm = mark?m_foldernoselectopenxpm:foldernoselectopenxpm;
+                       openxpm = foldernoselectopenxpm;
                } else if (item->hide_read_msgs || item->hide_read_threads) {
                        xpm = mark?m_folderhrmxpm:folderhrmxpm;
                        openxpm = mark?m_folderopenhrmxpm:folderopenhrmxpm;
@@ -1874,7 +1949,9 @@ static void folderview_set_sens_and_popup_menu(FolderView *folderview, gint row,
                fpopup->add_menuitems(ui_manager, item);
 
        MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "MarkAllRead", "FolderViewPopup/MarkAllRead", GTK_UI_MANAGER_MENUITEM)
+       MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "MarkAllUnread", "FolderViewPopup/MarkAllUnread", GTK_UI_MANAGER_MENUITEM)
        MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "MarkAllReadRec", "FolderViewPopup/MarkAllReadRec", GTK_UI_MANAGER_MENUITEM)
+       MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "MarkAllUnreadRec", "FolderViewPopup/MarkAllUnreadRec", GTK_UI_MANAGER_MENUITEM)
        MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "Separator1", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
        MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RunProcessing", "FolderViewPopup/RunProcessing", GTK_UI_MANAGER_MENUITEM)
        MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SearchFolder", "FolderViewPopup/SearchFolder", GTK_UI_MANAGER_MENUITEM)
@@ -1904,9 +1981,12 @@ static void folderview_set_sens_and_popup_menu(FolderView *folderview, gint row,
 #define SET_SENS(name, sens) \
        cm_menu_set_sensitive_full(ui_manager, "Popup/"name, sens)
 
-       SET_SENS("FolderViewPopup/MarkAllRead", item->unread_msgs >= 1);
+       SET_SENS("FolderViewPopup/MarkAllRead", item->unread_msgs > 0);
+       SET_SENS("FolderViewPopup/MarkAllUnread", (item->total_msgs > 0) &&
+               (item->unread_msgs != (item->total_msgs - item->ignored_msgs)));
        SET_SENS("FolderViewPopup/MarkAllReadRec", folderview_have_unread_children(folderview,item));
-       SET_SENS("FolderViewPopup/SearchFolder", item->total_msgs >= 1 && 
+       SET_SENS("FolderViewPopup/MarkAllUnreadRec", folderview_have_read_children(folderview,item));
+       SET_SENS("FolderViewPopup/SearchFolder", item->total_msgs > 0 && 
                 folderview->selected == folderview->opened);
        SET_SENS("FolderViewPopup/Properties", TRUE);
 
@@ -2065,7 +2145,7 @@ static gboolean folderview_key_pressed(GtkWidget *widget, GdkEventKey *event,
                        if (folderview->opened == folderview->selected &&
                            (!folderview->summaryview->folder_item ||
                             folderview->summaryview->folder_item->total_msgs == 0))
-                               folderview_select_next_with_flag(folderview, MSG_UNREAD, TRUE);
+                               folderview_select_next_with_flag(folderview, MSG_UNREAD);
                        else
                                folderview_select_node(folderview,
                                                       folderview->selected);
@@ -2721,8 +2801,19 @@ void folderview_reflect_prefs(void)
        last_boldfont = g_strdup(BOLD_FONT);
        last_derive = prefs_common.derive_from_normal_font;
 
-       normal_style = normal_color_style = bold_style =
-               bold_color_style = bold_tgtfold_style = NULL;
+#define STYLE_FREE(s)                  \
+       if (s != NULL) {                \
+               g_object_unref(s);      \
+               s = NULL;               \
+       }
+
+       STYLE_FREE(normal_style);
+       STYLE_FREE(normal_color_style);
+       STYLE_FREE(bold_style);
+       STYLE_FREE(bold_color_style);
+       STYLE_FREE(bold_tgtfold_style);
+
+#undef STYLE_FREE
 
        folderview_init(folderview);
        gtk_cmclist_freeze(GTK_CMCLIST(folderview->ctree));