[evolution-data-server] Bug 773419 - Age limit for offline message download
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug 773419 - Age limit for offline message download
- Date: Mon, 12 Dec 2016 21:22:59 +0000 (UTC)
commit e62b124811cb6c0c169f771773e4a0d2ef06f95e
Author: Milan Crha <mcrha redhat com>
Date: Mon Dec 12 22:22:10 2016 +0100
Bug 773419 - Age limit for offline message download
src/camel/camel-enums.h | 22 ++-
src/camel/camel-offline-folder.c | 93 +++++++++-
src/camel/camel-offline-settings.c | 213 +++++++++++++++++++++-
src/camel/camel-offline-settings.h | 16 ++
src/camel/camel-utils.c | 71 +++++++
src/camel/camel-utils.h | 6 +
src/camel/providers/imapx/camel-imapx-provider.c | 1 +
7 files changed, 411 insertions(+), 11 deletions(-)
---
diff --git a/src/camel/camel-enums.h b/src/camel/camel-enums.h
index 3e3bb9a..2900971 100644
--- a/src/camel/camel-enums.h
+++ b/src/camel/camel-enums.h
@@ -336,7 +336,8 @@ typedef enum {
CAMEL_PROVIDER_CONF_ENTRY,
CAMEL_PROVIDER_CONF_LABEL,
CAMEL_PROVIDER_CONF_HIDDEN,
- CAMEL_PROVIDER_CONF_OPTIONS
+ CAMEL_PROVIDER_CONF_OPTIONS,
+ CAMEL_PROVIDER_CONF_PLACEHOLDER
} CamelProviderConfType;
/**
@@ -531,4 +532,23 @@ typedef enum {
CAMEL_COMPARE_CASE_SENSITIVE
} CamelCompareType;
+/**
+ * CamelTimeUnit:
+ * @CAMEL_TIME_UNIT_DAYS: days
+ * @CAMEL_TIME_UNIT_WEEKS: weeks
+ * @CAMEL_TIME_UNIT_MONTHS: months
+ * @CAMEL_TIME_UNIT_YEARS: years
+ *
+ * Declares time unit, which serves to interpret the time value,
+ * like in #CamelOfflineSettings.
+ *
+ * Since: 3.24
+ **/
+typedef enum {
+ CAMEL_TIME_UNIT_DAYS = 1,
+ CAMEL_TIME_UNIT_WEEKS,
+ CAMEL_TIME_UNIT_MONTHS,
+ CAMEL_TIME_UNIT_YEARS
+} CamelTimeUnit;
+
#endif /* CAMEL_ENUMS_H */
diff --git a/src/camel/camel-offline-folder.c b/src/camel/camel-offline-folder.c
index 8edac3b..a29557f 100644
--- a/src/camel/camel-offline-folder.c
+++ b/src/camel/camel-offline-folder.c
@@ -28,6 +28,7 @@
#include "camel-offline-store.h"
#include "camel-operation.h"
#include "camel-session.h"
+#include "camel-utils.h"
#define CAMEL_OFFLINE_FOLDER_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -81,12 +82,42 @@ offline_downsync_data_free (OfflineDownsyncData *data)
g_slice_free (OfflineDownsyncData, data);
}
+/* Returns 0, if not set any limit */
+static gint64
+offline_folder_get_limit_time (CamelFolder *folder)
+{
+ CamelStore *parent_store;
+ CamelSettings *settings;
+ gint64 limit_time = 0;
+
+ g_return_val_if_fail (CAMEL_IS_FOLDER (folder), -1);
+
+ parent_store = camel_folder_get_parent_store (folder);
+ if (!parent_store)
+ return limit_time;
+
+ settings = camel_service_ref_settings (CAMEL_SERVICE (parent_store));
+
+ if (CAMEL_IS_OFFLINE_SETTINGS (settings) &&
+ camel_offline_settings_get_limit_by_age (CAMEL_OFFLINE_SETTINGS (settings))) {
+ limit_time = camel_time_value_apply (-1,
+ camel_offline_settings_get_limit_unit (CAMEL_OFFLINE_SETTINGS (settings)),
+ -camel_offline_settings_get_limit_value (CAMEL_OFFLINE_SETTINGS (settings)));
+ }
+
+ g_clear_object (&settings);
+
+ return limit_time;
+}
+
static void
offline_folder_downsync_background (CamelSession *session,
GCancellable *cancellable,
OfflineDownsyncData *data,
GError **error)
{
+ gint64 limit_time;
+
camel_operation_push_message (
/* 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
@@ -95,6 +126,8 @@ offline_folder_downsync_background (CamelSession *session,
camel_service_get_display_name (CAMEL_SERVICE (camel_folder_get_parent_store (data->folder))),
camel_folder_get_full_name (data->folder));
+ limit_time = offline_folder_get_limit_time (data->folder);
+
if (data->changes) {
GPtrArray *uid_added;
gboolean success = TRUE;
@@ -111,13 +144,36 @@ offline_folder_downsync_background (CamelSession *session,
camel_operation_progress (cancellable, percent);
+ if (limit_time > 0) {
+ CamelMessageInfo *mi;
+ gboolean download;
+
+ mi = camel_folder_get_message_info (data->folder, uid);
+ if (!mi)
+ continue;
+
+ download = camel_message_info_get_date_sent (mi) > limit_time;
+
+ g_clear_object (&mi);
+
+ if (!download)
+ continue;
+ }
+
success = camel_folder_synchronize_message_sync (
data->folder, uid, cancellable, error);
}
} else {
+ gchar *expression = NULL;
+
+ if (limit_time > 0)
+ expression = g_strdup_printf ("(match-all (> (get-sent-date) %" G_GINT64_FORMAT ")",
limit_time);
+
camel_offline_folder_downsync_sync (
CAMEL_OFFLINE_FOLDER (data->folder),
- "(match-all)", cancellable, error);
+ expression ? expression : "(match-all)", cancellable, error);
+
+ g_free (expression);
}
camel_operation_pop_message (cancellable);
@@ -363,6 +419,7 @@ offline_folder_downsync_sync (CamelOfflineFolder *offline,
{
CamelFolder *folder = (CamelFolder *) offline;
GPtrArray *uids, *uncached_uids = NULL;
+ gint64 limit_time;
gint i;
/* Translators: The first “%s” is replaced with an account name and the second “%s”
@@ -390,14 +447,36 @@ offline_folder_downsync_sync (CamelOfflineFolder *offline,
if (!uncached_uids)
goto done;
- for (i = 0; i < uncached_uids->len; i++) {
- camel_folder_synchronize_message_sync (
- folder, uncached_uids->pdata[i], cancellable, NULL);
- camel_operation_progress (
- cancellable, i * 100 / uncached_uids->len);
+ limit_time = offline_folder_get_limit_time (folder);
+ if (limit_time > 0 && camel_folder_get_folder_summary (folder))
+ camel_folder_summary_prepare_fetch_all (camel_folder_get_folder_summary (folder), NULL);
+
+ for (i = 0; i < uncached_uids->len && !g_cancellable_is_cancelled (cancellable); i++) {
+ const gchar *uid = uncached_uids->pdata[i];
+ gboolean download = limit_time <= 0;
+
+ if (limit_time > 0) {
+ CamelMessageInfo *mi;
+
+ mi = camel_folder_get_message_info (folder, uid);
+ if (!mi)
+ continue;
+
+ download = camel_message_info_get_date_sent (mi) > limit_time;
+
+ g_clear_object (&mi);
+ }
+
+ if (download) {
+ /* Stop on failure */
+ if (!camel_folder_synchronize_message_sync (folder, uid, cancellable, NULL))
+ break;
+ }
+
+ camel_operation_progress (cancellable, i * 100 / uncached_uids->len);
}
-done:
+ done:
if (uncached_uids)
camel_folder_free_uids (folder, uncached_uids);
diff --git a/src/camel/camel-offline-settings.c b/src/camel/camel-offline-settings.c
index 8b4aa6e..04dab33 100644
--- a/src/camel/camel-offline-settings.c
+++ b/src/camel/camel-offline-settings.c
@@ -15,9 +15,12 @@
*
*/
-#include "camel-offline-settings.h"
+#include "evolution-data-server-config.h"
+
+#include "camel-store-settings.h"
+#include "camel-enumtypes.h"
-#include <camel/camel-store-settings.h>
+#include "camel-offline-settings.h"
#define CAMEL_OFFLINE_SETTINGS_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -26,12 +29,18 @@
struct _CamelOfflineSettingsPrivate {
gboolean stay_synchronized;
gint store_changes_interval;
+ gboolean limit_by_age;
+ CamelTimeUnit limit_unit;
+ gint limit_value;
};
enum {
PROP_0,
PROP_STAY_SYNCHRONIZED,
- PROP_STORE_CHANGES_INTERVAL
+ PROP_STORE_CHANGES_INTERVAL,
+ PROP_LIMIT_BY_AGE,
+ PROP_LIMIT_UNIT,
+ PROP_LIMIT_VALUE
};
G_DEFINE_TYPE (
@@ -57,6 +66,24 @@ offline_settings_set_property (GObject *object,
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),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_LIMIT_UNIT:
+ camel_offline_settings_set_limit_unit (
+ CAMEL_OFFLINE_SETTINGS (object),
+ g_value_get_enum (value));
+ return;
+
+ case PROP_LIMIT_VALUE:
+ camel_offline_settings_set_limit_value (
+ CAMEL_OFFLINE_SETTINGS (object),
+ g_value_get_int (value));
+ return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -82,6 +109,27 @@ offline_settings_get_property (GObject *object,
camel_offline_settings_get_store_changes_interval (
CAMEL_OFFLINE_SETTINGS (object)));
return;
+
+ case PROP_LIMIT_BY_AGE:
+ g_value_set_boolean (
+ value,
+ camel_offline_settings_get_limit_by_age (
+ CAMEL_OFFLINE_SETTINGS (object)));
+ return;
+
+ case PROP_LIMIT_UNIT:
+ g_value_set_enum (
+ value,
+ camel_offline_settings_get_limit_unit (
+ CAMEL_OFFLINE_SETTINGS (object)));
+ return;
+
+ case PROP_LIMIT_VALUE:
+ g_value_set_int (
+ value,
+ camel_offline_settings_get_limit_value (
+ CAMEL_OFFLINE_SETTINGS (object)));
+ return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -123,6 +171,45 @@ camel_offline_settings_class_init (CamelOfflineSettingsClass *class)
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_LIMIT_BY_AGE,
+ g_param_spec_boolean (
+ "limit-by-age",
+ "Limit By Age",
+ "Whether to limit what will be synchronized by message date",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_LIMIT_UNIT,
+ g_param_spec_enum (
+ "limit-unit",
+ "Limit Unit",
+ "A unit for the limit-value",
+ CAMEL_TYPE_TIME_UNIT,
+ CAMEL_TIME_UNIT_YEARS,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_LIMIT_VALUE,
+ g_param_spec_int (
+ "limit-value",
+ "Limit Value",
+ "How many days/weeks/months/years to download into the local cache, if limit-by-age
is set to TRUE",
+ 1,
+ G_MAXINT,
+ 1,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
}
static void
@@ -220,3 +307,123 @@ camel_offline_settings_set_store_changes_interval (CamelOfflineSettings *setting
g_object_notify (G_OBJECT (settings), "store-changes-interval");
}
+
+/**
+ * camel_offline_settings_get_limit_by_age:
+ * @settings: a #CamelOfflineSettings
+ *
+ * Returns: whether limit messages stored for offline use by their age
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_offline_settings_get_limit_by_age (CamelOfflineSettings *settings)
+{
+ g_return_val_if_fail (CAMEL_IS_OFFLINE_SETTINGS (settings), FALSE);
+
+ return settings->priv->limit_by_age;
+}
+
+/**
+ * camel_offline_settings_set_limit_by_age:
+ * @settings: a #CamelOfflineSettings
+ * @limit_by_age: a value to set
+ *
+ * Set whether the messages to download for offline should be limited
+ * by age. If set to %TRUE, then messages older than 'limit-value'
+ * will not be downloaded automatically.
+ *
+ * Since: 3.24
+ **/
+void
+camel_offline_settings_set_limit_by_age (CamelOfflineSettings *settings,
+ gboolean limit_by_age)
+{
+ g_return_if_fail (CAMEL_IS_OFFLINE_SETTINGS (settings));
+
+ if ((!settings->priv->limit_by_age) == (!limit_by_age))
+ return;
+
+ settings->priv->limit_by_age = limit_by_age;
+
+ g_object_notify (G_OBJECT (settings), "limit-by-age");
+}
+
+/**
+ * camel_offline_settings_get_limit_unit:
+ * @settings: a #CamelOfflineSettings
+ *
+ * Returns: the limit unit to use when interpreting 'limit-value'
+ *
+ * Since: 3.24
+ **/
+CamelTimeUnit
+camel_offline_settings_get_limit_unit (CamelOfflineSettings *settings)
+{
+ g_return_val_if_fail (CAMEL_IS_OFFLINE_SETTINGS (settings), CAMEL_TIME_UNIT_YEARS);
+
+ return settings->priv->limit_unit;
+}
+
+/**
+ * camel_offline_settings_set_limit_unit:
+ * @settings: a #CamelOfflineSettings
+ * @limit_unit: a #CamelTimeUnit with a unit to use
+ *
+ * Set the limit unit to use when interpreting 'limit-value'.
+ *
+ * Since: 3.24
+ **/
+void
+camel_offline_settings_set_limit_unit (CamelOfflineSettings *settings,
+ CamelTimeUnit limit_unit)
+{
+ g_return_if_fail (CAMEL_IS_OFFLINE_SETTINGS (settings));
+ g_return_if_fail (limit_unit >= CAMEL_TIME_UNIT_DAYS && limit_unit <= CAMEL_TIME_UNIT_YEARS);
+
+ if (settings->priv->limit_unit == limit_unit)
+ return;
+
+ settings->priv->limit_unit = limit_unit;
+
+ g_object_notify (G_OBJECT (settings), "limit-unit");
+}
+
+/**
+ * camel_offline_settings_get_limit_value:
+ * @settings: a #CamelOfflineSettings
+ *
+ * Returns: the limit, in 'limit-unit', to use when 'limit-by-age' is set to %TRUE
+ *
+ * Since: 3.24
+ **/
+gint
+camel_offline_settings_get_limit_value (CamelOfflineSettings *settings)
+{
+ g_return_val_if_fail (CAMEL_IS_OFFLINE_SETTINGS (settings), -1);
+
+ return settings->priv->limit_value;
+}
+
+/**
+ * camel_offline_settings_set_limit_value:
+ * @settings: a #CamelOfflineSettings
+ * @limit_value: a value to set
+ *
+ * Set the limit, in 'limit-unit', to use when 'limit-by-age' is set to %TRUE.
+ *
+ * Since: 3.24
+ **/
+void
+camel_offline_settings_set_limit_value (CamelOfflineSettings *settings,
+ gboolean limit_value)
+{
+ g_return_if_fail (CAMEL_IS_OFFLINE_SETTINGS (settings));
+
+ if (settings->priv->limit_value == limit_value)
+ return;
+
+ settings->priv->limit_value = limit_value;
+
+ g_object_notify (G_OBJECT (settings), "limit-value");
+}
diff --git a/src/camel/camel-offline-settings.h b/src/camel/camel-offline-settings.h
index 63452a0..41e84df 100644
--- a/src/camel/camel-offline-settings.h
+++ b/src/camel/camel-offline-settings.h
@@ -22,6 +22,7 @@
#ifndef CAMEL_OFFLINE_SETTINGS_H
#define CAMEL_OFFLINE_SETTINGS_H
+#include <camel/camel-enums.h>
#include <camel/camel-store-settings.h>
/* Standard GObject macros */
@@ -82,6 +83,21 @@ gint camel_offline_settings_get_store_changes_interval
void camel_offline_settings_set_store_changes_interval
(CamelOfflineSettings *settings,
gint interval);
+gboolean camel_offline_settings_get_limit_by_age
+ (CamelOfflineSettings *settings);
+void camel_offline_settings_set_limit_by_age
+ (CamelOfflineSettings *settings,
+ gboolean limit_by_age);
+CamelTimeUnit camel_offline_settings_get_limit_unit
+ (CamelOfflineSettings *settings);
+void camel_offline_settings_set_limit_unit
+ (CamelOfflineSettings *settings,
+ CamelTimeUnit limit_unit);
+gint camel_offline_settings_get_limit_value
+ (CamelOfflineSettings *settings);
+void camel_offline_settings_set_limit_value
+ (CamelOfflineSettings *settings,
+ gboolean limit_value);
G_END_DECLS
diff --git a/src/camel/camel-utils.c b/src/camel/camel-utils.c
index b7a0f5d..b38b9a9 100644
--- a/src/camel/camel-utils.c
+++ b/src/camel/camel-utils.c
@@ -171,3 +171,74 @@ camel_util_bdata_put_string (GString *bdata_str,
g_string_append_printf (bdata_str, "-%s", value);
}
+
+/**
+ * camel_time_value_apply:
+ * @src_time: a time_t to apply the value to, or -1 to use the current time
+ * @unit: a #CamelTimeUnit
+ * @value: a value to apply
+ *
+ * Applies the given time @value in unit @unit to the @src_time.
+ * Use negative value to subtract it. The time part is rounded
+ * to the beginning of the day.
+ *
+ * Returns: @src_time modified by the given parameters as date, with
+ * the time part being beginning of the day.
+ *
+ * Since: 3.24
+ **/
+time_t
+camel_time_value_apply (time_t src_time,
+ CamelTimeUnit unit,
+ gint value)
+{
+ GDate dt;
+ struct tm tm;
+
+ g_return_val_if_fail (unit >= CAMEL_TIME_UNIT_DAYS && unit <= CAMEL_TIME_UNIT_YEARS, src_time);
+
+ if (src_time == (time_t) -1)
+ src_time = time (NULL);
+
+ if (!value)
+ return src_time;
+
+ g_date_clear (&dt, 1);
+
+ g_date_set_time_t (&dt, src_time);
+
+ switch (unit) {
+ case CAMEL_TIME_UNIT_DAYS:
+ if (value > 0)
+ g_date_add_days (&dt, value);
+ else
+ g_date_subtract_days (&dt, (-1) * value);
+ break;
+ case CAMEL_TIME_UNIT_WEEKS:
+ if (value > 0)
+ g_date_add_days (&dt, value * 7);
+ else
+ g_date_subtract_days (&dt, (-1) * value * 7);
+ break;
+ case CAMEL_TIME_UNIT_MONTHS:
+ if (value > 0)
+ g_date_add_months (&dt, value);
+ else
+ g_date_subtract_months (&dt, (-1) * value);
+ break;
+ case CAMEL_TIME_UNIT_YEARS:
+ if (value > 0)
+ g_date_add_years (&dt, value);
+ else
+ g_date_subtract_years (&dt, (-1) * value);
+ break;
+ }
+
+ g_date_to_struct_tm (&dt, &tm);
+
+ tm.tm_sec = 0;
+ tm.tm_min = 0;
+ tm.tm_hour = 0;
+
+ return mktime (&tm);
+}
diff --git a/src/camel/camel-utils.h b/src/camel/camel-utils.h
index 25c2864..c256057 100644
--- a/src/camel/camel-utils.h
+++ b/src/camel/camel-utils.h
@@ -23,6 +23,8 @@
#define CAMEL_UTILS_H
#include <glib-object.h>
+#include <time.h>
+#include <camel/camel-enums.h>
G_BEGIN_DECLS
@@ -35,6 +37,10 @@ gchar * camel_util_bdata_get_string (/* const */ gchar **bdata_ptr,
void camel_util_bdata_put_string (GString *bdata_str,
const gchar *value);
+time_t camel_time_value_apply (time_t src_time,
+ CamelTimeUnit unit,
+ gint value);
+
G_END_DECLS
#endif /* CAMEL_UTILS_H */
diff --git a/src/camel/providers/imapx/camel-imapx-provider.c
b/src/camel/providers/imapx/camel-imapx-provider.c
index 9036364..0b1d432 100644
--- a/src/camel/providers/imapx/camel-imapx-provider.c
+++ b/src/camel/providers/imapx/camel-imapx-provider.c
@@ -70,6 +70,7 @@ CamelProviderConfEntry imapx_conf_entries[] = {
N_("Only check for Junk messages in the In_box folder"), "0" },
{ CAMEL_PROVIDER_CONF_CHECKBOX, "stay-synchronized", NULL,
N_("Synchroni_ze remote mail locally in all folders"), "0" },
+ { CAMEL_PROVIDER_CONF_PLACEHOLDER, "imapx-limit-by-age-placeholder", NULL },
{ CAMEL_PROVIDER_CONF_SECTION_END },
{ CAMEL_PROVIDER_CONF_END }
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]