Add new mark-all-unread (and recursively when relevant) action to folder
authorwwp <wwp@free.fr>
Mon, 12 Dec 2016 14:17:15 +0000 (15:17 +0100)
committerwwp <wwp@free.fr>
Mon, 12 Dec 2016 14:17:15 +0000 (15:17 +0100)
context menu, message list and main window menu.

src/folderutils.c
src/folderutils.h
src/folderview.c
src/mainwindow.c
src/summaryview.c
src/summaryview.h

index 0a27229..939b019 100644 (file)
@@ -132,7 +132,7 @@ void folderutils_mark_all_read(FolderItem *item)
        if (mainwin && mainwin->summaryview &&
            mainwin->summaryview->folder_item == item) {
                debug_print("folder opened, using summary\n");
-               summary_mark_all_read(mainwin->summaryview);
+               summary_mark_all_read(mainwin->summaryview, TRUE);
        } else {
                msglist = folder_item_get_msg_list(item);
                debug_print("got msglist %p\n", msglist);
@@ -159,6 +159,46 @@ void folderutils_mark_all_read(FolderItem *item)
        folder_item_update_thaw();
 }
 
+void folderutils_mark_all_unread(FolderItem *item)
+{
+       MsgInfoList *msglist, *cur;
+       MainWindow *mainwin = mainwindow_get_mainwindow();
+       int i = 0, m = 0;
+       debug_print("marking all unread in item %s\n", (item==NULL)?"NULL":item->name);
+       cm_return_if_fail(item != NULL);
+
+
+       folder_item_update_freeze();
+       if (mainwin && mainwin->summaryview &&
+           mainwin->summaryview->folder_item == item) {
+               debug_print("folder opened, using summary\n");
+               summary_mark_all_read(mainwin->summaryview, FALSE);
+       } else {
+               msglist = folder_item_get_msg_list(item);
+               debug_print("got msglist %p\n", msglist);
+               if (msglist == NULL) {
+                       folder_item_update_thaw();
+                       return;
+               }
+               folder_item_set_batch(item, TRUE);
+               for (cur = msglist; cur != NULL; cur = g_slist_next(cur)) {
+                       MsgInfo *msginfo = cur->data;
+
+                       if (!(msginfo->flags.perm_flags & MSG_UNREAD)) {
+                               procmsg_msginfo_set_flags(msginfo, MSG_UNREAD, 0);
+                               m++;
+                       }
+                       i++;
+                       procmsg_msginfo_free(&msginfo);
+               }
+               folder_item_set_batch(item, FALSE);
+               folder_item_close(item);
+               debug_print("marked %d messages out of %d as unread\n", m, i);
+               g_slist_free(msglist);
+       }
+       folder_item_update_thaw();
+}
+
 void folderutils_mark_all_read_recursive(FolderItem *item)
 {
        GNode *node;
@@ -182,3 +222,27 @@ void folderutils_mark_all_read_recursive(FolderItem *item)
                }
        }
 }
+
+void folderutils_mark_all_unread_recursive(FolderItem *item)
+{
+       GNode *node;
+
+       cm_return_if_fail(item != NULL);
+
+       folderutils_mark_all_unread(item);
+
+       cm_return_if_fail(item->folder != NULL);
+       cm_return_if_fail(item->folder->node != NULL);
+
+       node = item->folder->node;
+       node = g_node_find(node, G_PRE_ORDER, G_TRAVERSE_ALL, item);
+       node = node->children;
+
+       while (node != NULL) {
+               if (node->data != NULL) {
+                       FolderItem *sub_item = (FolderItem *) node->data;
+                       node = node->next;
+                       folderutils_mark_all_unread_recursive(sub_item);
+               }
+       }
+}
index ca404c5..64a5c2e 100644 (file)
@@ -30,6 +30,8 @@ typedef enum {
 gint folderutils_delete_duplicates(FolderItem *item,
                                   DeleteDuplicatesMode mode);
 void folderutils_mark_all_read   (FolderItem *item);
+void folderutils_mark_all_unread         (FolderItem *item);
 void folderutils_mark_all_read_recursive         (FolderItem *item);
+void folderutils_mark_all_unread_recursive       (FolderItem *item);
 
 #endif /* FOLDERUTILS_H */
index 8469ee9..3fe8ccc 100644 (file)
@@ -169,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,7 +245,9 @@ 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/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, "---" },
        {"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) },
@@ -825,33 +832,54 @@ 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_read_handler(GtkAction *action, gpointer data, gboolean recursive)
+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_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 (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 (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,
+               val = alertpanel_full(title, message,
+                         GTK_STOCK_NO, GTK_STOCK_YES, NULL,
                          TRUE, NULL, ALERT_QUESTION, G_ALERTDEFAULT);
 
                if ((val & ~G_ALERTDISABLE) != G_ALERTALTERNATE)
@@ -866,11 +894,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
@@ -1355,6 +1389,52 @@ 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;
+                       }
+               }
+       }
+
+debug_print("-> false 2 %s\n", item->name);
+       return FALSE;
+}
+
+static gboolean folderview_have_read_children(FolderView *folderview,
+                                               FolderItem *item)
+{
+gboolean ret;
+        ret = folderview_have_read_children_sub(folderview, item, FALSE);
+debug_print("-> %s 0 (%d)\n", ret?"true":"false", ret);
+       return ret;
+}
+
 static gboolean folderview_have_matching_children_sub(FolderView *folderview,
                                                      FolderItem *item,
                                                      gboolean in_sub)
@@ -1874,7 +1954,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 +1986,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);
 
index e03c55e..1500488 100644 (file)
@@ -231,6 +231,8 @@ static void mark_as_read_cb         (GtkAction      *action,
                                  gpointer       data);
 static void mark_all_read_cb           (GtkAction      *action,
                                  gpointer       data);
+static void mark_all_unread_cb         (GtkAction      *action,
+                                 gpointer       data);
 static void mark_as_spam_cb            (GtkAction      *action,
                                  gpointer       data);
 static void mark_as_ham_cb             (GtkAction      *action,
@@ -704,6 +706,7 @@ static GtkActionEntry mainwin_entries[] =
        {"Message/Mark/MarkRead",               NULL, N_("Mark as rea_d"), NULL, NULL, G_CALLBACK(mark_as_read_cb) },
        /* separation */
        {"Message/Mark/MarkAllRead",            NULL, N_("Mark all read"), NULL, NULL, G_CALLBACK(mark_all_read_cb) },
+       {"Message/Mark/MarkAllUnread",          NULL, N_("Mark all unread"), NULL, NULL, G_CALLBACK(mark_all_unread_cb) },
        /* separation */
        {"Message/Mark/IgnoreThread",           NULL, N_("Ignore thread"), NULL, NULL, G_CALLBACK(ignore_thread_cb) },
        {"Message/Mark/UnignoreThread",         NULL, N_("Unignore thread"), NULL, NULL, G_CALLBACK(unignore_thread_cb) },
@@ -1788,6 +1791,7 @@ MainWindow *main_window_create()
        MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/Message/Mark", "MarkRead", "Message/Mark/MarkRead", GTK_UI_MANAGER_MENUITEM)
        MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/Message/Mark", "Separator2", "Message/Mark/---", GTK_UI_MANAGER_SEPARATOR)
        MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/Message/Mark", "MarkAllRead", "Message/Mark/MarkAllRead", GTK_UI_MANAGER_MENUITEM)
+       MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/Message/Mark", "MarkAllUnread", "Message/Mark/MarkAllUnread", GTK_UI_MANAGER_MENUITEM)
        MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/Message/Mark", "Separator3", "Message/Mark/---", GTK_UI_MANAGER_SEPARATOR)
        MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/Message/Mark", "IgnoreThread", "Message/Mark/IgnoreThread", GTK_UI_MANAGER_MENUITEM)
        MENUITEM_ADDUI_MANAGER(mainwin->ui_manager, "/Menu/Message/Mark", "UnignoreThread", "Message/Mark/UnignoreThread", GTK_UI_MANAGER_MENUITEM)
@@ -4461,22 +4465,28 @@ static void unmark_cb(GtkAction *action, gpointer data)
        summary_unmark(mainwin->summaryview);
 }
 
-static void mark_as_unread_cb(GtkAction *action, gpointer data)
+static void mark_as_read_cb(GtkAction *action, gpointer data)
 {
        MainWindow *mainwin = (MainWindow *)data;
-       summary_mark_as_unread(mainwin->summaryview);
+       summary_mark_as_read(mainwin->summaryview, TRUE);
 }
 
-static void mark_as_read_cb(GtkAction *action, gpointer data)
+static void mark_as_unread_cb(GtkAction *action, gpointer data)
 {
        MainWindow *mainwin = (MainWindow *)data;
-       summary_mark_as_read(mainwin->summaryview);
+       summary_mark_as_read(mainwin->summaryview, FALSE);
 }
 
 static void mark_all_read_cb(GtkAction *action, gpointer data)
 {
        MainWindow *mainwin = (MainWindow *)data;
-       summary_mark_all_read(mainwin->summaryview);
+       summary_mark_all_read(mainwin->summaryview, TRUE);
+}
+
+static void mark_all_unread_cb(GtkAction *action, gpointer data)
+{
+       MainWindow *mainwin = (MainWindow *)data;
+       summary_mark_all_read(mainwin->summaryview, FALSE);
 }
 
 static void mark_as_spam_cb(GtkAction *action, gpointer data)
index f135324..4739b66 100644 (file)
@@ -4025,7 +4025,25 @@ static void summary_mark_row_as_read(SummaryView *summaryview,
                msginfo->msgnum);
 }
 
-void summary_mark_as_read(SummaryView *summaryview)
+static void summary_mark_row_as_unread(SummaryView *summaryview,
+                                    GtkCMCTreeNode *row)
+{
+       GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree);
+       MsgInfo *msginfo;
+
+       msginfo = gtk_cmctree_node_get_row_data(ctree, row);
+       cm_return_if_fail(msginfo);
+
+       if(MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags))
+               return;
+
+       summary_msginfo_set_flags(msginfo, MSG_UNREAD, 0);
+       summary_set_row_marks(summaryview, row);
+       debug_print("Message %d is marked as unread\n",
+               msginfo->msgnum);
+}
+
+void summary_mark_as_read(SummaryView *summaryview, gboolean read)
 {
        GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree);
        GList *cur;
@@ -4036,8 +4054,12 @@ void summary_mark_as_read(SummaryView *summaryview)
        START_LONG_OPERATION(summaryview, FALSE);
        folder_item_set_batch(summaryview->folder_item, TRUE);
        for (cur = GTK_CMCLIST(ctree)->selection; cur != NULL && cur->data != NULL; cur = cur->next)
-               summary_mark_row_as_read(summaryview,
-                                        GTK_CMCTREE_NODE(cur->data));
+               if (read)
+                       summary_mark_row_as_read(summaryview,
+                                                GTK_CMCTREE_NODE(cur->data));
+               else
+                       summary_mark_row_as_unread(summaryview,
+                                                GTK_CMCTREE_NODE(cur->data));
        folder_item_set_batch(summaryview->folder_item, FALSE);
        END_LONG_OPERATION(summaryview);
        
@@ -4078,17 +4100,26 @@ void summary_msgs_unlock(SummaryView *summaryview)
        summary_status_show(summaryview);
 }
 
-void summary_mark_all_read(SummaryView *summaryview)
+void summary_mark_all_read(SummaryView *summaryview, gboolean read)
 {
        GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree);
        GtkCMCTreeNode *node;
        AlertValue val;
        gboolean froze = FALSE;
+       gchar *message;
+       gchar *title;
+
+       if (read) {
+               title = _("Mark all as read");
+               message = _("Do you really want to mark all mails in this folder as read?");
+       } else {
+               title = _("Mark all as unread");
+               message = _("Do you really want to mark all mails in this folder as unread?");
+       }
 
        if (prefs_common.ask_mark_all_read) {
-               val = alertpanel_full(_("Mark all as read"),
-                       _("Do you really want to mark all mails in this "
-                         "folder as read?"), GTK_STOCK_NO, GTK_STOCK_YES, NULL,
+               val = alertpanel_full(title, message,
+                         GTK_STOCK_NO, GTK_STOCK_YES, NULL,
                          TRUE, NULL, ALERT_QUESTION, G_ALERTDEFAULT);
 
                if ((val & ~G_ALERTDISABLE) != G_ALERTALTERNATE)
@@ -4103,7 +4134,10 @@ void summary_mark_all_read(SummaryView *summaryview)
        folder_item_set_batch(summaryview->folder_item, TRUE);
        for (node = GTK_CMCTREE_NODE(GTK_CMCLIST(ctree)->row_list); node != NULL;
             node = gtkut_ctree_node_next(ctree, node))
-               summary_mark_row_as_read(summaryview, node);
+               if (read)
+                       summary_mark_row_as_read(summaryview, node);
+               else
+                       summary_mark_row_as_unread(summaryview, node);
        folder_item_set_batch(summaryview->folder_item, FALSE);
        for (node = GTK_CMCTREE_NODE(GTK_CMCLIST(ctree)->row_list); node != NULL;
             node = gtkut_ctree_node_next(ctree, node)) {
@@ -4183,27 +4217,6 @@ void summary_mark_as_spam(SummaryView *summaryview, guint action, GtkWidget *wid
 }
 
 
-static void summary_mark_row_as_unread(SummaryView *summaryview,
-                                      GtkCMCTreeNode *row)
-{
-       GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree);
-       MsgInfo *msginfo;
-
-       msginfo = gtk_cmctree_node_get_row_data(ctree, row);
-       cm_return_if_fail(msginfo);
-       if (MSG_IS_DELETED(msginfo->flags)) {
-               procmsg_msginfo_set_to_folder(msginfo, NULL);
-               summary_msginfo_unset_flags(msginfo, MSG_DELETED, 0);
-               summaryview->deleted--;
-       }
-
-       summary_msginfo_set_flags(msginfo, MSG_UNREAD, 0);
-       debug_print("Message %d is marked as unread\n",
-               msginfo->msgnum);
-
-       summary_set_row_marks(summaryview, row);
-}
-
 void summary_mark_as_unread(SummaryView *summaryview)
 {
        GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree);
@@ -7750,6 +7763,7 @@ void summary_toggle_watch_thread(SummaryView *summaryview)
                summary_watch_thread(summaryview);
 }
 
+
 void summary_toggle_show_read_messages(SummaryView *summaryview)
 {
        FolderItemUpdateData source;
index ba24099..dee8068 100644 (file)
@@ -272,11 +272,10 @@ void summary_save_as                (SummaryView          *summaryview);
 void summary_print               (SummaryView          *summaryview);
 void summary_mark                (SummaryView          *summaryview);
 void summary_unmark              (SummaryView          *summaryview);
-void summary_mark_as_unread      (SummaryView          *summaryview);
-void summary_mark_as_read        (SummaryView          *summaryview);
+void summary_mark_as_read        (SummaryView          *summaryview, gboolean);
 void summary_msgs_lock           (SummaryView          *summaryview);
 void summary_msgs_unlock         (SummaryView          *summaryview);
-void summary_mark_all_read       (SummaryView          *summaryview);
+void summary_mark_all_read       (SummaryView          *summaryview, gboolean);
 void summary_mark_as_spam        (SummaryView          *summaryview, 
                                   guint                 action, 
                                   GtkWidget            *widget);