[evolution-data-server] [IMAPx] Local changes not always properly saved to the server



commit ccb5cc0e439918efab987220888509763372c908
Author: Milan Crha <mcrha redhat com>
Date:   Wed Sep 2 09:13:02 2015 +0200

    [IMAPx] Local changes not always properly saved to the server
    
    It could happen that some local changes were forgotten and reverted
    the next time the folder had been refreshed. This change addresses
    the issue. It also covers the case when some message info changes
    were done during the current set of changes being saved.

 camel/providers/imapx/camel-imapx-server.c  |   42 ++++++++++++++-
 camel/providers/imapx/camel-imapx-summary.c |   72 +++++++++++++++++++++++----
 2 files changed, 101 insertions(+), 13 deletions(-)
---
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 5595d20..c9f17d5 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -4993,6 +4993,21 @@ imapx_unset_folder_flagged_flag (CamelFolderSummary *summary,
        }
 }
 
+static void
+imapx_server_info_changed_cb (CamelIMAPXSummary *summary,
+                             CamelMessageInfo *info,
+                             gpointer user_data)
+{
+       GHashTable *changed_meanwhile = user_data;
+
+       g_return_if_fail (info != NULL);
+       g_return_if_fail (changed_meanwhile != NULL);
+
+       g_hash_table_insert (changed_meanwhile,
+               (gpointer) camel_pstring_strdup (camel_message_info_uid (info)),
+               GINT_TO_POINTER (1));
+}
+
 gboolean
 camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
                                      CamelIMAPXMailbox *mailbox,
@@ -5005,6 +5020,8 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
        CamelFolder *folder;
        CamelIMAPXMessageInfo *info;
        CamelIMAPXSettings *settings;
+       GHashTable *changed_meanwhile;
+       gulong changed_meanwhile_handler_id;
        guint32 permanentflags;
        struct _uidset_state uidset;
        gint unread_change = 0;
@@ -5038,6 +5055,10 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
                return TRUE;
        }
 
+       changed_meanwhile = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) 
camel_pstring_free, NULL);
+       changed_meanwhile_handler_id = g_signal_connect (folder->summary, "info-changed",
+               G_CALLBACK (imapx_server_info_changed_cb), changed_meanwhile);
+
        settings = camel_imapx_server_ref_settings (is);
        use_real_junk_path = camel_imapx_settings_get_use_real_junk_path (settings);
        use_real_trash_path = camel_imapx_settings_get_use_real_trash_path (settings);
@@ -5173,19 +5194,24 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
                (off_user == NULL);
 
        if (nothing_to_do) {
+               g_signal_handler_disconnect (folder->summary, changed_meanwhile_handler_id);
+
                imapx_sync_free_user (on_user);
                imapx_sync_free_user (off_user);
                imapx_unset_folder_flagged_flag (folder->summary, changed_uids, remove_deleted_flags);
                camel_folder_free_uids (folder, changed_uids);
+               g_hash_table_destroy (changed_meanwhile);
                g_object_unref (folder);
                return TRUE;
        }
 
        if (!camel_imapx_server_ensure_selected_sync (is, mailbox, cancellable, error)) {
+               g_signal_handler_disconnect (folder->summary, changed_meanwhile_handler_id);
+
                imapx_sync_free_user (on_user);
                imapx_sync_free_user (off_user);
-               imapx_unset_folder_flagged_flag (folder->summary, changed_uids, remove_deleted_flags);
                camel_folder_free_uids (folder, changed_uids);
+               g_hash_table_destroy (changed_meanwhile);
                g_object_unref (folder);
                return FALSE;
        }
@@ -5275,10 +5301,10 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
                        g_warn_if_fail (ic == NULL);
                }
 
-               if (user_set && (permanentflags & CAMEL_MESSAGE_USER) != 0) {
+               if (user_set && (permanentflags & CAMEL_MESSAGE_USER) != 0 && success) {
                        CamelIMAPXCommand *ic = NULL;
 
-                       for (jj = 0; jj < user_set->len; jj++) {
+                       for (jj = 0; jj < user_set->len && success; jj++) {
                                struct _imapx_flag_change *c = &g_array_index (user_set, struct 
_imapx_flag_change, jj);
 
                                imapx_uidset_init (&uidset, 0, 100);
@@ -5311,12 +5337,16 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
                }
        }
 
+       g_signal_handler_disconnect (folder->summary, changed_meanwhile_handler_id);
+
        if (success) {
                CamelStore *parent_store;
                guint32 unseen;
 
                parent_store = camel_folder_get_parent_store (folder);
 
+               camel_folder_summary_lock (folder->summary);
+
                for (i = 0; i < changed_uids->len; i++) {
                        CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) camel_folder_summary_get 
(folder->summary,
                                        changed_uids->pdata[i]);
@@ -5338,10 +5368,15 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
                            camel_flag_list_size (&xinfo->server_user_flags) == 0)
                                camel_flag_list_copy (&xinfo->server_user_flags, &xinfo->info.user_flags);
 
+                       if (g_hash_table_lookup (changed_meanwhile, changed_uids->pdata[i]))
+                               xinfo->info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
+
                        camel_folder_summary_touch (folder->summary);
                        camel_message_info_unref (xinfo);
                }
 
+               camel_folder_summary_unlock (folder->summary);
+
                /* Apply the changes to server-side unread count; it won't tell
                 * us of these changes, of course. */
                unseen = camel_imapx_mailbox_get_unseen (mailbox);
@@ -5372,6 +5407,7 @@ camel_imapx_server_sync_changes_sync (CamelIMAPXServer *is,
        imapx_sync_free_user (on_user);
        imapx_sync_free_user (off_user);
        camel_folder_free_uids (folder, changed_uids);
+       g_hash_table_destroy (changed_meanwhile);
        g_object_unref (folder);
 
        return success;
diff --git a/camel/providers/imapx/camel-imapx-summary.c b/camel/providers/imapx/camel-imapx-summary.c
index bf6f741..dbaff72 100644
--- a/camel/providers/imapx/camel-imapx-summary.c
+++ b/camel/providers/imapx/camel-imapx-summary.c
@@ -34,6 +34,13 @@
 
 #define CAMEL_IMAPX_SUMMARY_VERSION (4)
 
+enum {
+       INFO_CHANGED,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
 G_DEFINE_TYPE (
        CamelIMAPXSummary,
        camel_imapx_summary,
@@ -249,6 +256,15 @@ imapx_summary_message_info_clone (CamelFolderSummary *summary,
        return copy;
 }
 
+static void
+imapx_summary_emit_info_changed (CamelMessageInfo *info)
+{
+       g_return_if_fail (info != NULL);
+       g_return_if_fail (CAMEL_IS_IMAPX_SUMMARY (info->summary));
+
+       g_signal_emit (info->summary, signals[INFO_CHANGED], 0, info);
+}
+
 static gboolean
 imapx_summary_info_set_user_flag (CamelMessageInfo *info,
                                   const gchar *id,
@@ -256,18 +272,43 @@ imapx_summary_info_set_user_flag (CamelMessageInfo *info,
 {
        gboolean changed;
 
-       /* Chain up to parent's info_set_user_flag() method. */
-       changed = CAMEL_FOLDER_SUMMARY_CLASS (
-               camel_imapx_summary_parent_class)->
-               info_set_user_flag (info, id, state);
+       /* Chain up to parent's method. */
+       changed = CAMEL_FOLDER_SUMMARY_CLASS (camel_imapx_summary_parent_class)->info_set_user_flag (info, 
id, state);
 
-       /* there was a change, so do not forget to store it to server */
-       if (changed) {
-               CamelIMAPXMessageInfo *imapx_info;
+       if (changed)
+               imapx_summary_emit_info_changed (info);
 
-               imapx_info = (CamelIMAPXMessageInfo *) info;
-               imapx_info->info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
-       }
+       return changed;
+}
+
+static gboolean
+imapx_summary_info_set_user_tag (CamelMessageInfo *info,
+                                const gchar *name,
+                                const gchar *value)
+{
+       gboolean changed;
+
+       /* Chain up to parent's method. */
+       changed = CAMEL_FOLDER_SUMMARY_CLASS (camel_imapx_summary_parent_class)->info_set_user_tag (info, 
name, value);
+
+       if (changed)
+               imapx_summary_emit_info_changed (info);
+
+       return changed;
+}
+
+static gboolean
+imapx_summary_info_set_flags (CamelMessageInfo *info,
+                             guint32 flags,
+                             guint32 set)
+{
+       gboolean changed;
+
+       /* Chain up to parent's method. */
+       changed = CAMEL_FOLDER_SUMMARY_CLASS (camel_imapx_summary_parent_class)->info_set_flags (info, flags, 
set);
+
+       if (changed)
+               imapx_summary_emit_info_changed (info);
 
        return changed;
 }
@@ -289,6 +330,17 @@ camel_imapx_summary_class_init (CamelIMAPXSummaryClass *class)
        folder_summary_class->message_info_free = imapx_summary_message_info_free;
        folder_summary_class->message_info_clone = imapx_summary_message_info_clone;
        folder_summary_class->info_set_user_flag = imapx_summary_info_set_user_flag;
+       folder_summary_class->info_set_user_tag = imapx_summary_info_set_user_tag;
+       folder_summary_class->info_set_flags = imapx_summary_info_set_flags;
+
+       signals[INFO_CHANGED] = g_signal_new (
+               "info-changed",
+               G_OBJECT_CLASS_TYPE (class),
+               G_SIGNAL_RUN_LAST,
+               0 /* G_STRUCT_OFFSET (CamelIMAPXSummaryClass, info_changed) */,
+               NULL, NULL, NULL,
+               G_TYPE_NONE, 1,
+               G_TYPE_POINTER /* CamelMessageInfo * */);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]