0.9.10claws4
authorChristoph Hohmann <reboot@gmx.ch>
Thu, 11 Mar 2004 22:49:56 +0000 (22:49 +0000)
committerChristoph Hohmann <reboot@gmx.ch>
Thu, 11 Mar 2004 22:49:56 +0000 (22:49 +0000)
* src/folder.[ch]
* src/imap.c
* src/procmsg.h
        syncronize flags in cache with IMAP folder flags

Adapted a patch submitted by Simon 'corecode' Schubert
<corecode@corecode.ath.cx>

ChangeLog.claws
configure.ac
src/folder.c
src/folder.h
src/imap.c
src/procmsg.h

index ec448b9b8c1ce74686a2054c812b32c48dccae8b..766a32f76f8207ab9063912476bb466c32fc6619 100644 (file)
@@ -1,3 +1,14 @@
+2004-03-11 [christoph] 0.9.10claws4
+
+       * src/folder.[ch]
+       * src/imap.c
+       * src/procmsg.h
+               syncronize flags in cache with IMAP folder flags
+
+       Adapted a patch submitted by Simon 'corecode' Schubert
+       <corecode@corecode.ath.cx> 
+
+
 2004-03-11 [alfons]    0.9.10claws3
 
        * src/textview.[ch]
index 6040bd718d49eb54db0523ad83e918f9556a9cf3..e64f706f031ebbe35d75a71bdcdf5e98d47486cd 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=9
 MICRO_VERSION=10
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=3
+EXTRA_VERSION=4
 if test $EXTRA_VERSION -eq 0; then
     VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}claws
 else
index e54d78faa1ea6f29da23aab2aaa494350ba8be47..81c6e7cc816b3ef1eaca590bd61f904c50c4e9a0 100644 (file)
@@ -1361,7 +1361,8 @@ gint folder_item_open(FolderItem *item)
        if((item->folder->klass->scan_required != NULL) && (item->folder->klass->scan_required(item->folder, item))) {
                folder_item_scan_full(item, TRUE);
        }
-
+       folder_item_syncronize_flags(item);
+       
        /* Processing */
        buf = g_strdup_printf(_("Processing (%s)...\n"), item->path);
        debug_print("%s\n", buf);
@@ -1666,6 +1667,60 @@ gint folder_item_scan_full(FolderItem *item, gboolean filtering)
        return 0;
 }
 
+gint folder_item_syncronize_flags(FolderItem *item)
+{
+       MsgInfoList *msglist = NULL;
+       GSList *cur;
+       GRelation *relation;
+       gint ret = 0;
+       
+       g_return_val_if_fail(item != NULL, -1);
+       g_return_val_if_fail(item->folder != NULL, -1);
+       g_return_val_if_fail(item->folder->klass != NULL, -1);
+       if(item->folder->klass->get_flags == NULL)
+               return 0;
+       
+       if (item->cache == NULL)
+               folder_item_read_cache(item);
+       
+       msglist = msgcache_get_msg_list(item->cache);
+       
+       relation = g_relation_new(2);
+       g_relation_index(relation, 0, g_direct_hash, g_direct_equal);
+       if ((ret = item->folder->klass->get_flags(
+           item->folder, item, msglist, relation)) == 0) {
+               GTuples *tuples;
+               MsgInfo *msginfo;
+               MsgPermFlags permflags;
+               gboolean skip;
+
+               for (cur = msglist; cur != NULL; cur = g_slist_next(cur)) {
+                       msginfo = (MsgInfo *) cur->data;
+               
+                       tuples = g_relation_select(relation, msginfo, 0);
+                       skip = tuples->len < 1;
+                       if (!skip)
+                               permflags = GPOINTER_TO_INT(g_tuples_index(tuples, 0, 1));
+                       g_tuples_destroy(tuples);
+                       if (skip)
+                               continue;
+                       
+                       if (msginfo->flags.perm_flags != permflags) {
+                               procmsg_msginfo_set_flags(msginfo,
+                                       permflags & ~msginfo->flags.perm_flags, 0);
+                               procmsg_msginfo_unset_flags(msginfo,
+                                       ~permflags & msginfo->flags.perm_flags, 0);
+                       }
+               }
+       }
+       g_relation_destroy(relation);
+       
+       for (cur = msglist; cur != NULL; cur = g_slist_next(cur))
+               procmsg_msginfo_free((MsgInfo *) cur->data);
+       
+       return ret;
+}
+
 gint folder_item_scan(FolderItem *item)
 {
        return folder_item_scan_full(item, TRUE);
index 7cea6aff8a04a6fc4d3a83ec62ea3f64824cb555..05bf262a14a16e0c205d52df0b08a376fc3583c8 100644 (file)
@@ -169,7 +169,7 @@ struct _FolderClass
         * user. Can be upper and lowercase unlike the idstr.
         */
        gchar      *uistr;
-
+       
        /* virtual functions */
 
        /* Folder funtions */
@@ -538,6 +538,21 @@ struct _FolderClass
                                                 FolderItem     *item,
                                                 MsgInfo        *msginfo,
                                                 MsgPermFlags    newflags);
+       /**
+        * Get the flags for a list of messages
+        *
+        * \param folder The \c Folder of the messages
+        * \param item The \c FolderItem of the messages
+        * \param msglist The list of \c MsgInfos for which the flags should
+        *                   be returned
+        * \param msgflags A \c GRelation for tuples of (message number,
+        *                 permanent flags). Add tuples for the messages in msgnumlist
+        * \return 0 on success, a negative number otherwise
+        */
+       gint            (*get_flags)            (Folder         *folder,
+                                                FolderItem     *item,
+                                                MsgInfoList    *msglist,
+                                                GRelation      *msgflags);
 };
 
 struct _FolderItem
index 8a03969daa225556b343c86d7bcb3832738f252f..cec5ec158318323999310af5e778145d91b1cea1 100644 (file)
@@ -435,7 +435,11 @@ static gboolean imap_scan_required         (Folder         *folder,
 static void imap_change_flags                  (Folder         *folder,
                                                 FolderItem     *item,
                                                 MsgInfo        *msginfo,
-                                                MsgPermFlags   newflags);
+                                                MsgPermFlags    newflags);
+static gint imap_get_flags                     (Folder         *folder,
+                                                FolderItem     *item,
+                                                MsgInfoList    *msglist,
+                                                GRelation      *msgflags);
 static gchar *imap_folder_get_path             (Folder         *folder);
 static gchar *imap_item_get_path               (Folder         *folder,
                                                 FolderItem     *item);
@@ -478,6 +482,7 @@ FolderClass *imap_get_class(void)
                imap_class.remove_all_msg = imap_remove_all_msg;
                imap_class.is_msg_changed = imap_is_msg_changed;
                imap_class.change_flags = imap_change_flags;
+               imap_class.get_flags = imap_get_flags;
        }
        
        return &imap_class;
@@ -4055,3 +4060,147 @@ void imap_change_flags(Folder *folder, FolderItem *item, MsgInfo *msginfo, MsgPe
 
        return;
 }
+
+static gint compare_msginfo(gconstpointer a, gconstpointer b)
+{
+       return ((MsgInfo *)a)->msgnum - ((MsgInfo *)b)->msgnum;
+}
+
+static guint gslist_find_next_num(MsgNumberList **list, guint num)
+{
+       GSList *elem;
+
+       g_return_val_if_fail(list != NULL, -1);
+
+       for (elem = *list; elem != NULL; elem = g_slist_next(elem))
+               if (GPOINTER_TO_INT(elem->data) >= num)
+                       break;
+       *list = elem;
+       return elem != NULL ? GPOINTER_TO_INT(elem->data) : (gint)-1;
+}
+
+/*
+ * NEW and DELETED flags are not syncronized
+ * - The NEW/RECENT flags in IMAP folders can not really be directly
+ *   modified by Sylpheed
+ * - The DELETE/DELETED flag in IMAP and Sylpheed don't have the same
+ *   meaning, in IMAP it always removes the messages from the FolderItem
+ *   in Sylpheed it can mean to move the message to trash
+ */
+static gint imap_get_flags(Folder *folder, FolderItem *item,
+                           MsgInfoList *msginfo_list, GRelation *msgflags)
+{
+       IMAPSession *session;
+       GSList *sorted_list;
+       /*
+       GSList *new = NULL, *p_new;
+       */
+       GSList *unseen = NULL, *answered = NULL, *flagged = NULL, *deleted = NULL;
+       GSList *p_unseen, *p_answered, *p_flagged, *p_deleted;
+       GSList *elem;
+       GSList *seq_list, *cur;
+       gboolean reverse_seen = FALSE;
+       GString *cmd_buf;
+       gint ok;
+       gint exists_cnt, recent_cnt, unseen_cnt, uid_next;
+       guint32 uidvalidity;
+
+       g_return_val_if_fail(folder != NULL, -1);
+       g_return_val_if_fail(item != NULL, -1);
+       g_return_val_if_fail(msginfo_list != NULL, -1);
+
+       session = imap_session_get(folder);
+       g_return_val_if_fail(session != NULL, -1);
+
+       ok = imap_select(session, IMAP_FOLDER(folder), item->path,
+                       NULL, NULL, NULL, NULL);
+       if (ok != IMAP_SUCCESS)
+               return -1;
+
+       ok = imap_status(session, IMAP_FOLDER(folder), item->path,
+                        &exists_cnt, &recent_cnt, &uid_next, &uidvalidity, &unseen_cnt);
+
+       if (unseen_cnt > exists_cnt / 2)
+               reverse_seen = TRUE;
+
+       cmd_buf = g_string_new(NULL);
+
+       sorted_list = g_slist_sort(g_slist_copy(msginfo_list), compare_msginfo);
+
+       seq_list = imap_get_seq_set_from_msglist(msginfo_list);
+
+       for (cur = seq_list; cur != NULL; cur = g_slist_next(cur)) {
+               IMAPSet imapset = cur->data;
+/*
+               g_string_sprintf(cmd_buf, "RECENT UID %s", imapset);
+               imap_cmd_search(session, cmd_buf->str, &p_new);
+               new = g_slist_concat(new, p_new);
+*/
+               g_string_sprintf(cmd_buf, "%sSEEN UID %s", reverse_seen ? "" : "UN", imapset);
+               imap_cmd_search(session, cmd_buf->str, &p_unseen);
+               unseen = g_slist_concat(unseen, p_unseen);
+
+               g_string_sprintf(cmd_buf, "ANSWERED UID %s", imapset);
+               imap_cmd_search(session, cmd_buf->str, &p_answered);
+               answered = g_slist_concat(answered, p_answered);
+
+               g_string_sprintf(cmd_buf, "FLAGGED UID %s", imapset);
+               imap_cmd_search(session, cmd_buf->str, &p_flagged);
+               flagged = g_slist_concat(flagged, p_flagged);
+/*
+               g_string_sprintf(cmd_buf, "DELETED UID %s", imapset);
+               imap_cmd_search(session, cmd_buf->str, &p_deleted);
+               deleted = g_slist_concat(deleted, p_deleted);
+*/
+       }
+
+/*
+       p_new = new;
+*/
+       p_unseen = unseen;
+       p_answered = answered;
+       p_flagged = flagged;
+       p_deleted = deleted;
+       
+       for (elem = sorted_list; elem != NULL; elem = g_slist_next(elem)) {
+               MsgInfo *msginfo;
+               MsgPermFlags flags;
+               
+               msginfo = (MsgInfo *) elem->data;
+               flags = msginfo->flags.perm_flags;
+               flags &= ~((reverse_seen ? 0 : MSG_UNREAD) | MSG_REPLIED | MSG_MARKED);
+               if (reverse_seen)
+                       flags |= MSG_UNREAD;
+               /*
+               if (gslist_find_next_num(&p_new, msginfo->msgnum) == msginfo->msgnum)
+                       flags |= MSG_NEW;
+               */
+               if (gslist_find_next_num(&p_unseen, msginfo->msgnum) == msginfo->msgnum) {
+                       if (!reverse_seen) {
+                               flags |= MSG_UNREAD;
+                       } else {
+                               flags &= ~(MSG_UNREAD | MSG_NEW);
+                       }
+               }
+               if (gslist_find_next_num(&p_answered, msginfo->msgnum) == msginfo->msgnum)
+                       flags |= MSG_REPLIED;
+               if (gslist_find_next_num(&p_flagged, msginfo->msgnum) == msginfo->msgnum)
+                       flags |= MSG_MARKED;
+               /*
+               if (gslist_find_next_num(&p_deleted, msginfo->msgnum) == msginfo->msgnum)
+                       MSG_SET_PERM_FLAGS(msginfo->flags, MSG_DELETED);
+                */
+               g_relation_insert(msgflags, msginfo, GINT_TO_POINTER(flags));
+       }
+
+       imap_seq_set_free(seq_list);
+       g_slist_free(deleted);
+       g_slist_free(flagged);
+       g_slist_free(answered);
+       g_slist_free(unseen);
+       /* new not freed in original patch ??? */
+       g_slist_free(sorted_list);
+       g_string_free(cmd_buf, TRUE);
+
+       return 0;
+}
index 41681157f513227c40e93acd9c44b9b581c7748f..2a8d3c737a483e52c15887baa6c035951461d3c7 100644 (file)
@@ -279,10 +279,10 @@ gint procmsg_send_message_queue           (const gchar *file);
 
 void procmsg_msginfo_set_flags         (MsgInfo *msginfo,
                                         MsgPermFlags perm_flags,
-                                         MsgTmpFlags tmp_flags);
+                                        MsgTmpFlags tmp_flags);
 void procmsg_msginfo_unset_flags       (MsgInfo *msginfo,
                                         MsgPermFlags perm_flags,
-                                         MsgTmpFlags tmp_flags);
+                                        MsgTmpFlags tmp_flags);
 gint procmsg_remove_special_headers    (const gchar    *in, 
                                         const gchar    *out);