[evolution-data-server] I#38 - Archive from search folder should use original folder for transfer



commit 29baf819afac77baffe997938ee852247d5c103c
Author: Milan Crha <mcrha redhat com>
Date:   Tue Oct 2 18:01:34 2018 +0200

    I#38 - Archive from search folder should use original folder for transfer
    
    Closes https://gitlab.gnome.org/GNOME/evolution-data-server/issues/38

 src/camel/camel-folder.c           | 133 ++++++++++++++++++++++++++++++++++++-
 src/camel/camel-vee-folder.c       |   2 +-
 src/camel/camel-vee-message-info.c |   8 ++-
 3 files changed, 137 insertions(+), 6 deletions(-)
---
diff --git a/src/camel/camel-folder.c b/src/camel/camel-folder.c
index 17d0983cd..1ecca75bb 100644
--- a/src/camel/camel-folder.c
+++ b/src/camel/camel-folder.c
@@ -4060,6 +4060,24 @@ camel_folder_synchronize_message_finish (CamelFolder *folder,
        return g_task_propagate_boolean (G_TASK (result), error);
 }
 
+typedef struct _UidIndexPair {
+       GPtrArray *uids; /* gchar * */
+       GPtrArray *indexes; /* GUINT_TO_POINTER () */
+} UidIndexPair;
+
+static void
+uid_index_pair_free (gpointer ptr)
+{
+       UidIndexPair *uip = ptr;
+
+       if (uip) {
+               g_ptr_array_unref (uip->uids);
+               if (uip->indexes)
+                       g_ptr_array_unref (uip->indexes);
+               g_free (uip);
+       }
+}
+
 /**
  * camel_folder_transfer_messages_to_sync:
  * @source: the source #CamelFolder
@@ -4092,7 +4110,7 @@ camel_folder_transfer_messages_to_sync (CamelFolder *source,
        CamelFolderClass *class;
        CamelStore *source_store;
        CamelStore *destination_store;
-       gboolean success;
+       gboolean success, done = FALSE;
 
        g_return_val_if_fail (CAMEL_IS_FOLDER (source), FALSE);
        g_return_val_if_fail (CAMEL_IS_FOLDER (destination), FALSE);
@@ -4124,7 +4142,118 @@ camel_folder_transfer_messages_to_sync (CamelFolder *source,
                success = class->transfer_messages_to_sync (
                        source, message_uids, destination, delete_originals,
                        transferred_uids, cancellable, error);
-       } else {
+
+               done = TRUE;
+       }
+
+       /* When the source folder is a virtual folder then split the transfer operation
+          to respective real folder(s). */
+       if (!done && CAMEL_IS_VEE_FOLDER (source)) {
+               GHashTable *todo; /* CamelFolder * ~> UidIndexPair * */
+               CamelVeeFolder *vfolder = CAMEL_VEE_FOLDER (source);
+               guint ii;
+
+               todo = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, 
uid_index_pair_free);
+
+               for (ii = 0; ii < message_uids->len; ii++) {
+                       CamelMessageInfo *nfo = camel_folder_get_message_info (source, 
message_uids->pdata[ii]);
+                       CamelFolder *folder;
+                       gchar *real_uid = NULL;
+
+                       if (!nfo)
+                               continue;
+
+                       folder = camel_vee_folder_get_location (vfolder, CAMEL_VEE_MESSAGE_INFO (nfo), 
&real_uid);
+                       if (folder && real_uid) {
+                               UidIndexPair *uip;
+
+                               uip = g_hash_table_lookup (todo, folder);
+                               if (!uip) {
+                                       uip = g_new0 (UidIndexPair, 1);
+                                       uip->uids = g_ptr_array_new_with_free_func ((GDestroyNotify) 
camel_pstring_free);
+                                       if (transferred_uids)
+                                               uip->indexes = g_ptr_array_new ();
+
+                                       g_hash_table_insert (todo, g_object_ref (folder), uip);
+                               }
+
+                               g_ptr_array_add (uip->uids, (gpointer) camel_pstring_strdup (real_uid));
+                               if (uip->indexes)
+                                       g_ptr_array_add (uip->indexes, GUINT_TO_POINTER (ii));
+                       }
+
+                       g_object_unref (nfo);
+                       g_free (real_uid);
+               }
+
+               done = g_hash_table_size (todo) > 0;
+
+               if (done) {
+                       GHashTableIter iter;
+                       gpointer key, value;
+
+                       if (transferred_uids) {
+                               *transferred_uids = g_ptr_array_new ();
+                               g_ptr_array_set_size (*transferred_uids, message_uids->len);
+                       }
+
+                       g_hash_table_iter_init (&iter, todo);
+                       while (g_hash_table_iter_next (&iter, &key, &value) && success) {
+                               CamelFolder *folder = key;
+                               UidIndexPair *uip = value;
+                               GPtrArray *transferred = NULL;
+
+                               source_store = camel_folder_get_parent_store (folder);
+
+                               if (source_store == destination_store) {
+                                       /* If either folder is a vtrash, we need to use the
+                                        * vtrash transfer method. */
+                                       if (CAMEL_IS_VTRASH_FOLDER (destination))
+                                               class = CAMEL_FOLDER_GET_CLASS (destination);
+                                       else
+                                               class = CAMEL_FOLDER_GET_CLASS (folder);
+
+                                       g_warn_if_fail (class != NULL);
+
+                                       success = class && class->transfer_messages_to_sync (
+                                               folder, uip->uids, destination, delete_originals,
+                                               transferred_uids ? &transferred : NULL, cancellable, error);
+                               } else {
+                                       success = folder_transfer_messages_to_sync (
+                                               folder, uip->uids, destination, delete_originals,
+                                               transferred_uids ? &transferred : NULL, cancellable, error);
+                               }
+
+                               if (transferred) {
+                                       g_warn_if_fail (transferred->len != uip->indexes->len);
+
+                                       for (ii = 0; ii < transferred->len && ii < uip->indexes->len; ii++) {
+                                               guint idx = GPOINTER_TO_UINT (uip->indexes->pdata[ii]);
+
+                                               g_warn_if_fail (idx < (*transferred_uids)->len);
+
+                                               if (idx < (*transferred_uids)->len) {
+                                                       (*transferred_uids)->pdata[idx] = 
transferred->pdata[ii];
+                                                       transferred->pdata[ii] = NULL;
+                                               }
+                                       }
+
+                                       g_ptr_array_foreach (transferred, (GFunc) g_free, NULL);
+                                       g_ptr_array_free (transferred, TRUE);
+                               }
+                       }
+
+                       if (!success && transferred_uids) {
+                               g_ptr_array_foreach (*transferred_uids, (GFunc) g_free, NULL);
+                               g_ptr_array_free (*transferred_uids, TRUE);
+                               *transferred_uids = NULL;
+                       }
+               }
+
+               g_hash_table_destroy (todo);
+       }
+
+       if (!done) {
                success = folder_transfer_messages_to_sync (
                        source, message_uids, destination, delete_originals,
                        transferred_uids, cancellable, error);
diff --git a/src/camel/camel-vee-folder.c b/src/camel/camel-vee-folder.c
index ec46465fe..75ff5b9e6 100644
--- a/src/camel/camel-vee-folder.c
+++ b/src/camel/camel-vee-folder.c
@@ -1901,7 +1901,7 @@ camel_vee_folder_get_location (CamelVeeFolder *vf,
  * @vfolder: a #CamelVeeFolder
  * @vee_message_uid: a virtual message info UID
  *
- * Returns: (transfer none) (nullable): a #CamelFolder to which the @vee_message_info
+ * Returns: (transfer none) (nullable): a #CamelFolder to which the @vee_message_uid
  *    belongs, or %NULL, when it could not be found.
  *
  * Since: 3.6
diff --git a/src/camel/camel-vee-message-info.c b/src/camel/camel-vee-message-info.c
index d932cfadd..f11bf3a0e 100644
--- a/src/camel/camel-vee-message-info.c
+++ b/src/camel/camel-vee-message-info.c
@@ -87,7 +87,8 @@ vee_message_info_notify_mi_changed (CamelFolder *folder,
                g_return_val_if_fail (CAMEL_IS_VEE_MESSAGE_INFO (mi), _err_ret);                \
                                                                                                \
                vmi = CAMEL_VEE_MESSAGE_INFO (mi);                                              \
-               g_return_val_if_fail (vmi->priv->orig_summary != NULL, _err_ret);               \
+               if (!vmi->priv->orig_summary)                                                   \
+                       return (_err_ret);                                                      \
                                                                                                \
                uid = camel_message_info_pooldup_uid (mi);                                      \
                g_return_val_if_fail (uid != NULL, _err_ret);                                   \
@@ -101,7 +102,7 @@ vee_message_info_notify_mi_changed (CamelFolder *folder,
                                                                                                \
                orig_mi = (CamelMessageInfo *) camel_folder_summary_get (vmi->priv->orig_summary, uid + 8);   
          \
                if (!orig_mi) {                                                                 \
-                       g_warning ("%s: Failed to get orig uid '%s'\n", G_STRFUNC, uid);        \
+                       /* It can be NULL when it had been removed from the orig folder */      \
                        camel_pstring_free (uid);                                               \
                        return _err_ret;                                                        \
                }                                                                               \
@@ -147,7 +148,8 @@ vee_message_info_read_flags_from_orig_summary (const CamelMessageInfo *mi,
        g_return_val_if_fail (out_flags != NULL, FALSE);
 
        vmi = CAMEL_VEE_MESSAGE_INFO (mi);
-       g_return_val_if_fail (vmi->priv->orig_summary != NULL, FALSE);
+       if (!vmi->priv->orig_summary)
+               return FALSE;
 
        uid = camel_message_info_pooldup_uid (mi);
        g_return_val_if_fail (uid != NULL, FALSE);


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