summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2020-11-19 16:56:56 +0100
committerMilan Crha <mcrha@redhat.com>2020-11-19 16:56:56 +0100
commit9f9f5c12f518db081010cacfcc982a15e1fed04d (patch)
tree5e3e8d89daaacf331d28a5c878f0ff41d0fc6ac1
parent74fa03dc54b9c6e60bdcf6264cbb40da50677b6f (diff)
downloadevolution-data-server-9f9f5c12f518db081010cacfcc982a15e1fed04d.tar.gz
I#273 - Camel: Save folder changes periodically
Closes https://gitlab.gnome.org/GNOME/evolution-data-server/-/issues/273
-rw-r--r--src/camel/camel-folder.c133
-rw-r--r--src/camel/camel-local-settings.h12
-rw-r--r--src/camel/camel-offline-folder.c161
-rw-r--r--src/camel/camel-offline-settings.c41
-rw-r--r--src/camel/camel-offline-store.c22
-rw-r--r--src/camel/camel-store-settings.c77
-rw-r--r--src/camel/camel-store-settings.h5
-rw-r--r--src/camel/camel-store.c31
-rw-r--r--src/camel/camel-store.h6
-rw-r--r--src/camel/camel-vee-store.c8
10 files changed, 289 insertions, 207 deletions
diff --git a/src/camel/camel-folder.c b/src/camel/camel-folder.c
index a0e7c5c9e..f39ace33a 100644
--- a/src/camel/camel-folder.c
+++ b/src/camel/camel-folder.c
@@ -36,6 +36,7 @@
#include "camel-operation.h"
#include "camel-session.h"
#include "camel-store.h"
+#include "camel-store-settings.h"
#include "camel-vtrash-folder.h"
#include "camel-string-utils.h"
@@ -70,6 +71,10 @@ struct _CamelFolderPrivate {
CamelThreeState mark_seen;
gint mark_seen_timeout;
+
+ GMutex store_changes_lock;
+ guint store_changes_id;
+ gboolean store_changes_after_frozen;
};
struct _AsyncContext {
@@ -133,6 +138,110 @@ G_DEFINE_BOXED_TYPE (CamelFolderQuotaInfo,
camel_folder_quota_info_clone,
camel_folder_quota_info_free)
+
+static void
+folder_store_changes_job_cb (CamelSession *session,
+ GCancellable *cancellable,
+ gpointer user_data,
+ GError **error)
+{
+ CamelFolder *folder = user_data;
+
+ g_return_if_fail (CAMEL_IS_FOLDER (folder));
+
+ camel_folder_synchronize_sync (folder, FALSE, cancellable, error);
+}
+
+static gboolean
+folder_schedule_store_changes_job (gpointer user_data)
+{
+ CamelFolder *folder = user_data;
+ GSource *source;
+
+ source = g_main_current_source ();
+
+ if (g_source_is_destroyed (source))
+ return FALSE;
+
+ g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+
+ g_mutex_lock (&folder->priv->store_changes_lock);
+
+ if (folder->priv->store_changes_id == g_source_get_id (source)) {
+ CamelSession *session;
+ CamelStore *parent_store;
+
+ folder->priv->store_changes_id = 0;
+
+ parent_store = camel_folder_get_parent_store (folder);
+ session = parent_store ? camel_service_ref_session (CAMEL_SERVICE (parent_store)) : NULL;
+ if (session) {
+ gchar *description;
+
+ /* Translators: The first “%s” is replaced with an account name and the second “%s”
+ is replaced with a full path name. The spaces around “:” are intentional, as
+ the whole “%s : %s” is meant as an absolute identification of the folder. */
+ description = g_strdup_printf (_("Storing changes in folder “%s : %s”"),
+ camel_service_get_display_name (CAMEL_SERVICE (parent_store)),
+ camel_folder_get_full_name (folder));
+
+ camel_session_submit_job (session, description,
+ folder_store_changes_job_cb,
+ g_object_ref (folder), g_object_unref);
+
+ g_free (description);
+ }
+
+ g_clear_object (&session);
+ }
+
+ g_mutex_unlock (&folder->priv->store_changes_lock);
+
+ return FALSE;
+}
+
+static void
+folder_maybe_schedule_folder_change_store (CamelFolder *folder)
+{
+ CamelStore *store;
+
+ g_return_if_fail (CAMEL_IS_FOLDER (folder));
+
+ g_mutex_lock (&folder->priv->store_changes_lock);
+
+ if (folder->priv->store_changes_id)
+ g_source_remove (folder->priv->store_changes_id);
+ folder->priv->store_changes_id = 0;
+ folder->priv->store_changes_after_frozen = FALSE;
+
+ if (camel_folder_is_frozen (folder)) {
+ folder->priv->store_changes_after_frozen = TRUE;
+ g_mutex_unlock (&folder->priv->store_changes_lock);
+
+ return;
+ }
+
+ store = camel_folder_get_parent_store (folder);
+
+ if (store && camel_store_get_can_auto_save_changes (store)) {
+ CamelSettings *settings;
+ gint interval = -1;
+
+ settings = camel_service_ref_settings (CAMEL_SERVICE (store));
+ if (settings && CAMEL_IS_STORE_SETTINGS (settings))
+ interval = camel_store_settings_get_store_changes_interval (CAMEL_STORE_SETTINGS (settings));
+ g_clear_object (&settings);
+
+ if (interval == 0)
+ folder_schedule_store_changes_job (folder);
+ else if (interval > 0)
+ folder->priv->store_changes_id = g_timeout_add_seconds (interval,
+ folder_schedule_store_changes_job, folder);
+ }
+
+ g_mutex_unlock (&folder->priv->store_changes_lock);
+}
+
static void
async_context_free (AsyncContext *async_context)
{
@@ -190,6 +299,9 @@ folder_emit_changed_cb (gpointer user_data)
g_signal_emit (folder, signals[CHANGED], 0, changes);
+ if (changes && changes->uid_changed && changes->uid_changed->len > 0)
+ folder_maybe_schedule_folder_change_store (folder);
+
camel_folder_change_info_free (changes);
return FALSE;
@@ -688,6 +800,12 @@ folder_dispose (GObject *object)
folder->priv->parent_store = NULL;
}
+ g_mutex_lock (&folder->priv->store_changes_lock);
+ if (folder->priv->store_changes_id)
+ g_source_remove (folder->priv->store_changes_id);
+ folder->priv->store_changes_id = 0;
+ g_mutex_unlock (&folder->priv->store_changes_lock);
+
/* Chain up to parent's dispose () method. */
G_OBJECT_CLASS (camel_folder_parent_class)->dispose (object);
}
@@ -712,6 +830,7 @@ folder_finalize (GObject *object)
g_rec_mutex_clear (&priv->lock);
g_mutex_clear (&priv->change_lock);
+ g_mutex_clear (&priv->store_changes_lock);
/* Chain up to parent's finalize () method. */
G_OBJECT_CLASS (camel_folder_parent_class)->finalize (object);
@@ -1019,6 +1138,18 @@ folder_thaw (CamelFolder *folder)
if (folder->priv->summary)
camel_folder_summary_save (folder->priv->summary, NULL);
}
+
+ if (!camel_folder_is_frozen (folder)) {
+ g_mutex_lock (&folder->priv->store_changes_lock);
+ if (folder->priv->store_changes_after_frozen) {
+ folder->priv->store_changes_after_frozen = FALSE;
+ g_mutex_unlock (&folder->priv->store_changes_lock);
+
+ folder_maybe_schedule_folder_change_store (folder);
+ } else {
+ g_mutex_unlock (&folder->priv->store_changes_lock);
+ }
+ }
}
static gboolean
@@ -1423,10 +1554,12 @@ camel_folder_init (CamelFolder *folder)
folder->priv = camel_folder_get_instance_private (folder);
folder->priv->frozen = 0;
folder->priv->changed_frozen = camel_folder_change_info_new ();
+ folder->priv->store_changes_after_frozen = FALSE;
g_rec_mutex_init (&folder->priv->lock);
g_mutex_init (&folder->priv->change_lock);
g_mutex_init (&folder->priv->property_lock);
+ g_mutex_init (&folder->priv->store_changes_lock);
}
G_DEFINE_QUARK (camel-folder-error-quark, camel_folder_error)
diff --git a/src/camel/camel-local-settings.h b/src/camel/camel-local-settings.h
index ea5b76cce..04c705e41 100644
--- a/src/camel/camel-local-settings.h
+++ b/src/camel/camel-local-settings.h
@@ -77,15 +77,15 @@ gchar * camel_local_settings_dup_path (CamelLocalSettings *settings);
void camel_local_settings_set_path (CamelLocalSettings *settings,
const gchar *path);
gboolean camel_local_settings_get_filter_all
- (CamelLocalSettings *settings);
+ (CamelLocalSettings *settings);
void camel_local_settings_set_filter_all
- (CamelLocalSettings *settings,
- gboolean filter_all);
+ (CamelLocalSettings *settings,
+ gboolean filter_all);
gboolean camel_local_settings_get_filter_junk
- (CamelLocalSettings *settings);
+ (CamelLocalSettings *settings);
void camel_local_settings_set_filter_junk
- (CamelLocalSettings *settings,
- gboolean filter_junk);
+ (CamelLocalSettings *settings,
+ gboolean filter_junk);
G_END_DECLS
diff --git a/src/camel/camel-offline-folder.c b/src/camel/camel-offline-folder.c
index abaf7bd6a..270fd18b3 100644
--- a/src/camel/camel-offline-folder.c
+++ b/src/camel/camel-offline-folder.c
@@ -37,10 +37,6 @@ typedef struct _OfflineDownsyncData OfflineDownsyncData;
struct _CamelOfflineFolderPrivate {
CamelThreeState offline_sync;
- GMutex store_changes_lock;
- guint store_changes_id;
- gboolean store_changes_after_frozen;
-
GMutex ongoing_downloads_lock;
GHashTable *ongoing_downloads; /* gchar * UID ~> g_thread_self() */
};
@@ -234,112 +230,6 @@ offline_folder_downsync_background (CamelSession *session,
}
static void
-offline_folder_store_changes_job_cb (CamelSession *session,
- GCancellable *cancellable,
- gpointer user_data,
- GError **error)
-{
- CamelFolder *folder = user_data;
-
- g_return_if_fail (CAMEL_IS_OFFLINE_FOLDER (folder));
-
- camel_folder_synchronize_sync (folder, FALSE, cancellable, error);
-}
-
-static gboolean
-offline_folder_schedule_store_changes_job (gpointer user_data)
-{
- CamelOfflineFolder *offline_folder = user_data;
- GSource *source;
-
- source = g_main_current_source ();
-
- if (g_source_is_destroyed (source))
- return FALSE;
-
- g_return_val_if_fail (CAMEL_IS_OFFLINE_FOLDER (offline_folder), FALSE);
-
- g_mutex_lock (&offline_folder->priv->store_changes_lock);
- if (offline_folder->priv->store_changes_id == g_source_get_id (source)) {
- CamelSession *session;
- CamelStore *parent_store;
-
- offline_folder->priv->store_changes_id = 0;
-
- parent_store = camel_folder_get_parent_store (CAMEL_FOLDER (offline_folder));
- session = parent_store ? camel_service_ref_session (CAMEL_SERVICE (parent_store)) : NULL;
- if (session) {
- gchar *description;
-
- /* Translators: The first “%s” is replaced with an account name and the second “%s”
- is replaced with a full path name. The spaces around “:” are intentional, as
- the whole “%s : %s” is meant as an absolute identification of the folder. */
- description = g_strdup_printf (_("Storing changes in folder “%s : %s”"),
- camel_service_get_display_name (CAMEL_SERVICE (parent_store)),
- camel_folder_get_full_name (CAMEL_FOLDER (offline_folder)));
-
- camel_session_submit_job (session, description,
- offline_folder_store_changes_job_cb,
- g_object_ref (offline_folder), g_object_unref);
-
- g_free (description);
- }
-
- g_clear_object (&session);
- }
- g_mutex_unlock (&offline_folder->priv->store_changes_lock);
-
- return FALSE;
-}
-
-static void
-offline_folder_maybe_schedule_folder_change_store (CamelOfflineFolder *offline_folder)
-{
- CamelSession *session;
- CamelStore *store;
-
- g_return_if_fail (CAMEL_IS_OFFLINE_FOLDER (offline_folder));
-
- g_mutex_lock (&offline_folder->priv->store_changes_lock);
-
- if (offline_folder->priv->store_changes_id)
- g_source_remove (offline_folder->priv->store_changes_id);
- offline_folder->priv->store_changes_id = 0;
- offline_folder->priv->store_changes_after_frozen = FALSE;
-
- if (camel_folder_is_frozen (CAMEL_FOLDER (offline_folder))) {
- offline_folder->priv->store_changes_after_frozen = TRUE;
- g_mutex_unlock (&offline_folder->priv->store_changes_lock);
-
- return;
- }
-
- store = camel_folder_get_parent_store (CAMEL_FOLDER (offline_folder));
- session = store ? camel_service_ref_session (CAMEL_SERVICE (store)) : NULL;
-
- if (session && camel_session_get_online (session) && CAMEL_IS_OFFLINE_STORE (store) &&
- camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store))) {
- CamelSettings *settings;
- gint interval = -1;
-
- settings = camel_service_ref_settings (CAMEL_SERVICE (store));
- if (settings && CAMEL_IS_OFFLINE_SETTINGS (settings))
- interval = camel_offline_settings_get_store_changes_interval (CAMEL_OFFLINE_SETTINGS (settings));
- g_clear_object (&settings);
-
- if (interval == 0)
- offline_folder_schedule_store_changes_job (offline_folder);
- else if (interval > 0)
- offline_folder->priv->store_changes_id = g_timeout_add_seconds (interval,
- offline_folder_schedule_store_changes_job, offline_folder);
- }
-
- g_clear_object (&session);
-
- g_mutex_unlock (&offline_folder->priv->store_changes_lock);
-}
-
-static void
offline_folder_changed (CamelFolder *folder,
CamelFolderChangeInfo *changes)
{
@@ -380,9 +270,6 @@ offline_folder_changed (CamelFolder *folder,
}
g_object_unref (session);
-
- if (changes && changes->uid_changed && changes->uid_changed->len > 0)
- offline_folder_maybe_schedule_folder_change_store (CAMEL_OFFLINE_FOLDER (folder));
}
static void
@@ -420,26 +307,10 @@ offline_folder_get_property (GObject *object,
}
static void
-offline_folder_dispose (GObject *object)
-{
- CamelOfflineFolder *offline_folder = CAMEL_OFFLINE_FOLDER (object);
-
- g_mutex_lock (&offline_folder->priv->store_changes_lock);
- if (offline_folder->priv->store_changes_id)
- g_source_remove (offline_folder->priv->store_changes_id);
- offline_folder->priv->store_changes_id = 0;
- g_mutex_unlock (&offline_folder->priv->store_changes_lock);
-
- /* Chain up to parent's method. */
- G_OBJECT_CLASS (camel_offline_folder_parent_class)->dispose (object);
-}
-
-static void
offline_folder_finalize (GObject *object)
{
CamelOfflineFolder *offline_folder = CAMEL_OFFLINE_FOLDER (object);
- g_mutex_clear (&offline_folder->priv->store_changes_lock);
g_mutex_clear (&offline_folder->priv->ongoing_downloads_lock);
g_hash_table_destroy (offline_folder->priv->ongoing_downloads);
@@ -448,31 +319,6 @@ offline_folder_finalize (GObject *object)
G_OBJECT_CLASS (camel_offline_folder_parent_class)->finalize (object);
}
-static void
-offline_folder_thaw (CamelFolder *folder)
-{
- /* Chain up to parent's method. */
- CAMEL_FOLDER_CLASS (camel_offline_folder_parent_class)->thaw (folder);
-
- if (!camel_folder_is_frozen (folder)) {
- CamelOfflineFolder *offline_folder;
-
- g_return_if_fail (CAMEL_IS_OFFLINE_FOLDER (folder));
-
- offline_folder = CAMEL_OFFLINE_FOLDER (folder);
-
- g_mutex_lock (&offline_folder->priv->store_changes_lock);
- if (offline_folder->priv->store_changes_after_frozen) {
- offline_folder->priv->store_changes_after_frozen = FALSE;
- g_mutex_unlock (&offline_folder->priv->store_changes_lock);
-
- offline_folder_maybe_schedule_folder_change_store (offline_folder);
- } else {
- g_mutex_unlock (&offline_folder->priv->store_changes_lock);
- }
- }
-}
-
static gboolean
offline_folder_downsync_sync (CamelOfflineFolder *offline,
const gchar *expression,
@@ -621,17 +467,12 @@ static void
camel_offline_folder_class_init (CamelOfflineFolderClass *class)
{
GObjectClass *object_class;
- CamelFolderClass *folder_class;
object_class = G_OBJECT_CLASS (class);
object_class->set_property = offline_folder_set_property;
object_class->get_property = offline_folder_get_property;
- object_class->dispose = offline_folder_dispose;
object_class->finalize = offline_folder_finalize;
- folder_class = CAMEL_FOLDER_CLASS (class);
- folder_class->thaw = offline_folder_thaw;
-
class->downsync_sync = offline_folder_downsync_sync;
g_object_class_install_property (
@@ -653,9 +494,7 @@ camel_offline_folder_init (CamelOfflineFolder *folder)
{
folder->priv = camel_offline_folder_get_instance_private (folder);
- g_mutex_init (&folder->priv->store_changes_lock);
g_mutex_init (&folder->priv->ongoing_downloads_lock);
- folder->priv->store_changes_after_frozen = FALSE;
folder->priv->offline_sync = CAMEL_THREE_STATE_INCONSISTENT;
folder->priv->ongoing_downloads = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) camel_pstring_free, NULL);
diff --git a/src/camel/camel-offline-settings.c b/src/camel/camel-offline-settings.c
index ab41ffcb2..b78dd6d42 100644
--- a/src/camel/camel-offline-settings.c
+++ b/src/camel/camel-offline-settings.c
@@ -24,7 +24,6 @@
struct _CamelOfflineSettingsPrivate {
gboolean stay_synchronized;
- gint store_changes_interval;
gboolean limit_by_age;
CamelTimeUnit limit_unit;
gint limit_value;
@@ -33,7 +32,6 @@ struct _CamelOfflineSettingsPrivate {
enum {
PROP_0,
PROP_STAY_SYNCHRONIZED,
- PROP_STORE_CHANGES_INTERVAL,
PROP_LIMIT_BY_AGE,
PROP_LIMIT_UNIT,
PROP_LIMIT_VALUE
@@ -57,12 +55,6 @@ offline_settings_set_property (GObject *object,
g_value_get_boolean (value));
return;
- case PROP_STORE_CHANGES_INTERVAL:
- camel_offline_settings_set_store_changes_interval (
- CAMEL_OFFLINE_SETTINGS (object),
- g_value_get_int (value));
- return;
-
case PROP_LIMIT_BY_AGE:
camel_offline_settings_set_limit_by_age (
CAMEL_OFFLINE_SETTINGS (object),
@@ -99,13 +91,6 @@ offline_settings_get_property (GObject *object,
CAMEL_OFFLINE_SETTINGS (object)));
return;
- case PROP_STORE_CHANGES_INTERVAL:
- g_value_set_int (
- value,
- camel_offline_settings_get_store_changes_interval (
- CAMEL_OFFLINE_SETTINGS (object)));
- return;
-
case PROP_LIMIT_BY_AGE:
g_value_set_boolean (
value,
@@ -155,21 +140,6 @@ camel_offline_settings_class_init (CamelOfflineSettingsClass *class)
g_object_class_install_property (
object_class,
- PROP_STORE_CHANGES_INTERVAL,
- g_param_spec_int (
- "store-changes-interval",
- "Store Changes Interval",
- "Interval, in seconds, to store folder changes",
- G_MININT,
- G_MAXINT,
- 3,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_EXPLICIT_NOTIFY |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (
- object_class,
PROP_LIMIT_BY_AGE,
g_param_spec_boolean (
"limit-by-age",
@@ -261,6 +231,7 @@ camel_offline_settings_set_stay_synchronized (CamelOfflineSettings *settings,
g_object_notify (G_OBJECT (settings), "stay-synchronized");
}
+
/**
* camel_offline_settings_get_store_changes_interval:
* @settings: a #CamelOfflineSettings
@@ -273,13 +244,12 @@ camel_offline_settings_set_stay_synchronized (CamelOfflineSettings *settings,
*
* Since: 3.18
**/
-
gint
camel_offline_settings_get_store_changes_interval (CamelOfflineSettings *settings)
{
g_return_val_if_fail (CAMEL_IS_OFFLINE_SETTINGS (settings), -1);
- return settings->priv->store_changes_interval;
+ return camel_store_settings_get_store_changes_interval (CAMEL_STORE_SETTINGS (settings));
}
/**
@@ -299,12 +269,7 @@ camel_offline_settings_set_store_changes_interval (CamelOfflineSettings *setting
{
g_return_if_fail (CAMEL_IS_OFFLINE_SETTINGS (settings));
- if (settings->priv->store_changes_interval == interval)
- return;
-
- settings->priv->store_changes_interval = interval;
-
- g_object_notify (G_OBJECT (settings), "store-changes-interval");
+ camel_store_settings_set_store_changes_interval (CAMEL_STORE_SETTINGS (settings), interval);
}
/**
diff --git a/src/camel/camel-offline-store.c b/src/camel/camel-offline-store.c
index d58c3e2de..981a4d12e 100644
--- a/src/camel/camel-offline-store.c
+++ b/src/camel/camel-offline-store.c
@@ -110,6 +110,24 @@ offline_store_downsync_folders_thread (CamelSession *session,
offline_store_downsync_folders_sync (store, cancellable, error);
}
+static gboolean
+offline_store_get_can_auto_save_changes (CamelStore *store)
+{
+ CamelSession *session;
+ gboolean res;
+
+ g_return_val_if_fail (CAMEL_IS_OFFLINE_STORE (store), FALSE);
+
+ session = camel_service_ref_session (CAMEL_SERVICE (store));
+
+ res = session && camel_session_get_online (session) &&
+ camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store));
+
+ g_clear_object (&session);
+
+ return res;
+}
+
static void
offline_store_constructed (GObject *object)
{
@@ -164,6 +182,7 @@ camel_offline_store_class_init (CamelOfflineStoreClass *class)
{
GObjectClass *object_class;
CamelServiceClass *service_class;
+ CamelStoreClass *store_class;
object_class = G_OBJECT_CLASS (class);
object_class->constructed = offline_store_constructed;
@@ -173,6 +192,9 @@ camel_offline_store_class_init (CamelOfflineStoreClass *class)
service_class = CAMEL_SERVICE_CLASS (class);
service_class->settings_type = CAMEL_TYPE_OFFLINE_SETTINGS;
+ store_class = CAMEL_STORE_CLASS (class);
+ store_class->get_can_auto_save_changes = offline_store_get_can_auto_save_changes;
+
g_object_class_install_property (
object_class,
PROP_ONLINE,
diff --git a/src/camel/camel-store-settings.c b/src/camel/camel-store-settings.c
index 1dc49d7ec..ce7d30965 100644
--- a/src/camel/camel-store-settings.c
+++ b/src/camel/camel-store-settings.c
@@ -19,11 +19,13 @@
struct _CamelStoreSettingsPrivate {
gboolean filter_inbox;
+ gint store_changes_interval;
};
enum {
PROP_0,
- PROP_FILTER_INBOX
+ PROP_FILTER_INBOX,
+ PROP_STORE_CHANGES_INTERVAL
};
G_DEFINE_TYPE_WITH_PRIVATE (
@@ -43,6 +45,12 @@ store_settings_set_property (GObject *object,
CAMEL_STORE_SETTINGS (object),
g_value_get_boolean (value));
return;
+
+ case PROP_STORE_CHANGES_INTERVAL:
+ camel_store_settings_set_store_changes_interval (
+ CAMEL_STORE_SETTINGS (object),
+ g_value_get_int (value));
+ return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -61,6 +69,13 @@ store_settings_get_property (GObject *object,
camel_store_settings_get_filter_inbox (
CAMEL_STORE_SETTINGS (object)));
return;
+
+ case PROP_STORE_CHANGES_INTERVAL:
+ g_value_set_int (
+ value,
+ camel_store_settings_get_store_changes_interval (
+ CAMEL_STORE_SETTINGS (object)));
+ return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -87,6 +102,21 @@ camel_store_settings_class_init (CamelStoreSettingsClass *class)
G_PARAM_CONSTRUCT |
G_PARAM_EXPLICIT_NOTIFY |
G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_STORE_CHANGES_INTERVAL,
+ g_param_spec_int (
+ "store-changes-interval",
+ "Store Changes Interval",
+ "Interval, in seconds, to store folder changes",
+ G_MININT,
+ G_MAXINT,
+ 3,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_EXPLICIT_NOTIFY |
+ G_PARAM_STATIC_STRINGS));
}
static void
@@ -137,3 +167,48 @@ camel_store_settings_set_filter_inbox (CamelStoreSettings *settings,
g_object_notify (G_OBJECT (settings), "filter-inbox");
}
+
+/**
+ * camel_store_settings_get_store_changes_interval:
+ * @settings: a #CamelStoreSettings
+ *
+ * Returns the interval, in seconds, for the changes in the folder being
+ * saved automatically. 0 means immediately, while -1 means turning off
+ * automatic folder change saving.
+ *
+ * Returns: the interval for automatic store of folder changes
+ *
+ * Since: 3.38.2
+ **/
+gint
+camel_store_settings_get_store_changes_interval (CamelStoreSettings *settings)
+{
+ g_return_val_if_fail (CAMEL_IS_STORE_SETTINGS (settings), -1);
+
+ return settings->priv->store_changes_interval;
+}
+
+/**
+ * camel_store_settings_set_store_changes_interval:
+ * @settings: a #CamelStoreSettings
+ * @interval: the interval, in seconds
+ *
+ * Sets the interval, in seconds, for the changes in the folder being
+ * saved automatically. 0 means immediately, while -1 means turning off
+ * automatic folder change saving.
+ *
+ * Since: 3.38.2
+ **/
+void
+camel_store_settings_set_store_changes_interval (CamelStoreSettings *settings,
+ gint interval)
+{
+ g_return_if_fail (CAMEL_IS_STORE_SETTINGS (settings));
+
+ if (settings->priv->store_changes_interval == interval)
+ return;
+
+ settings->priv->store_changes_interval = interval;
+
+ g_object_notify (G_OBJECT (settings), "store-changes-interval");
+}
diff --git a/src/camel/camel-store-settings.h b/src/camel/camel-store-settings.h
index 010fa8692..fe9ec164a 100644
--- a/src/camel/camel-store-settings.h
+++ b/src/camel/camel-store-settings.h
@@ -76,6 +76,11 @@ gboolean camel_store_settings_get_filter_inbox
void camel_store_settings_set_filter_inbox
(CamelStoreSettings *settings,
gboolean filter_inbox);
+gint camel_store_settings_get_store_changes_interval
+ (CamelStoreSettings *settings);
+void camel_store_settings_set_store_changes_interval
+ (CamelStoreSettings *settings,
+ gint interval);
G_END_DECLS
diff --git a/src/camel/camel-store.c b/src/camel/camel-store.c
index 5c0ecfc21..11f032cc9 100644
--- a/src/camel/camel-store.c
+++ b/src/camel/camel-store.c
@@ -563,6 +563,12 @@ store_initable_init (GInitable *initable,
return TRUE;
}
+static gboolean
+store_get_can_auto_save_changes (CamelStore *store)
+{
+ return TRUE;
+}
+
static void
camel_store_class_init (CamelStoreClass *class)
{
@@ -586,6 +592,7 @@ camel_store_class_init (CamelStoreClass *class)
class->get_trash_folder_sync = store_get_trash_folder_sync;
class->synchronize_sync = store_synchronize_sync;
class->initial_setup_sync = store_initial_setup_sync;
+ class->get_can_auto_save_changes = store_get_can_auto_save_changes;
signals[FOLDER_CREATED] = g_signal_new (
"folder-created",
@@ -3333,3 +3340,27 @@ camel_store_delete_cached_folder (CamelStore *store,
camel_object_bag_remove (store->priv->folders, folder);
g_object_unref (folder);
}
+
+/**
+ * camel_store_get_can_auto_save_changes:
+ * @store: a #CamelStore
+ *
+ * Returns whether there can be done automatic save of folder changes.
+ * Default is TRUE. The descendants can overwrite it with CamelStoreClass::get_can_auto_save_changes().
+ *
+ * Return: Whether there can be done automatic save of folder changes.
+ *
+ * Since: 3.38.2
+ **/
+gboolean
+camel_store_get_can_auto_save_changes (CamelStore *store)
+{
+ CamelStoreClass *klass;
+
+ g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+
+ klass = CAMEL_STORE_GET_CLASS (store);
+ g_return_val_if_fail (klass != NULL, FALSE);
+
+ return klass->get_can_auto_save_changes && klass->get_can_auto_save_changes (store);
+}
diff --git a/src/camel/camel-store.h b/src/camel/camel-store.h
index 45c309ebf..76e2b791b 100644
--- a/src/camel/camel-store.h
+++ b/src/camel/camel-store.h
@@ -206,9 +206,11 @@ struct _CamelStoreClass {
GHashTable *out_save_setup,
GCancellable *cancellable,
GError **error);
+ gboolean (*get_can_auto_save_changes)
+ (CamelStore *store);
/* Padding for future expansion */
- gpointer reserved_methods[20];
+ gpointer reserved_methods[19];
/* Signals */
void (*folder_created) (CamelStore *store,
@@ -416,6 +418,8 @@ gboolean camel_store_maybe_run_db_maintenance
void camel_store_delete_cached_folder
(CamelStore *store,
const gchar *folder_name);
+gboolean camel_store_get_can_auto_save_changes
+ (CamelStore *store);
G_END_DECLS
diff --git a/src/camel/camel-vee-store.c b/src/camel/camel-vee-store.c
index a8414b210..09bac5e4e 100644
--- a/src/camel/camel-vee-store.c
+++ b/src/camel/camel-vee-store.c
@@ -514,6 +514,13 @@ vee_store_rename_folder_sync (CamelStore *store,
return TRUE;
}
+static gboolean
+vee_store_get_can_auto_save_changes (CamelStore *store)
+{
+ /* Let only the real folder auto-save the changes */
+ return FALSE;
+}
+
static void
camel_vee_store_class_init (CamelVeeStoreClass *class)
{
@@ -538,6 +545,7 @@ camel_vee_store_class_init (CamelVeeStoreClass *class)
store_class->get_trash_folder_sync = vee_store_get_trash_folder_sync;
store_class->delete_folder_sync = vee_store_delete_folder_sync;
store_class->rename_folder_sync = vee_store_rename_folder_sync;
+ store_class->get_can_auto_save_changes = vee_store_get_can_auto_save_changes;
g_object_class_install_property (
object_class,