[evolution-data-server] Bug 766682 - Three-state value for 'download messages for offline' per folder



commit 60d550f89684bf5dc8935be2d9b33e8551ebf78f
Author: Milan Crha <mcrha redhat com>
Date:   Wed May 25 22:00:02 2016 +0200

    Bug 766682 - Three-state value for 'download messages for offline' per folder
    
    Camel soname version bump due to CamelOfflineFolder::offline-sync
    property changing its type from gboolean to CamelThreeState enum.

 camel/camel-enums.h                        |   16 ++++++
 camel/camel-object.c                       |   44 +++++++++++++---
 camel/camel-offline-folder.c               |   81 ++++++++++++++++++----------
 camel/camel-offline-folder.h               |    8 ++-
 camel/camel-offline-store.c                |   70 +++++-------------------
 camel/providers/imapx/camel-imapx-folder.c |    4 +-
 configure.ac                               |    2 +-
 docs/reference/camel/camel-sections.txt    |    1 +
 8 files changed, 127 insertions(+), 99 deletions(-)
---
diff --git a/camel/camel-enums.h b/camel/camel-enums.h
index 7a885d5..13577db 100644
--- a/camel/camel-enums.h
+++ b/camel/camel-enums.h
@@ -458,4 +458,20 @@ typedef enum {
        CAMEL_TRANSFER_NUM_ENCODINGS
 } CamelTransferEncoding;
 
+/**
+ * CamelThreeState:
+ * @CAMEL_THREE_STATE_OFF: the three-state value is Off
+ * @CAMEL_THREE_STATE_ON: the three-state value is On
+ * @CAMEL_THREE_STATE_INCONSISTENT: the three-state value is neither On, nor Off
+ *
+ * Describes a three-state value, which can be either Off, On or Inconsistent.
+ *
+ * Since: 3.22
+ **/
+typedef enum {
+       CAMEL_THREE_STATE_OFF = 0,
+       CAMEL_THREE_STATE_ON,
+       CAMEL_THREE_STATE_INCONSISTENT
+} CamelThreeState;
+
 #endif /* CAMEL_ENUMS_H */
diff --git a/camel/camel-object.c b/camel/camel-object.c
index 7587c63..1c3a545 100644
--- a/camel/camel-object.c
+++ b/camel/camel-object.c
@@ -27,6 +27,8 @@
 
 #include <glib/gstdio.h>
 
+#include "camel-enums.h"
+#include "camel-enumtypes.h"
 #include "camel-file-utils.h"
 #include "camel-object.h"
 
@@ -84,7 +86,8 @@ enum camel_arg_t {
        CAMEL_ARG_DBL = 0x20000000, /* gdouble */
        CAMEL_ARG_STR = 0x30000000, /* c string */
        CAMEL_ARG_PTR = 0x40000000, /* ptr */
-       CAMEL_ARG_BOO = 0x50000000  /* bool */
+       CAMEL_ARG_BOO = 0x50000000, /* bool */
+       CAMEL_ARG_3ST = 0x60000000  /* three-state */
 };
 
 #define CAMEL_ARGV_MAX (20)
@@ -157,7 +160,7 @@ object_state_read (CamelObject *object,
        if (camel_file_util_decode_uint32 (fp, &version) == -1)
                return -1;
 
-       if (version > 1)
+       if (version > 2)
                return -1;
 
        if (camel_file_util_decode_uint32 (fp, &count) == -1)
@@ -204,7 +207,7 @@ object_state_read (CamelObject *object,
                        goto exit;
 
                /* Record state file values into GValues.
-                * XXX We currently only support booleans. */
+                * XXX We currently only support booleans and three-state. */
                switch (tag & CAMEL_ARG_TYPE) {
                        case CAMEL_ARG_BOO:
                                if (camel_file_util_decode_uint32 (fp, &v_uint32) == -1)
@@ -212,6 +215,12 @@ object_state_read (CamelObject *object,
                                g_value_init (&value, G_TYPE_BOOLEAN);
                                g_value_set_boolean (&value, (gboolean) v_uint32);
                                break;
+                       case CAMEL_ARG_3ST:
+                               if (camel_file_util_decode_uint32 (fp, &v_uint32) == -1)
+                                       goto exit;
+                               g_value_init (&value, CAMEL_TYPE_THREE_STATE);
+                               g_value_set_enum (&value, (CamelThreeState) v_uint32);
+                               break;
                        default:
                                g_warn_if_reached ();
                                goto exit;
@@ -236,6 +245,17 @@ object_state_read (CamelObject *object,
                        if ((pspec->flags & CAMEL_PARAM_PERSISTENT) == 0)
                                continue;
 
+                       if (version == 1 && pspec->value_type == CAMEL_TYPE_THREE_STATE &&
+                           G_VALUE_HOLDS_BOOLEAN (&value)) {
+                               /* Convert from boolean to three-state value. Assign the 'TRUE' to 'On'
+                                  and the rest keep as 'Inconsistent'. */
+                               gboolean stored = g_value_get_boolean (&value);
+
+                               g_value_unset (&value);
+                               g_value_init (&value, CAMEL_TYPE_THREE_STATE);
+                               g_value_set_enum (&value, stored ? CAMEL_THREE_STATE_ON : 
CAMEL_THREE_STATE_INCONSISTENT);
+                       }
+
                        g_object_set_property (
                                G_OBJECT (object), pspec->name, &value);
 
@@ -278,8 +298,8 @@ object_state_write (CamelObject *object,
        class = G_OBJECT_GET_CLASS (object);
        properties = g_object_class_list_properties (class, &n_properties);
 
-       /* Version = 1 */
-       if (camel_file_util_encode_uint32 (fp, 1) == -1)
+       /* Version = 2 */
+       if (camel_file_util_encode_uint32 (fp, 2) == -1)
                goto exit;
 
        /* No meta-data items. */
@@ -325,8 +345,18 @@ object_state_write (CamelObject *object,
                                        goto exit;
                                break;
                        default:
-                               g_warn_if_reached ();
-                               goto exit;
+                               if (pspec->value_type == CAMEL_TYPE_THREE_STATE) {
+                                       tag |= CAMEL_ARG_3ST;
+                                       v_uint32 = g_value_get_enum (&value);
+                                       if (camel_file_util_encode_uint32 (fp, tag) == -1)
+                                               goto exit;
+                                       if (camel_file_util_encode_uint32 (fp, v_uint32) == -1)
+                                               goto exit;
+                               } else {
+                                       g_warn_if_reached ();
+                                       goto exit;
+                               }
+                               break;
                }
 
                g_value_unset (&value);
diff --git a/camel/camel-offline-folder.c b/camel/camel-offline-folder.c
index af18fc8..3bc3887 100644
--- a/camel/camel-offline-folder.c
+++ b/camel/camel-offline-folder.c
@@ -24,6 +24,7 @@
 #include <glib/gi18n-lib.h>
 
 #include "camel-debug.h"
+#include "camel-enumtypes.h"
 #include "camel-offline-folder.h"
 #include "camel-offline-settings.h"
 #include "camel-offline-store.h"
@@ -38,7 +39,7 @@ typedef struct _AsyncContext AsyncContext;
 typedef struct _OfflineDownsyncData OfflineDownsyncData;
 
 struct _CamelOfflineFolderPrivate {
-       gboolean offline_sync;
+       CamelThreeState offline_sync;
 
        GMutex store_changes_lock;
        guint store_changes_id;
@@ -225,32 +226,16 @@ static void
 offline_folder_changed (CamelFolder *folder,
                         CamelFolderChangeInfo *changes)
 {
-       CamelStore *parent_store;
-       CamelService *service;
+       CamelStore *store;
        CamelSession *session;
-       CamelSettings *settings;
-       gboolean sync_store;
-       gboolean sync_folder;
-
-       parent_store = camel_folder_get_parent_store (folder);
 
-       service = CAMEL_SERVICE (parent_store);
-       session = camel_service_ref_session (service);
+       store = camel_folder_get_parent_store (folder);
+       session = camel_service_ref_session (CAMEL_SERVICE (store));
 
        if (!session)
                return;
 
-       settings = camel_service_ref_settings (service);
-
-       sync_store = camel_offline_settings_get_stay_synchronized (
-               CAMEL_OFFLINE_SETTINGS (settings));
-
-       g_object_unref (settings);
-
-       sync_folder = camel_offline_folder_get_offline_sync (
-               CAMEL_OFFLINE_FOLDER (folder));
-
-       if (changes && changes->uid_added->len > 0 && (sync_store || sync_folder)) {
+       if (changes && changes->uid_added->len > 0 && camel_offline_folder_can_downsync (CAMEL_OFFLINE_FOLDER 
(folder))) {
                OfflineDownsyncData *data;
                gchar *description;
 
@@ -285,7 +270,7 @@ offline_folder_set_property (GObject *object,
                case PROP_OFFLINE_SYNC:
                        camel_offline_folder_set_offline_sync (
                                CAMEL_OFFLINE_FOLDER (object),
-                               g_value_get_boolean (value));
+                               g_value_get_enum (value));
                        return;
        }
 
@@ -300,7 +285,7 @@ offline_folder_get_property (GObject *object,
 {
        switch (property_id) {
                case PROP_OFFLINE_SYNC:
-                       g_value_set_boolean (
+                       g_value_set_enum (
                                value, camel_offline_folder_get_offline_sync (
                                CAMEL_OFFLINE_FOLDER (object)));
                        return;
@@ -432,11 +417,12 @@ camel_offline_folder_class_init (CamelOfflineFolderClass *class)
        g_object_class_install_property (
                object_class,
                PROP_OFFLINE_SYNC,
-               g_param_spec_boolean (
+               g_param_spec_enum (
                        "offline-sync",
                        "Offline Sync",
                        _("Copy folder content locally for _offline operation"),
-                       FALSE,
+                       CAMEL_TYPE_THREE_STATE,
+                       CAMEL_THREE_STATE_INCONSISTENT,
                        G_PARAM_READWRITE |
                        CAMEL_PARAM_PERSISTENT));
 }
@@ -448,6 +434,7 @@ camel_offline_folder_init (CamelOfflineFolder *folder)
 
        g_mutex_init (&folder->priv->store_changes_lock);
        folder->priv->store_changes_after_frozen = FALSE;
+       folder->priv->offline_sync = CAMEL_THREE_STATE_INCONSISTENT;
 
        g_signal_connect (
                folder, "changed",
@@ -460,10 +447,10 @@ camel_offline_folder_init (CamelOfflineFolder *folder)
  *
  * Since: 2.32
  **/
-gboolean
+CamelThreeState
 camel_offline_folder_get_offline_sync (CamelOfflineFolder *folder)
 {
-       g_return_val_if_fail (CAMEL_IS_OFFLINE_FOLDER (folder), FALSE);
+       g_return_val_if_fail (CAMEL_IS_OFFLINE_FOLDER (folder), CAMEL_THREE_STATE_INCONSISTENT);
 
        return folder->priv->offline_sync;
 }
@@ -471,13 +458,15 @@ camel_offline_folder_get_offline_sync (CamelOfflineFolder *folder)
 /**
  * camel_offline_folder_set_offline_sync:
  * @folder: a #CamelOfflineFolder
- * @offline_sync: whether to synchronize for offline use
+ * @offline_sync: whether to synchronize for offline use, as a #CamelThreeState enum
+ *
+ * The %CAMEL_THREE_STATE_INCONSISTENT means what the parent store has set.
  *
  * Since: 2.32
  **/
 void
 camel_offline_folder_set_offline_sync (CamelOfflineFolder *folder,
-                                       gboolean offline_sync)
+                                       CamelThreeState offline_sync)
 {
        g_return_if_fail (CAMEL_IS_OFFLINE_FOLDER (folder));
 
@@ -490,6 +479,40 @@ camel_offline_folder_set_offline_sync (CamelOfflineFolder *folder,
 }
 
 /**
+ * camel_offline_folder_can_downsync:
+ * @folder: a #CamelOfflineFolder
+ *
+ * Checks whether the @folder can run downsync according to its
+ * settings (camel_offline_folder_get_offline_sync()) and to
+ * the parent's #CamelOfflineStore settings (camel_offline_settings_get_stay_synchronized()).
+ *
+ * Returns: %TRUE, when the @folder can be synchronized for offline; %FALSE otherwise.
+ *
+ * Since: 3.22
+ **/
+gboolean
+camel_offline_folder_can_downsync (CamelOfflineFolder *folder)
+{
+       CamelService *service;
+       CamelSettings *settings;
+       CamelThreeState sync_folder;
+       gboolean sync_store;
+
+       g_return_val_if_fail (CAMEL_IS_OFFLINE_FOLDER (folder), FALSE);
+
+       service = CAMEL_SERVICE (camel_folder_get_parent_store (CAMEL_FOLDER (folder)));
+       settings = camel_service_ref_settings (service);
+
+       sync_store = camel_offline_settings_get_stay_synchronized (CAMEL_OFFLINE_SETTINGS (settings));
+
+       g_object_unref (settings);
+
+       sync_folder = camel_offline_folder_get_offline_sync (CAMEL_OFFLINE_FOLDER (folder));
+
+       return sync_folder == CAMEL_THREE_STATE_ON || (sync_store && sync_folder == 
CAMEL_THREE_STATE_INCONSISTENT);
+}
+
+/**
  * camel_offline_folder_downsync_sync:
  * @folder: a #CamelOfflineFolder
  * @expression: search expression describing which set of messages
diff --git a/camel/camel-offline-folder.h b/camel/camel-offline-folder.h
index 33a4fd0..0182cb3 100644
--- a/camel/camel-offline-folder.h
+++ b/camel/camel-offline-folder.h
@@ -24,6 +24,7 @@
 #ifndef CAMEL_OFFLINE_FOLDER_H
 #define CAMEL_OFFLINE_FOLDER_H
 
+#include <camel/camel-enums.h>
 #include <camel/camel-folder.h>
 
 /* Standard GObject macros */
@@ -70,12 +71,13 @@ struct _CamelOfflineFolderClass {
 };
 
 GType          camel_offline_folder_get_type   (void);
-gboolean       camel_offline_folder_get_offline_sync
+CamelThreeState        camel_offline_folder_get_offline_sync
                                                (CamelOfflineFolder *folder);
 void           camel_offline_folder_set_offline_sync
                                                (CamelOfflineFolder *folder,
-                                                gboolean offline_sync);
-
+                                                CamelThreeState offline_sync);
+gboolean       camel_offline_folder_can_downsync
+                                               (CamelOfflineFolder *folder);
 gboolean       camel_offline_folder_downsync_sync
                                                (CamelOfflineFolder *folder,
                                                 const gchar *expression,
diff --git a/camel/camel-offline-store.c b/camel/camel-offline-store.c
index 0965c76..2865906 100644
--- a/camel/camel-offline-store.c
+++ b/camel/camel-offline-store.c
@@ -171,11 +171,9 @@ camel_offline_store_set_online_sync (CamelOfflineStore *store,
                                      GError **error)
 {
        CamelService *service;
-       CamelSettings *settings;
        CamelServiceConnectionStatus status;
        gboolean host_reachable = TRUE;
        gboolean store_is_online;
-       gboolean sync_store;
        gboolean success = TRUE;
 
        g_return_val_if_fail (CAMEL_IS_OFFLINE_STORE (store), FALSE);
@@ -203,13 +201,6 @@ camel_offline_store_set_online_sync (CamelOfflineStore *store,
 
        store_is_online = camel_offline_store_get_online (store);
 
-       settings = camel_service_ref_settings (service);
-
-       sync_store = camel_offline_settings_get_stay_synchronized (
-               CAMEL_OFFLINE_SETTINGS (settings));
-
-       g_object_unref (settings);
-
        /* Returning to online mode is the simpler case. */
        if (!store_is_online) {
                store->priv->online = online;
@@ -239,19 +230,15 @@ camel_offline_store_set_online_sync (CamelOfflineStore *store,
 
                for (ii = 0; ii < folders->len; ii++) {
                        CamelFolder *folder = folders->pdata[ii];
-                       gboolean sync_folder;
+                       CamelOfflineFolder *offline_folder;
 
                        if (!CAMEL_IS_OFFLINE_FOLDER (folder))
                                continue;
 
-                       sync_folder =
-                               camel_offline_folder_get_offline_sync (
-                               CAMEL_OFFLINE_FOLDER (folder));
+                       offline_folder = CAMEL_OFFLINE_FOLDER (folder);
 
-                       if (sync_store || sync_folder)
-                               camel_offline_folder_downsync_sync (
-                                       CAMEL_OFFLINE_FOLDER (folder),
-                                       NULL, cancellable, NULL);
+                       if (camel_offline_folder_can_downsync (offline_folder))
+                               camel_offline_folder_downsync_sync (offline_folder, NULL, cancellable, NULL);
                }
 
                g_ptr_array_foreach (folders, (GFunc) g_object_unref, NULL);
@@ -283,15 +270,11 @@ camel_offline_store_prepare_for_offline_sync (CamelOfflineStore *store,
                                               GCancellable *cancellable,
                                               GError **error)
 {
-       CamelService *service;
-       CamelSettings *settings;
        gboolean host_reachable = TRUE;
        gboolean store_is_online;
-       gboolean sync_store;
 
        g_return_val_if_fail (CAMEL_IS_OFFLINE_STORE (store), FALSE);
 
-       service = CAMEL_SERVICE (store);
        store_is_online = camel_offline_store_get_online (store);
 
        if (store_is_online && CAMEL_IS_NETWORK_SERVICE (store)) {
@@ -303,13 +286,6 @@ camel_offline_store_prepare_for_offline_sync (CamelOfflineStore *store,
                        cancellable, NULL);
        }
 
-       settings = camel_service_ref_settings (service);
-
-       sync_store = camel_offline_settings_get_stay_synchronized (
-               CAMEL_OFFLINE_SETTINGS (settings));
-
-       g_object_unref (settings);
-
        if (host_reachable && store_is_online) {
                GPtrArray *folders;
                guint ii;
@@ -319,20 +295,15 @@ camel_offline_store_prepare_for_offline_sync (CamelOfflineStore *store,
 
                for (ii = 0; ii < folders->len; ii++) {
                        CamelFolder *folder = folders->pdata[ii];
-                       gboolean sync_folder;
+                       CamelOfflineFolder *offline_folder;
 
                        if (!CAMEL_IS_OFFLINE_FOLDER (folder))
                                continue;
 
-                       sync_folder =
-                               camel_offline_folder_get_offline_sync (
-                               CAMEL_OFFLINE_FOLDER (folder));
+                       offline_folder = CAMEL_OFFLINE_FOLDER (folder);
 
-                       if (sync_store || sync_folder) {
-                               camel_offline_folder_downsync_sync (
-                                       CAMEL_OFFLINE_FOLDER (folder),
-                                       NULL, cancellable, NULL);
-                       }
+                       if (camel_offline_folder_can_downsync (offline_folder))
+                               camel_offline_folder_downsync_sync (offline_folder, NULL, cancellable, NULL);
                }
 
                g_ptr_array_foreach (folders, (GFunc) g_object_unref, NULL);
@@ -361,16 +332,12 @@ camel_offline_store_prepare_for_offline_sync (CamelOfflineStore *store,
 gboolean
 camel_offline_store_requires_downsync (CamelOfflineStore *store)
 {
-       CamelService *service;
-       CamelSettings *settings;
        gboolean host_reachable = TRUE;
        gboolean store_is_online;
-       gboolean sync_store;
+       gboolean sync_any_folder = FALSE;
 
        g_return_val_if_fail (CAMEL_IS_OFFLINE_STORE (store), FALSE);
 
-       service = CAMEL_SERVICE (store);
-
        if (CAMEL_IS_NETWORK_SERVICE (store)) {
                host_reachable =
                        camel_network_service_get_host_reachable (
@@ -382,42 +349,33 @@ camel_offline_store_requires_downsync (CamelOfflineStore *store)
        if (!store_is_online)
                return FALSE;
 
-       settings = camel_service_ref_settings (service);
-
-       sync_store = camel_offline_settings_get_stay_synchronized (
-               CAMEL_OFFLINE_SETTINGS (settings));
-
-       g_object_unref (settings);
-
        if (host_reachable) {
                CamelSession *session;
 
-               session = camel_service_ref_session (service);
+               session = camel_service_ref_session (CAMEL_SERVICE (store));
                host_reachable = session && camel_session_get_online (session);
                g_clear_object (&session);
        }
 
-       if (host_reachable && !sync_store) {
+       if (host_reachable) {
                GPtrArray *folders;
                guint ii;
 
                folders = camel_object_bag_list (
                        CAMEL_STORE (store)->folders);
 
-               for (ii = 0; ii < folders->len && !sync_store; ii++) {
+               for (ii = 0; ii < folders->len && !sync_any_folder; ii++) {
                        CamelFolder *folder = folders->pdata[ii];
 
                        if (!CAMEL_IS_OFFLINE_FOLDER (folder))
                                continue;
 
-                       sync_store = sync_store ||
-                               camel_offline_folder_get_offline_sync (
-                               CAMEL_OFFLINE_FOLDER (folder));
+                       sync_any_folder = camel_offline_folder_can_downsync (CAMEL_OFFLINE_FOLDER (folder));
                }
 
                g_ptr_array_foreach (folders, (GFunc) g_object_unref, NULL);
                g_ptr_array_free (folders, TRUE);
        }
 
-       return sync_store && host_reachable;
+       return sync_any_folder && host_reachable;
 }
diff --git a/camel/providers/imapx/camel-imapx-folder.c b/camel/providers/imapx/camel-imapx-folder.c
index e53b050..1250709 100644
--- a/camel/providers/imapx/camel-imapx-folder.c
+++ b/camel/providers/imapx/camel-imapx-folder.c
@@ -1050,7 +1050,6 @@ camel_imapx_folder_new (CamelStore *store,
        gboolean filter_inbox;
        gboolean filter_junk;
        gboolean filter_junk_inbox;
-       gboolean store_offline_sync = FALSE;
 
        d ("opening imap folder '%s'\n", folder_dir);
 
@@ -1064,7 +1063,6 @@ camel_imapx_folder_new (CamelStore *store,
                "filter-inbox", &filter_inbox,
                "filter-junk", &filter_junk,
                "filter-junk-inbox", &filter_junk_inbox,
-               "stay-synchronized", &store_offline_sync,
                NULL);
 
        g_object_unref (settings);
@@ -1104,7 +1102,7 @@ camel_imapx_folder_new (CamelStore *store,
        g_free (state_file);
        camel_object_state_read (CAMEL_OBJECT (folder));
 
-       if (store_offline_sync || camel_offline_folder_get_offline_sync (CAMEL_OFFLINE_FOLDER (folder))) {
+       if (camel_offline_folder_can_downsync (CAMEL_OFFLINE_FOLDER (folder))) {
                /* Ensure cache will never expire, otherwise
                 * it causes redownload of messages. */
                camel_data_cache_set_expire_age (imapx_folder->cache, -1);
diff --git a/configure.ac b/configure.ac
index 1dc4d1d..cbf7aeb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -136,7 +136,7 @@ LIBEBOOK_CONTACTS_CURRENT=2
 LIBEBOOK_CONTACTS_REVISION=0
 LIBEBOOK_CONTACTS_AGE=0
 
-LIBCAMEL_CURRENT=57
+LIBCAMEL_CURRENT=58
 LIBCAMEL_REVISION=0
 LIBCAMEL_AGE=0
 
diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt
index b870454..0e663a5 100644
--- a/docs/reference/camel/camel-sections.txt
+++ b/docs/reference/camel/camel-sections.txt
@@ -1552,6 +1552,7 @@ camel_error_quark
 CamelOfflineFolder
 camel_offline_folder_get_offline_sync
 camel_offline_folder_set_offline_sync
+camel_offline_folder_can_downsync
 camel_offline_folder_downsync_sync
 camel_offline_folder_downsync
 camel_offline_folder_downsync_finish


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