0.8.8claws110
[claws.git] / src / folder.c
index ea04318e90610f9eb0dd4ecfb3cb805c33bdd935..e4eb3c06b39b5bd321347299605f3c5db4419d47 100644 (file)
 #include "utils.h"
 #include "xml.h"
 #include "codeconv.h"
-#include "prefs.h"
+#include "prefs_gtk.h"
 #include "account.h"
 #include "filtering.h"
 #include "scoring.h"
 #include "prefs_folder_item.h"
 #include "procheader.h"
-#include "statusbar.h"
+#include "hooks.h"
+#include "log.h"
 
 /* Dependecies to be removed ?! */
 #include "prefs_common.h"
@@ -416,7 +417,7 @@ void folder_write_list(void)
 
        fputs("</folderlist>\n", pfile->fp);
 
-       if (prefs_write_close(pfile) < 0)
+       if (prefs_file_close(pfile) < 0)
                g_warning("failed to write folder list.\n");
 }
 
@@ -988,8 +989,7 @@ void folder_item_close(FolderItem *item)
 
        folder_item_write_cache(item);
        
-       folder_update_item(item, FALSE);
-
+       folder_item_update(item, F_ITEM_UPDATE_MSGCNT);
 }
 
 gint folder_item_scan(FolderItem *item)
@@ -998,7 +998,7 @@ gint folder_item_scan(FolderItem *item)
        GSList *folder_list = NULL, *cache_list = NULL, *folder_list_cur, *cache_list_cur, *new_list = NULL;
        guint newcnt = 0, unreadcnt = 0, totalcnt = 0, unreadmarkedcnt = 0;
        guint cache_max_num, folder_max_num, cache_cur_num, folder_cur_num;
-       gboolean contentchange = FALSE;
+       gboolean update_flags = 0;
     
        g_return_val_if_fail(item != NULL, -1);
        if (item->path == NULL) return -1;
@@ -1098,8 +1098,6 @@ gint folder_item_scan(FolderItem *item)
                        else
                                folder_cur_num = G_MAXINT;
 
-                       contentchange = TRUE;
-
                        continue;
                }
 
@@ -1119,7 +1117,7 @@ gint folder_item_scan(FolderItem *item)
                        else
                                cache_cur_num = G_MAXINT;
 
-                       contentchange = TRUE;
+                       update_flags |= F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT;
 
                        continue;
                }
@@ -1145,6 +1143,8 @@ gint folder_item_scan(FolderItem *item)
                                                unreadcnt++;
                                        if (MSG_IS_UNREAD(newmsginfo->flags) && procmsg_msg_has_marked_parent(newmsginfo))
                                                unreadmarkedcnt++;
+                                       if (procmsg_msg_has_flagged_parent(newmsginfo, MSG_IGNORE_THREAD))
+                                               procmsg_msginfo_set_flags(newmsginfo, MSG_IGNORE_THREAD, 0);
                                        procmsg_msginfo_free(newmsginfo);
                                }                                       
 
@@ -1156,6 +1156,8 @@ gint folder_item_scan(FolderItem *item)
                                        unreadcnt++;
                                if (MSG_IS_UNREAD(msginfo->flags) && procmsg_msg_has_marked_parent(msginfo))
                                        unreadmarkedcnt++;
+                               if (!MSG_IS_IGNORE_THREAD(msginfo->flags) && procmsg_msg_has_flagged_parent(msginfo, MSG_IGNORE_THREAD))
+                                       procmsg_msginfo_set_flags(msginfo, MSG_IGNORE_THREAD, 0);
                        }
                        totalcnt++;
                        procmsg_msginfo_free(msginfo);
@@ -1174,7 +1176,7 @@ gint folder_item_scan(FolderItem *item)
                        else
                                folder_cur_num = G_MAXINT;
 
-                       contentchange = TRUE;
+                       update_flags |= F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT;
 
                        continue;
                }
@@ -1203,8 +1205,12 @@ gint folder_item_scan(FolderItem *item)
                                        unreadcnt++;
                                if (MSG_IS_UNREAD(msginfo->flags) && procmsg_msg_has_marked_parent(msginfo))
                                        unreadmarkedcnt++;
+                               if (procmsg_msg_has_flagged_parent(msginfo, MSG_IGNORE_THREAD))
+                                       procmsg_msginfo_set_flags(msginfo, MSG_IGNORE_THREAD, 0);
                                totalcnt++;
                                procmsg_msginfo_free(msginfo);
+
+                               update_flags |= F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT;
                        }
                        g_slist_free(newmsg_list);
                }
@@ -1225,10 +1231,14 @@ gint folder_item_scan(FolderItem *item)
                                    unreadcnt++;
                                if (MSG_IS_UNREAD(msginfo->flags) && procmsg_msg_has_marked_parent(msginfo))
                                        unreadmarkedcnt++;
+                               if (procmsg_msg_has_flagged_parent(msginfo, MSG_IGNORE_THREAD))
+                                       procmsg_msginfo_set_flags(msginfo, MSG_IGNORE_THREAD, 0);
                                totalcnt++;
                                procmsg_msginfo_free(msginfo);
                                debug_print("Added newly found message %d to cache.\n", num);
                        }
+
+                       update_flags |= F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT;
                }
        }
 
@@ -1238,7 +1248,7 @@ gint folder_item_scan(FolderItem *item)
        item->unreadmarked = unreadmarkedcnt;
        g_slist_free(new_list);
 
-       folder_update_item(item, contentchange);
+       folder_item_update(item, update_flags);
 
        return 0;
 }
@@ -1477,8 +1487,10 @@ gint folder_item_add_msg(FolderItem *dest, const gchar *file,
                                dest->unread++;
                        if (MSG_IS_UNREAD(msginfo->flags) && procmsg_msg_has_marked_parent(msginfo))
                                dest->unreadmarked++;
+                       if (procmsg_msg_has_flagged_parent(msginfo, MSG_IGNORE_THREAD))
+                               procmsg_msginfo_set_flags(msginfo, MSG_IGNORE_THREAD, 0);
                        dest->total++;
-                       dest->need_update = TRUE;
+                       folder_item_update(dest, F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT);
 
                        msgcache_add_msg(dest->cache, msginfo);
 
@@ -1538,13 +1550,11 @@ FolderItem *folder_item_move_recursive (FolderItem *src, FolderItem *dest)
                MsgInfo * msginfo;
                cnt++;
                if (cnt%500)
-                       statusbar_print_all(_("Moving %s to %s (%d%%)..."), src->name, 
+                       log_message(_("Moving %s to %s (%d%%)...\n"), src->name, 
                                        new_item->path,
                                        100*cnt/g_slist_length(mlist));
                msginfo = (MsgInfo *) cur->data;
                folder_item_move_msg(new_item, msginfo);
-               if (cnt%500)
-                       statusbar_pop_all();
 
                procmsg_msginfo_free(msginfo);
        }
@@ -1672,7 +1682,7 @@ gint folder_item_move_msg(FolderItem *dest, MsgInfo *msginfo)
 
        num = folder->copy_msg(folder, dest, msginfo);
        
-       if (num != -1) {
+       if (num > 0) {
                MsgInfo *newmsginfo;
     
                /* Add new msginfo to dest folder */
@@ -1691,8 +1701,10 @@ gint folder_item_move_msg(FolderItem *dest, MsgInfo *msginfo)
                                dest->unread++;
                        if (MSG_IS_UNREAD(newmsginfo->flags) && procmsg_msg_has_marked_parent(newmsginfo))
                                dest->unreadmarked++;
+                       if (procmsg_msg_has_flagged_parent(newmsginfo, MSG_IGNORE_THREAD))
+                               procmsg_msginfo_set_flags(newmsginfo, MSG_IGNORE_THREAD, 0);
                        dest->total++;
-                       dest->need_update = TRUE;
+                       folder_item_update(dest, F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT);
 
                        procmsg_msginfo_free(newmsginfo);
                }
@@ -1703,14 +1715,14 @@ gint folder_item_move_msg(FolderItem *dest, MsgInfo *msginfo)
                                               msginfo->msgnum);
                        msgcache_remove_msg(msginfo->folder->cache, msginfo->msgnum);
 
-                       if (MSG_IS_NEW(msginfo->flags))
+                       if (MSG_IS_NEW(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags))
                                msginfo->folder->new--;
-                       if (MSG_IS_UNREAD(msginfo->flags))
+                       if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags))
                                msginfo->folder->unread--;
                        if (MSG_IS_UNREAD(msginfo->flags) && procmsg_msg_has_marked_parent(msginfo))
                                msginfo->folder->unreadmarked--;
                        msginfo->folder->total--;
-                       msginfo->folder->need_update = TRUE;
+                       folder_item_update(dest, F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT);
                }
        }
        
@@ -1784,7 +1796,7 @@ gint folder_item_move_msgs_with_dest(FolderItem *dest, GSList *msglist)
 
                num = GPOINTER_TO_INT(l2->data);
 
-               if (num != -1) {
+               if (num > 0) {
                        MsgInfo *newmsginfo;
 
                        newmsginfo = folder->get_msginfo(folder, dest, num);
@@ -1804,8 +1816,10 @@ gint folder_item_move_msgs_with_dest(FolderItem *dest, GSList *msglist)
                                        dest->unread++;
                                if (MSG_IS_UNREAD(newmsginfo->flags) && procmsg_msg_has_marked_parent(newmsginfo))
                                        dest->unreadmarked++;
+                               if (procmsg_msg_has_flagged_parent(newmsginfo, MSG_IGNORE_THREAD))
+                                       procmsg_msginfo_set_flags(newmsginfo, MSG_IGNORE_THREAD, 0);
                                dest->total++;
-                               dest->need_update = TRUE;
+                               folder_item_update(dest, F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT);
 
                                procmsg_msginfo_free(newmsginfo);
                        }
@@ -1824,7 +1838,7 @@ gint folder_item_move_msgs_with_dest(FolderItem *dest, GSList *msglist)
 
                num = GPOINTER_TO_INT(l2->data);
                
-               if (num != -1) {
+               if (num > 0) {
                        item->folder->remove_msg(item->folder,
                                                 msginfo->folder,
                                                 msginfo->msgnum);
@@ -1832,14 +1846,14 @@ gint folder_item_move_msgs_with_dest(FolderItem *dest, GSList *msglist)
                                folder_item_read_cache(item);
                        msgcache_remove_msg(item->cache, msginfo->msgnum);
 
-                       if (MSG_IS_NEW(msginfo->flags))
+                       if (MSG_IS_NEW(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags))
                                msginfo->folder->new--;
-                       if (MSG_IS_UNREAD(msginfo->flags))
+                       if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags))
                                msginfo->folder->unread--;
                        if (MSG_IS_UNREAD(msginfo->flags) && procmsg_msg_has_marked_parent(msginfo))
                                msginfo->folder->unreadmarked--;
                        msginfo->folder->total--;                       
-                       msginfo->folder->need_update = TRUE;
+                       folder_item_update(msginfo->folder, F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT);
                }
 
                l2 = g_slist_next(l2);
@@ -1887,7 +1901,7 @@ gint folder_item_copy_msg(FolderItem *dest, MsgInfo *msginfo)
        if (!dest->cache) folder_item_read_cache(dest);
        
        num = folder->copy_msg(folder, dest, msginfo);
-       if (num != -1) {
+       if (num > 0) {
                MsgInfo *newmsginfo;
 
                if (NULL != (newmsginfo = folder->get_msginfo(folder, dest, num))) {
@@ -1906,8 +1920,10 @@ gint folder_item_copy_msg(FolderItem *dest, MsgInfo *msginfo)
                                dest->unread++;
                        if (MSG_IS_UNREAD(newmsginfo->flags) && procmsg_msg_has_marked_parent(newmsginfo))
                                dest->unreadmarked++;
+                       if (procmsg_msg_has_flagged_parent(newmsginfo, MSG_IGNORE_THREAD))
+                               procmsg_msginfo_set_flags(newmsginfo, MSG_IGNORE_THREAD, 0);
                        dest->total++;
-                       dest->need_update = TRUE;
+                       folder_item_update(dest, F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT);
 
                        procmsg_msginfo_free(newmsginfo);
                }                       
@@ -1977,7 +1993,7 @@ gint folder_item_copy_msgs_with_dest(FolderItem *dest, GSList *msglist)
 
                num = GPOINTER_TO_INT(l2->data);
 
-               if (num != -1) {
+               if (num > 0) {
                        MsgInfo *newmsginfo;
 
                        newmsginfo = folder->get_msginfo(folder, dest, num);
@@ -1997,8 +2013,10 @@ gint folder_item_copy_msgs_with_dest(FolderItem *dest, GSList *msglist)
                                        dest->unread++;
                                if (MSG_IS_UNREAD(newmsginfo->flags) && procmsg_msg_has_marked_parent(newmsginfo))
                                        dest->unreadmarked++;
+                               if (procmsg_msg_has_flagged_parent(newmsginfo, MSG_IGNORE_THREAD))
+                                       procmsg_msginfo_set_flags(newmsginfo, MSG_IGNORE_THREAD, 0);
                                dest->total++;
-                               dest->need_update = TRUE;
+                               folder_item_update(dest, F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT);
 
                                procmsg_msginfo_free(newmsginfo);
                        }
@@ -2028,9 +2046,9 @@ gint folder_item_remove_msg(FolderItem *item, gint num)
 
        msginfo = msgcache_get_msg(item->cache, num);
        if (msginfo != NULL) {
-               if (MSG_IS_NEW(msginfo->flags))
+               if (MSG_IS_NEW(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags))
                        item->new--;
-               if (MSG_IS_UNREAD(msginfo->flags))
+               if (MSG_IS_UNREAD(msginfo->flags) && !MSG_IS_IGNORE_THREAD(msginfo->flags))
                        item->unread--;
                if (MSG_IS_UNREAD(msginfo->flags) && procmsg_msg_has_marked_parent(msginfo))
                        item->unreadmarked--;
@@ -2038,7 +2056,7 @@ gint folder_item_remove_msg(FolderItem *item, gint num)
                msgcache_remove_msg(item->cache, num);
        }
        item->total--;
-       item->need_update = TRUE;
+       folder_item_update(item, F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT);
 
        return ret;
 }
@@ -2097,7 +2115,7 @@ gint folder_item_remove_all_msg(FolderItem *item)
                item->unread = 0;
                item->unreadmarked = 0;
                item->total = 0;
-               item->need_update = TRUE;
+               folder_item_update(item, F_ITEM_UPDATE_MSGCNT | F_ITEM_UPDATE_CONTENT);
        }
 
        return result;
@@ -2246,6 +2264,8 @@ static gboolean folder_build_tree(GNode *node, gpointer data)
                                sort_key = SORT_BY_UNREAD;
                        else if (!strcmp(attr->value, "mime"))
                                sort_key = SORT_BY_MIME;
+                       else if (!strcmp(attr->value, "to"))
+                               sort_key = SORT_BY_TO;
                        else if (!strcmp(attr->value, "locked"))
                                sort_key = SORT_BY_LOCKED;
                } else if (!strcmp(attr->name, "sort_type")) {
@@ -2401,7 +2421,8 @@ static void folder_write_list_recursive(GNode *node, gpointer data)
                                                 "draft", "queue", "trash"};
        static gchar *sort_key_str[] = {"none", "number", "size", "date",
                                        "from", "subject", "score", "label",
-                                       "mark", "unread", "mime", "locked" };
+                                       "mark", "unread", "mime", "to", 
+                                       "locked"};
        g_return_if_fail(node != NULL);
        g_return_if_fail(fp != NULL);
 
@@ -2501,7 +2522,7 @@ static void folder_update_op_count_rec(GNode *node)
        if (g_node_depth(node) > 0) {
                if (fitem->op_count > 0) {
                        fitem->op_count = 0;
-                       folder_update_item(fitem, FALSE);
+                       folder_item_update(fitem, F_ITEM_UPDATE_MSGCNT);
                }
                if (node->children) {
                        GNode *child;
@@ -2712,8 +2733,9 @@ void folder_item_apply_processing(FolderItem *item)
        if (processing_list == NULL)
                return;
 
+       folder_item_update_freeze();
+
        mlist = folder_item_get_msg_list(item);
-       
        for (cur = mlist ; cur != NULL ; cur = cur->next) {
                MsgInfo * msginfo;
 
@@ -2721,104 +2743,80 @@ void folder_item_apply_processing(FolderItem *item)
                filter_message_by_msginfo(processing_list, msginfo);
                procmsg_msginfo_free(msginfo);
        }
-       
-       folder_update_items_when_required(FALSE);
-
        g_slist_free(mlist);
+
+       folder_item_update_thaw();
 }
 
 /*
- *  Callback handling for FolderItem content changes
+ *  functions for handling FolderItem content changes
  */
-GSList *folder_item_update_callbacks_list = NULL;
-gint   folder_item_update_callbacks_nextid = 0;
+static gint folder_item_update_freeze_cnt = 0;
 
-struct FolderItemUpdateCallback
-{
-       gint                    id;
-       FolderItemUpdateFunc    func;
-       gpointer                data;
-};
-
-gint folder_item_update_callback_register(FolderItemUpdateFunc func, gpointer data)
+/**
+ * Notify the folder system about changes to a folder. If the
+ * update system is not frozen the FOLDER_ITEM_UPDATE_HOOKLIST will
+ * be invoked, otherwise the changes will be remebered until
+ * the folder system is thawed.
+ *
+ * \param item The FolderItem that was changed
+ * \param update_flags Type of changed that was made
+ */
+void folder_item_update(FolderItem *item, FolderItemUpdateFlags update_flags)
 {
-       struct FolderItemUpdateCallback *callback;
-
-       g_return_val_if_fail(func != NULL, -1);
-
-       folder_item_update_callbacks_nextid++;
-
-       callback = g_new0(struct FolderItemUpdateCallback, 1);
-       callback->id = folder_item_update_callbacks_nextid;
-       callback->func = func;
-       callback->data = data;
-
-       folder_item_update_callbacks_list =
-               g_slist_append(folder_item_update_callbacks_list, callback);
-
-       return folder_item_update_callbacks_nextid;
+       if (folder_item_update_freeze_cnt == 0) {
+               FolderItemUpdateData source;
+       
+               source.item = item;
+               source.update_flags = update_flags;
+               hooks_invoke(FOLDER_ITEM_UPDATE_HOOKLIST, &source);
+       } else {
+               item->update_flags |= update_flags;
+       }
 }
 
-void folder_item_update_callback_unregister(gint id)
+void folder_item_update_recursive(FolderItem *item, FolderItemUpdateFlags update_flags)
 {
-       GSList *list, *next;
+       GNode *node = item->folder->node;       
 
-       for (list = folder_item_update_callbacks_list; list != NULL; list = next) {
-               struct FolderItemUpdateCallback *callback;
+       node = g_node_find(node, G_PRE_ORDER, G_TRAVERSE_ALL, item);
+       node = node->children;
 
-               next = list->next;
+       folder_item_update(item, update_flags);
+       while (node != NULL) {
+               if (node && node->data) {
+                       FolderItem *next_item = (FolderItem*) node->data;
 
-               callback = list->data;
-               if (callback->id == id) {
-                       folder_item_update_callbacks_list =
-                               g_slist_remove(folder_item_update_callbacks_list, callback);
-                       g_free(callback);
+                       folder_item_update(next_item, update_flags);
                }
+               node = node->next;
        }
 }
 
-static void folder_item_update_callback_execute(FolderItem *item, gboolean contentchange)
-{
-       GSList *list;
-
-       for (list = folder_item_update_callbacks_list; list != NULL; list = list->next) {
-               struct FolderItemUpdateCallback *callback;
-
-               callback = list->data;
-               callback->func(item, contentchange, callback->data);
-       }
-}
-
-void folder_update_item(FolderItem *item, gboolean contentchange)
+void folder_item_update_freeze()
 {
-       folder_item_update_callback_execute(item, contentchange);
+       folder_item_update_freeze_cnt++;
 }
 
-static void folder_update_item_func(FolderItem *item, gpointer contentchange)
+static void folder_item_update_func(FolderItem *item, gpointer data)
 {
-       if (item->need_update) {
-               folder_item_update_callback_execute(item, GPOINTER_TO_INT(contentchange));
-               item->need_update = FALSE;
+       FolderItemUpdateData source;
+    
+       if (item->update_flags) {
+               source.item = item;
+               source.update_flags = item->update_flags;
+               hooks_invoke(FOLDER_ITEM_UPDATE_HOOKLIST, &source);                             
+               item->update_flags = 0;
        }
 }
 
-void folder_update_items_when_required(gboolean contentchange)
-{
-       folder_func_to_all_folders(folder_update_item_func, GINT_TO_POINTER(contentchange));
-}
-
-void folder_update_item_recursive(FolderItem *item, gboolean update_summary)
+void folder_item_update_thaw()
 {
-       GNode *node = item->folder->node;       
-       node = g_node_find(node, G_PRE_ORDER, G_TRAVERSE_ALL, item);
-       node = node->children;
-       folder_item_update_callback_execute(item, update_summary);
-       while (node != NULL) {
-               if (node && node->data) {
-                       FolderItem *next_item = (FolderItem*) node->data;
-                       folder_item_update_callback_execute(next_item, update_summary);
-               }
-               node = node->next;
+       if (folder_item_update_freeze_cnt > 0)
+               folder_item_update_freeze_cnt--;
+       if (folder_item_update_freeze_cnt == 0) {
+               /* Update all folders */
+               folder_func_to_all_folders(folder_item_update_func, NULL);
        }
 }