[evolution-data-server/wip/camel-more-gobject] Prototype load/save CamelMessageInfo methods
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/wip/camel-more-gobject] Prototype load/save CamelMessageInfo methods
- Date: Tue, 6 Sep 2016 13:12:25 +0000 (UTC)
commit 1b75b7415a3f90c83e5b8e6ab293a3c7008b2312
Author: Milan Crha <mcrha redhat com>
Date: Tue Sep 6 15:11:44 2016 +0200
Prototype load/save CamelMessageInfo methods
camel/camel-message-info-base.c | 36 +
camel/camel-message-info.c | 759 ++++++++++++++++++--
camel/camel-message-info.h | 42 ++-
camel/camel-vee-message-info.c | 14 +
camel/providers/imapx/camel-imapx-message-info.c | 32 +-
camel/providers/local/camel-maildir-message-info.c | 38 +-
camel/providers/local/camel-maildir-message-info.h | 3 +
camel/providers/local/camel-mbox-message-info.c | 67 ++-
8 files changed, 899 insertions(+), 92 deletions(-)
---
diff --git a/camel/camel-message-info-base.c b/camel/camel-message-info-base.c
index 9a4950f..ddeb031 100644
--- a/camel/camel-message-info-base.c
+++ b/camel/camel-message-info-base.c
@@ -129,6 +129,23 @@ message_info_base_set_user_flag (xCamelMessageInfo *mi,
return changed;
}
+static const CamelNamedFlags *
+message_info_base_get_user_flags (const xCamelMessageInfo *mi)
+{
+ xCamelMessageInfoBase *bmi;
+ const CamelNamedFlags *result;
+
+ g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO_BASE (mi), NULL);
+
+ bmi = XCAMEL_MESSAGE_INFO_BASE (mi);
+
+ xcamel_message_info_property_lock (mi);
+ result = bmi->priv->user_flags;
+ xcamel_message_info_property_unlock (mi);
+
+ return result;
+}
+
static CamelNamedFlags *
message_info_base_dup_user_flags (const xCamelMessageInfo *mi)
{
@@ -218,6 +235,23 @@ message_info_base_set_user_tag (xCamelMessageInfo *mi,
return changed;
}
+static const CamelNameValueArray *
+message_info_base_get_user_tags (const xCamelMessageInfo *mi)
+{
+ xCamelMessageInfoBase *bmi;
+ const CamelNameValueArray *result;
+
+ g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO_BASE (mi), NULL);
+
+ bmi = XCAMEL_MESSAGE_INFO_BASE (mi);
+
+ xcamel_message_info_property_lock (mi);
+ result = bmi->priv->user_tags;
+ xcamel_message_info_property_unlock (mi);
+
+ return result;
+}
+
static CamelNameValueArray *
message_info_base_dup_user_tags (const xCamelMessageInfo *mi)
{
@@ -836,10 +870,12 @@ xcamel_message_info_base_class_init (xCamelMessageInfoBaseClass *class)
mi_class->set_flags = message_info_base_set_flags;
mi_class->get_user_flag = message_info_base_get_user_flag;
mi_class->set_user_flag = message_info_base_set_user_flag;
+ mi_class->get_user_flags = message_info_base_get_user_flags;
mi_class->dup_user_flags = message_info_base_dup_user_flags;
mi_class->take_user_flags = message_info_base_take_user_flags;
mi_class->get_user_tag = message_info_base_get_user_tag;
mi_class->set_user_tag = message_info_base_set_user_tag;
+ mi_class->get_user_tags = message_info_base_get_user_tags;
mi_class->dup_user_tags = message_info_base_dup_user_tags;
mi_class->take_user_tags = message_info_base_take_user_tags;
mi_class->get_subject = message_info_base_get_subject;
diff --git a/camel/camel-message-info.c b/camel/camel-message-info.c
index bd5110d..f89d975 100644
--- a/camel/camel-message-info.c
+++ b/camel/camel-message-info.c
@@ -20,7 +20,9 @@
#endif
#include <stdio.h>
+#include <string.h>
+#include "camel-db.h"
#include "camel-folder.h"
#include "camel-folder-summary.h"
#include "camel-message-info-base.h"
@@ -34,6 +36,7 @@ struct _xCamelMessageInfoPrivate {
GWeakRef summary; /* CamelFolderSummary * */
gboolean dirty; /* whether requires save to local disk/summary */
const gchar *uid; /* allocated in the string pool */
+ gboolean loading;
};
enum {
@@ -41,6 +44,7 @@ enum {
PROP_SUMMARY,
PROP_DIRTY,
PROP_FOLDER_FLAGGED,
+ PROP_LOADING,
PROP_UID,
PROP_FLAGS,
PROP_USER_FLAGS,
@@ -80,6 +84,7 @@ message_info_clone (const xCamelMessageInfo *mi,
result = xcamel_message_info_new (assign_summary);
g_object_freeze_notify (G_OBJECT (result));
+ xcamel_message_info_set_loading (result, TRUE);
uid = xcamel_message_info_pooldup_uid (mi);
xcamel_message_info_set_uid (result, uid);
@@ -127,11 +132,216 @@ message_info_clone (const xCamelMessageInfo *mi,
/* Also ensure 'dirty' flag, thus it can be eventually saved. */
xcamel_message_info_set_dirty (result, TRUE);
+ xcamel_message_info_set_loading (result, FALSE);
g_object_thaw_notify (G_OBJECT (result));
return result;
}
+static gboolean
+message_info_load (xCamelMessageInfo *mi,
+ const CamelMIRecord *record,
+ /* const */ gchar **bdata_ptr)
+{
+ gint ii, count;
+ gchar *part, *label;
+
+ g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_ptr != NULL, FALSE);
+
+ xcamel_message_info_set_uid (mi, record->uid);
+ xcamel_message_info_set_flags (mi, ~0, record->flags);
+ xcamel_message_info_set_size (mi, record->size);
+ xcamel_message_info_set_date_sent (mi, record->dsent);
+ xcamel_message_info_set_date_received (mi, record->dreceived);
+
+ xcamel_message_info_set_subject (mi, record->subject);
+ xcamel_message_info_set_from (mi, record->from);
+ xcamel_message_info_set_to (mi, record->to);
+ xcamel_message_info_set_cc (mi, record->cc);
+ xcamel_message_info_set_mlist (mi, record->mlist);
+
+ /* Extract Message id & References */
+ part = record->part;
+ if (part) {
+ CamelSummaryMessageID message_id;
+
+ message_id.id.part.hi = camel_message_info_util_bdata_get_number (&part, 0);
+ message_id.id.part.lo = camel_message_info_util_bdata_get_number (&part, 0);
+
+ xcamel_message_info_set_message_id (mi, message_id.id.id);
+
+ count = camel_message_info_util_bdata_get_number (&part, 0);
+
+ if (count > 0) {
+ GArray *references = g_array_sized_new (FALSE, FALSE, sizeof (guint64), count);
+
+ for (ii = 0; ii < count; ii++) {
+ message_id.id.part.hi = camel_message_info_util_bdata_get_number (&part, 0);
+ message_id.id.part.lo = camel_message_info_util_bdata_get_number (&part, 0);
+
+ g_array_append_val (references, message_id.id.id);
+ }
+
+ xcamel_message_info_take_references (mi, references);
+ }
+ }
+
+ /* Extract User flags/labels */
+ part = record->labels;
+ if (part) {
+ CamelNamedFlags *user_flags;
+
+ user_flags = camel_named_flags_new ();
+
+ label = part;
+ for (ii = 0; part[ii]; ii++) {
+ if (part[ii] == ' ') {
+ part[ii] = 0;
+ if (label && *label)
+ camel_named_flags_insert (user_flags, label);
+ label = &(part[ii + 1]);
+ }
+ }
+ if (label && *label)
+ camel_named_flags_insert (user_flags, label);
+
+ xcamel_message_info_take_user_flags (mi, user_flags);
+ }
+
+ /* Extract User tags */
+ part = record->usertags;
+ if (part) {
+ CamelNameValueArray *user_tags;
+
+ count = camel_message_info_util_bdata_get_number (&part, 0);
+
+ user_tags = camel_name_value_array_new_sized (count);
+
+ for (ii = 0; ii < count; ii++) {
+ gchar *name, *value;
+
+ name = camel_message_info_util_bdata_get_string (&part, NULL);
+ value = camel_message_info_util_bdata_get_string (&part, NULL);
+
+ if (name && value)
+ camel_name_value_array_set_named (user_tags, TRUE, name, value);
+
+ g_free (name);
+ g_free (value);
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+message_info_save (const xCamelMessageInfo *mi,
+ CamelMIRecord *record,
+ GString *bdata_str)
+{
+ GString *tmp;
+ CamelSummaryMessageID message_id;
+ const CamelNamedFlags *user_flags;
+ const CamelNameValueArray *user_tags;
+ const GArray *references;
+
+ g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_str != NULL, FALSE);
+
+ #warning Change camel_db_camel_mir_free() to pstring_free only the UID and g_free() all other text
fields
+
+ record->uid = (gchar *) camel_pstring_strdup (xcamel_message_info_get_uid (mi));
+ record->flags = xcamel_message_info_get_flags (mi);
+
+ record->read = ((record->flags & (CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_JUNK)))
? 1 : 0;
+ record->deleted = (record->flags & CAMEL_MESSAGE_DELETED) != 0 ? 1 : 0;
+ record->replied = (record->flags & CAMEL_MESSAGE_ANSWERED) != 0 ? 1 : 0;
+ record->important = (record->flags & CAMEL_MESSAGE_FLAGGED) != 0 ? 1 : 0;
+ record->junk = (record->flags & CAMEL_MESSAGE_JUNK) != 0 ? 1 : 0;
+ record->dirty = (record->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0 ? 1 : 0;
+ record->attachment = (record->flags & CAMEL_MESSAGE_ATTACHMENTS) != 0 ? 1 : 0;
+
+ record->size = xcamel_message_info_get_size (mi);
+ record->dsent = xcamel_message_info_get_date_sent (mi);
+ record->dreceived = xcamel_message_info_get_date_received (mi);
+
+ record->subject = g_strdup (xcamel_message_info_get_subject (mi));
+ record->from = g_strdup (xcamel_message_info_get_from (mi));
+ record->to = g_strdup (xcamel_message_info_get_to (mi));
+ record->cc = g_strdup (xcamel_message_info_get_cc (mi));
+ record->mlist = g_strdup (xcamel_message_info_get_mlist (mi));
+
+ record->followup_flag = g_strdup (xcamel_message_info_get_user_tag (mi, "follow-up"));
+ record->followup_completed_on = g_strdup (xcamel_message_info_get_user_tag (mi, "completed-on"));
+ record->followup_due_by = g_strdup (xcamel_message_info_get_user_tag (mi, "due-by"));
+
+ tmp = g_string_new (NULL);
+ message_id.id.id = xcamel_message_info_get_message_id (mi);
+ g_string_append_printf (tmp, "%lu %lu ", (gulong) message_id.id.part.hi, (gulong)
message_id.id.part.lo);
+ references = xcamel_message_info_get_references (mi);
+ if (references) {
+ guint ii;
+
+ g_string_append_printf (tmp, "%lu", (gulong) references->len);
+ for (ii = 0; ii < references->len; ii++) {
+ message_id.id.id = g_array_index (references, guint64, ii);
+
+ g_string_append_printf (tmp, " %lu %lu", (gulong) message_id.id.part.hi, (gulong)
message_id.id.part.lo);
+ }
+ } else {
+ g_string_append (tmp, "0");
+ }
+ record->part = g_string_free (tmp, FALSE);
+
+ tmp = g_string_new (NULL);
+ user_flags = xcamel_message_info_dup_user_flags (mi);
+ if (user_flags) {
+ guint ii, count;
+
+ count = camel_named_flags_get_length (user_flags);
+ for (ii = 0; ii < count; ii++) {
+ const gchar *name = camel_named_flags_get (user_flags, ii);
+
+ if (name && *name) {
+ if (tmp->len)
+ g_string_append (tmp, " ");
+ g_string_append (tmp, name);
+ }
+ }
+ }
+ record->labels = g_string_free (tmp, FALSE);
+
+ tmp = g_string_new (NULL);
+ user_tags = xcamel_message_info_get_user_tags (mi);
+ if (user_tags) {
+ guint ii, count;
+
+ count = camel_name_value_array_get_length (user_tags);
+ g_string_append_printf (tmp, "%lu", (gulong) count);
+
+ for (ii = 0; ii < count; ii++) {
+ const gchar *name = NULL, *value = NULL;
+
+ if (camel_name_value_array_get (user_tags, ii, &name, &value)) {
+ if (!name)
+ name = "";
+ if (!value)
+ value = "";
+
+ g_string_append_printf (tmp, " %lu-%s %lu-%s", (gulong) strlen (name), name,
(gulong) strlen (value), value);
+ }
+ }
+ } else {
+ g_string_append (tmp, "0");
+ }
+ record->usertags = g_string_free (tmp, FALSE);
+
+ return TRUE;
+}
+
static void
message_info_set_property (GObject *object,
guint property_id,
@@ -153,6 +363,10 @@ message_info_set_property (GObject *object,
xcamel_message_info_set_folder_flagged (mi, g_value_get_boolean (value));
return;
+ case PROP_LOADING:
+ xcamel_message_info_set_loading (mi, g_value_get_boolean (value));
+ return;
+
case PROP_UID:
xcamel_message_info_set_uid (mi, g_value_get_string (value));
return;
@@ -235,11 +449,15 @@ message_info_get_property (GObject *object,
return;
case PROP_DIRTY:
- xcamel_message_info_set_dirty (mi, g_value_get_boolean (value));
+ g_value_set_boolean (value, xcamel_message_info_get_dirty (mi));
return;
case PROP_FOLDER_FLAGGED:
- xcamel_message_info_set_folder_flagged (mi, g_value_get_boolean (value));
+ g_value_set_boolean (value, xcamel_message_info_get_folder_flagged (mi));
+ return;
+
+ case PROP_LOADING:
+ g_value_set_boolean (value, xcamel_message_info_get_loading (mi));
return;
case PROP_UID:
@@ -343,6 +561,8 @@ xcamel_message_info_class_init (xCamelMessageInfoClass *class)
g_type_class_add_private (class, sizeof (xCamelMessageInfoPrivate));
class->clone = message_info_clone;
+ class->load = message_info_load;
+ class->save = message_info_save;
object_class = G_OBJECT_CLASS (class);
object_class->set_property = message_info_set_property;
@@ -425,6 +645,24 @@ xcamel_message_info_class_init (xCamelMessageInfoClass *class)
G_PARAM_READWRITE));
/**
+ * xCamelMessageInfo:loading
+ *
+ * Flag, whether the info is currently loading. It is used to avoid
+ * unnecessary 'folder-flagged' and 'dirty' flags changes.
+ *
+ * Since: 3.24
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_LOADING,
+ g_param_spec_boolean (
+ "loading",
+ "Loading",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+
+ /**
* xCamelMessageInfo:flags
*
* Bit-or of #CamelMessageFlags.
@@ -756,6 +994,96 @@ xcamel_message_info_clone (const xCamelMessageInfo *mi,
}
/**
+ * camel_message_info_load:
+ * @mi: a #CamelMessageInfo to load
+ * @record: a #CamelMIRecord to load the @mi from
+ * @bdata_ptr: a backend specific data (bdata) pointer
+ *
+ * Load content of @mi from the data stored in @record. The @bdata_ptr points
+ * to the current position of the record->bdata, where the read can continue.
+ * Use helper functions camel_message_info_util_bdata_get_number() and
+ * camel_message_info_util_bdata_get_string() to read data from it and
+ * also move forward the *bdata_ptr.
+ *
+ * After successful load of the @mi, the 'dirty' flag is unset.
+ *
+ * Returns: Whether the load was successful.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_load (xCamelMessageInfo *mi,
+ const CamelMIRecord *record,
+ /* const */ gchar **bdata_ptr)
+{
+ xCamelMessageInfoClass *klass;
+ gboolean success;
+
+ g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_ptr != NULL, FALSE);
+
+ klass = XCAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->load != NULL, FALSE);
+
+ g_object_freeze_notify (G_OBJECT (mi));
+ xcamel_message_info_property_lock (mi);
+ xcamel_message_info_set_loading (mi, TRUE);
+
+ success = klass->load (mi, record, bdata_ptr);
+
+ if (success)
+ xcamel_message_info_set_dirty (mi, FALSE);
+
+ xcamel_message_info_set_loading (mi, FALSE);
+ xcamel_message_info_property_unlock (mi);
+ g_object_thaw_notify (G_OBJECT (mi));
+
+ return success;
+}
+
+/**
+ * camel_message_info_save:
+ * @mi: a #xCamelMessageInfo
+ * @record: a #CamelMIRecord to populate
+ * @bdata_str: a #GString with a string to save as backend specific data (bdata)
+ *
+ * Save the @mi content to the message info record @record. It can populate all
+ * but the record->bdata value, which is set fro mthe @bdata_str. Use helper functions
+ * camel_message_info_util_bdata_put_number() and
+ * camel_message_info_util_bdata_put_string() to put data into the @bdata_str.
+ *
+ * Returns: Whether the save succeeded.
+ *
+ * Since: 3.24
+ **/
+gboolean
+camel_message_info_save (const xCamelMessageInfo *mi,
+ CamelMIRecord *record,
+ GString *bdata_str)
+{
+ xCamelMessageInfoClass *klass;
+ gboolean success;
+
+ g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_str != NULL, FALSE);
+
+ klass = XCAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->save != NULL, FALSE);
+
+ xcamel_message_info_property_lock (mi);
+
+ success = klass->save (mi, record, bdata_str);
+
+ xcamel_message_info_property_unlock (mi);
+
+ return success;
+}
+
+/**
* xcamel_message_info_ref_summary:
* @mi: a #xCamelMessageInfo
*
@@ -885,16 +1213,18 @@ void
xcamel_message_info_set_dirty (const xCamelMessageInfo *mi,
gboolean dirty)
{
- gboolean changed;
+ gboolean changed, loading;
+
g_return_if_fail (XCAMEL_IS_MESSAGE_INFO (mi));
xcamel_message_info_property_lock (mi);
changed = (!mi->priv->dirty) != (!dirty);
if (changed)
mi->priv->dirty = dirty;
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "dirty");
if (dirty) {
@@ -906,7 +1236,6 @@ xcamel_message_info_set_dirty (const xCamelMessageInfo *mi,
g_clear_object (&summary);
}
-
}
}
@@ -964,6 +1293,58 @@ xcamel_message_info_set_folder_flagged (xCamelMessageInfo *mi,
}
/**
+ * xcamel_message_info_get_loading:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: Whether the @mi is loading, which means that it will not influence
+ * 'dirty' and 'folder-flagged' flags in the set/take functions,
+ * neither it will emit any GObject::notify signals on change.
+ *
+ * Since: 3.24
+ **/
+gboolean
+xcamel_message_info_get_loading (const xCamelMessageInfo *mi)
+{
+ gboolean result;
+
+ g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
+
+ xcamel_message_info_property_lock (mi);
+ result = mi->priv->loading;
+ xcamel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
+ * xcamel_message_info_set_loading:
+ * @mi: a #CamelMessageInfo
+ * @loading: a loading state to set
+ *
+ * Marks the @mi as loading, which means that it will not influence
+ * 'dirty' and 'folder-flagged' flags in the set/take functions,
+ * neither it will emit any GObject::notify signals on change.
+ *
+ * Since: 3.24
+ **/
+void
+xcamel_message_info_set_loading (const xCamelMessageInfo *mi,
+ gboolean loading)
+{
+ gboolean changed;
+ g_return_if_fail (XCAMEL_IS_MESSAGE_INFO (mi));
+
+ xcamel_message_info_property_lock (mi);
+ changed = (!mi->priv->loading) != (!loading);
+ if (changed)
+ mi->priv->loading = loading;
+ xcamel_message_info_property_unlock (mi);
+
+ if (changed)
+ g_object_notify (G_OBJECT (mi), "loading");
+}
+
+/**
* xcamel_message_info_get_uid:
* @mi: a #CamelMessageInfo
*
@@ -1019,8 +1400,8 @@ xcamel_message_info_pooldup_uid (const xCamelMessageInfo *mi)
* @uid: a UID to set
*
* Changes UID of the @mi to @uid. If it changes, the 'dirty' flag
- * of the @mi is set too. This change does not influence the 'folder-flagged'
- * flag.
+ * of the @mi is set too, unless the @mi is loading. This change
+ * does not influence the 'folder-flagged' flag.
*
* Returns: Whether the UID changed.
*
@@ -1030,7 +1411,7 @@ gboolean
xcamel_message_info_set_uid (xCamelMessageInfo *mi,
const gchar *uid)
{
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -1040,9 +1421,10 @@ xcamel_message_info_set_uid (xCamelMessageInfo *mi,
camel_pstring_free (mi->priv->uid);
mi->priv->uid = camel_pstring_strdup (uid);
}
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "uid");
xcamel_message_info_set_dirty (mi, TRUE);
}
@@ -1086,8 +1468,8 @@ xcamel_message_info_get_flags (const xCamelMessageInfo *mi)
* Change the state of the flags on the @mi.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is also emitted folder's "changed" signal
- * for this @mi, if necessary.
+ * set automatically, unless the @mi is loading. There is also emitted
+ * folder's "changed" signal for this @mi, if necessary.
*
* Returns: Whether the flags changed.
*
@@ -1099,7 +1481,7 @@ xcamel_message_info_set_flags (xCamelMessageInfo *mi,
guint32 set)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -1109,9 +1491,10 @@ xcamel_message_info_set_flags (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->set_flags (mi, mask, set);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "flags");
xcamel_message_info_set_dirty (mi, TRUE);
@@ -1166,8 +1549,8 @@ xcamel_message_info_get_user_flag (const xCamelMessageInfo *mi,
* can only be set or unset, while the user tags can contain certain values.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is also emitted folder's "changed" signal
- * for this @mi, if necessary.
+ * set automatically, unless the @mi is loading. There is also emitted
+ * folder's "changed" signal for this @mi, if necessary.
*
* Returns: Whether the message info changed.
*
@@ -1179,7 +1562,7 @@ xcamel_message_info_set_user_flag (xCamelMessageInfo *mi,
gboolean state)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
g_return_val_if_fail (name != NULL, FALSE);
@@ -1190,9 +1573,10 @@ xcamel_message_info_set_user_flag (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->set_user_flag (mi, name, state);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "user-flags");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -1204,6 +1588,34 @@ xcamel_message_info_set_user_flag (xCamelMessageInfo *mi,
}
/**
+ * xcamel_message_info_get_user_flags:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: (transfer none) (nullable): A #CamelNamedFlags with all the currently set
+ * user flags on the @mi. Do not modify it.
+ *
+ * Since: 3.24
+ **/
+const CamelNamedFlags *
+xcamel_message_info_get_user_flags (const xCamelMessageInfo *mi)
+{
+ xCamelMessageInfoClass *klass;
+ const CamelNamedFlags *result;
+
+ g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ klass = XCAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->get_user_flags != NULL, NULL);
+
+ xcamel_message_info_property_lock (mi);
+ result = klass->get_user_flags (mi);
+ xcamel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
* xcamel_message_info_dup_user_flags:
* @mi: a #CamelMessageInfo
*
@@ -1242,8 +1654,8 @@ xcamel_message_info_dup_user_flags (const xCamelMessageInfo *mi)
* of it. The caller should not change @user_flags afterwards.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is also emitted folder's "changed" signal
- * for this @mi, if necessary.
+ * set automatically, unless the @mi is loading. There is also emitted
+ * folder's "changed" signal for this @mi, if necessary.
*
* Note that it's not safe to use the @user_flags after the call to this function,
* because it can be freed due to no change.
@@ -1257,7 +1669,7 @@ xcamel_message_info_take_user_flags (xCamelMessageInfo *mi,
CamelNamedFlags *user_flags)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -1267,9 +1679,10 @@ xcamel_message_info_take_user_flags (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->take_user_flags (mi, user_flags);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "user-flags");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -1345,8 +1758,8 @@ xcamel_message_info_dup_user_tag (const xCamelMessageInfo *mi,
* Set user tag @name to @value, or remove it, if @value is %NULL.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is also emitted folder's "changed" signal
- * for this @mi, if necessary.
+ * set automatically, unless the @mi is loading. There is also emitted
+ * folder's "changed" signal for this @mi, if necessary.
*
* Returns: Whether the @mi changed.
*
@@ -1358,7 +1771,7 @@ xcamel_message_info_set_user_tag (xCamelMessageInfo *mi,
const gchar *value)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
g_return_val_if_fail (name != NULL, FALSE);
@@ -1369,9 +1782,10 @@ xcamel_message_info_set_user_tag (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->set_user_tag (mi, name, value);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "user-tags");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -1383,10 +1797,38 @@ xcamel_message_info_set_user_tag (xCamelMessageInfo *mi,
}
/**
+ * xcamel_message_info_get_user_tags:
+ * @mi: a #CamelMessageInfo
+ *
+ * Returns: (transfer none) (nullable): a #CamelNameValueArray containing all set
+ * user tags of the @mi. Do not modify it.
+ *
+ * Since: 3.24
+ **/
+const CamelNameValueArray *
+xcamel_message_info_get_user_tags (const xCamelMessageInfo *mi)
+{
+ xCamelMessageInfoClass *klass;
+ const CamelNameValueArray *result;
+
+ g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), NULL);
+
+ klass = XCAMEL_MESSAGE_INFO_GET_CLASS (mi);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->get_user_tags != NULL, NULL);
+
+ xcamel_message_info_property_lock (mi);
+ result = klass->get_user_tags (mi);
+ xcamel_message_info_property_unlock (mi);
+
+ return result;
+}
+
+/**
* xcamel_message_info_dup_user_tags:
* @mi: a #CamelMessageInfo
*
- * Returns: (transfer full): a newly allocated #CamelNameValueArray containing all set
+ * Returns: (transfer full) (nullable): a newly allocated #CamelNameValueArray containing all set
* user tags of the @mi. Free it with camel_name_value_array_free() when no longer needed.
*
* Since: 3.24
@@ -1420,8 +1862,8 @@ xcamel_message_info_dup_user_tags (const xCamelMessageInfo *mi)
* of it. The caller should not change @user_tags afterwards.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is also emitted folder's "changed" signal
- * for this @mi, if necessary.
+ * set automatically, unless the @mi is loading. There is also emitted
+ * folder's "changed" signal for this @mi, if necessary.
*
* Note that it's not safe to use the @user_tags after the call to this function,
* because it can be freed due to no change.
@@ -1435,7 +1877,7 @@ xcamel_message_info_take_user_tags (xCamelMessageInfo *mi,
CamelNameValueArray *user_tags)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -1445,9 +1887,10 @@ xcamel_message_info_take_user_tags (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->take_user_tags (mi, user_tags);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "user-tags");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -1497,8 +1940,8 @@ xcamel_message_info_get_subject (const xCamelMessageInfo *mi)
* change in the associated message.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is not emitted folder's "changed" signal
- * for this @mi.
+ * set automatically, unless the @mi is loading. There is not emitted
+ * folder's "changed" signal for this @mi.
*
* Returns: Whether the value changed.
*
@@ -1509,7 +1952,7 @@ xcamel_message_info_set_subject (xCamelMessageInfo *mi,
const gchar *subject)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -1519,9 +1962,10 @@ xcamel_message_info_set_subject (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->set_subject (mi, subject);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "subject");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -1569,8 +2013,8 @@ xcamel_message_info_get_preview (const xCamelMessageInfo *mi)
* change in the associated message.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is not emitted folder's "changed" signal
- * for this @mi.
+ * set automatically, unless the @mi is loading. There is not emitted
+ * folder's "changed" signal for this @mi.
*
* Returns: Whether the value changed.
*
@@ -1581,7 +2025,7 @@ xcamel_message_info_set_preview (xCamelMessageInfo *mi,
const gchar *preview)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -1591,9 +2035,10 @@ xcamel_message_info_set_preview (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->set_preview (mi, preview);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "preview");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -1641,8 +2086,8 @@ xcamel_message_info_get_from (const xCamelMessageInfo *mi)
* change in the associated message.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is not emitted folder's "changed" signal
- * for this @mi.
+ * set automatically, unless the @mi is loading. There is not emitted
+ * folder's "changed" signal for this @mi.
*
* Returns: Whether the value changed.
*
@@ -1653,7 +2098,7 @@ xcamel_message_info_set_from (xCamelMessageInfo *mi,
const gchar *from)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -1663,9 +2108,10 @@ xcamel_message_info_set_from (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->set_from (mi, from);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "from");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -1713,8 +2159,8 @@ xcamel_message_info_get_to (const xCamelMessageInfo *mi)
* change in the associated message.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is not emitted folder's "changed" signal
- * for this @mi.
+ * set automatically, unless the @mi is loading. There is not emitted
+ * folder's "changed" signal for this @mi.
*
* Returns: Whether the value changed.
*
@@ -1725,7 +2171,7 @@ xcamel_message_info_set_to (xCamelMessageInfo *mi,
const gchar *to)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -1735,9 +2181,10 @@ xcamel_message_info_set_to (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->set_to (mi, to);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "to");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -1785,8 +2232,8 @@ xcamel_message_info_get_cc (const xCamelMessageInfo *mi)
* change in the associated message.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is not emitted folder's "changed" signal
- * for this @mi.
+ * set automatically, unless the @mi is loading. There is not emitted
+ * folder's "changed" signal for this @mi.
*
* Returns: Whether the value changed.
*
@@ -1797,7 +2244,7 @@ xcamel_message_info_set_cc (xCamelMessageInfo *mi,
const gchar *cc)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -1807,9 +2254,10 @@ xcamel_message_info_set_cc (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->set_cc (mi, cc);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "cc");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -1857,8 +2305,8 @@ xcamel_message_info_get_mlist (const xCamelMessageInfo *mi)
* change in the associated message.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is not emitted folder's "changed" signal
- * for this @mi.
+ * set automatically, unless the @mi is loading. There is not emitted
+ * folder's "changed" signal for this @mi.
*
* Returns: Whether the value changed.
*
@@ -1869,7 +2317,7 @@ xcamel_message_info_set_mlist (xCamelMessageInfo *mi,
const gchar *mlist)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -1879,9 +2327,10 @@ xcamel_message_info_set_mlist (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->set_mlist (mi, mlist);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "mlist");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -1929,8 +2378,8 @@ xcamel_message_info_get_size (const xCamelMessageInfo *mi)
* change in the associated message.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is not emitted folder's "changed" signal
- * for this @mi.
+ * set automatically, unless the @mi is loading. There is not emitted
+ * folder's "changed" signal for this @mi.
*
* Returns: Whether the value changed.
*
@@ -1941,7 +2390,7 @@ xcamel_message_info_set_size (xCamelMessageInfo *mi,
guint32 size)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -1951,9 +2400,10 @@ xcamel_message_info_set_size (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->set_size (mi, size);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "size");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -2001,8 +2451,8 @@ xcamel_message_info_get_date_sent (const xCamelMessageInfo *mi)
* change in the associated message.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is not emitted folder's "changed" signal
- * for this @mi.
+ * set automatically, unless the @mi is loading. There is not emitted
+ * folder's "changed" signal for this @mi.
*
* Returns: Whether the value changed.
*
@@ -2013,7 +2463,7 @@ xcamel_message_info_set_date_sent (xCamelMessageInfo *mi,
gint64 date_sent)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -2023,9 +2473,10 @@ xcamel_message_info_set_date_sent (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->set_date_sent (mi, date_sent);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "date-sent");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -2073,8 +2524,8 @@ xcamel_message_info_get_date_received (const xCamelMessageInfo *mi)
* change in the associated message.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is not emitted folder's "changed" signal
- * for this @mi.
+ * set automatically, unless the @mi is loading. There is not emitted
+ * folder's "changed" signal for this @mi.
*
* Returns: Whether the value changed.
*
@@ -2085,7 +2536,7 @@ xcamel_message_info_set_date_received (xCamelMessageInfo *mi,
gint64 date_received)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -2095,9 +2546,10 @@ xcamel_message_info_set_date_received (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->set_date_received (mi, date_received);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "date-received");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -2149,8 +2601,8 @@ xcamel_message_info_get_message_id (const xCamelMessageInfo *mi)
* change in the associated message.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is not emitted folder's "changed" signal
- * for this @mi.
+ * set automatically, unless the @mi is loading. There is not emitted
+ * folder's "changed" signal for this @mi.
*
* Returns: Whether the value changed.
*
@@ -2161,7 +2613,7 @@ xcamel_message_info_set_message_id (xCamelMessageInfo *mi,
guint64 message_id)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -2171,9 +2623,10 @@ xcamel_message_info_set_message_id (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->set_message_id (mi, message_id);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "message-id");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -2267,8 +2720,8 @@ xcamel_message_info_dup_references (const xCamelMessageInfo *mi)
* change in the associated message.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is not emitted folder's "changed" signal
- * for this @mi.
+ * set automatically, unless the @mi is loading. There is not emitted
+ * folder's "changed" signal for this @mi.
*
* Note that it's not safe to use the @references after the call to this function,
* because it can be freed due to no change.
@@ -2282,7 +2735,7 @@ xcamel_message_info_take_references (xCamelMessageInfo *mi,
GArray *references)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -2292,9 +2745,10 @@ xcamel_message_info_take_references (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->take_references (mi, references);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "references");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -2375,8 +2829,8 @@ xcamel_message_info_dup_headers (const xCamelMessageInfo *mi)
* change in the associated message.
*
* If the @mi changed, the 'dirty' flag and the 'folder-flagged' flag are
- * set automatically. There is not emitted folder's "changed" signal
- * for this @mi.
+ * set automatically, unless the @mi is loading. There is not emitted
+ * folder's "changed" signal for this @mi.
*
* Note that it's not safe to use the @headers after the call to this function,
* because it can be freed due to no change.
@@ -2390,7 +2844,7 @@ xcamel_message_info_take_headers (xCamelMessageInfo *mi,
CamelNameValueArray *headers)
{
xCamelMessageInfoClass *klass;
- gboolean changed;
+ gboolean changed, loading;
g_return_val_if_fail (XCAMEL_IS_MESSAGE_INFO (mi), FALSE);
@@ -2400,9 +2854,10 @@ xcamel_message_info_take_headers (xCamelMessageInfo *mi,
xcamel_message_info_property_lock (mi);
changed = klass->take_headers (mi, headers);
+ loading = mi->priv->loading;
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !loading) {
g_object_notify (G_OBJECT (mi), "headers");
xcamel_message_info_set_dirty (mi, TRUE);
xcamel_message_info_set_folder_flagged (mi, TRUE);
@@ -2410,3 +2865,151 @@ xcamel_message_info_take_headers (xCamelMessageInfo *mi,
return changed;
}
+
+/**
+ * camel_message_info_util_bdata_get_number:
+ * @bdata_ptr: a backend specific data (bdata) pointer
+ * @default_value: a value to return, when no data can be read
+ *
+ * Reads a numeric data from the @bdata_ptr and moves the @bdata_ptr
+ * after that number. If the number cannot be read, then the @default_value
+ * is returned instead and the @bdata_ptr is left unchanged. The number
+ * might be previously stored with the camel_message_info_util_bdata_put_number().
+ *
+ * Returns: The read number, or the @default_value, if the @bdata_ptr doesn't
+ * point to a number.
+ *
+ * Since: 3.24
+ **/
+gint64
+camel_message_info_util_bdata_get_number (/* const */ gchar **bdata_ptr,
+ gint64 default_value)
+{
+ gint64 result;
+ gchar *endptr;
+
+ g_return_val_if_fail (bdata_ptr != NULL, default_value);
+
+ if (!bdata_ptr || !*bdata_ptr || !**bdata_ptr)
+ return default_value;
+
+ if (**bdata_ptr == ' ')
+ *bdata_ptr += 1;
+
+ if (!**bdata_ptr)
+ return default_value;
+
+ endptr = *bdata_ptr;
+
+ result = g_ascii_strtoll (*bdata_ptr, &endptr, 10);
+
+ if (endptr == *bdata_ptr)
+ result = default_value;
+ else
+ *bdata_ptr = endptr;
+
+ return result;
+}
+
+/**
+ * camel_message_info_util_bdata_put_number:
+ * @bdata_str: a #GString to store a backend specific data (bdata)
+ * @value: a value to store
+ *
+ * Puts the number @value at the end of the @bdata_str. In case the @bdata_str
+ * is not empty a space is added before the numeric @value. The stored value
+ * can be read back with the camel_message_info_util_bdata_get_number().
+ *
+ * Since: 3.24
+ **/
+void
+camel_message_info_util_bdata_put_number (GString *bdata_str,
+ gint64 value)
+{
+ g_return_if_fail (bdata_str != NULL);
+
+ if (bdata_str->len && bdata_str->str[bdata_str->len - 1] != ' ')
+ g_string_append_c (bdata_str, ' ');
+
+ g_string_append_printf (bdata_str, "%" G_GINT64_FORMAT, value);
+}
+
+/**
+ * camel_message_info_util_bdata_get_string:
+ * @bdata_ptr: a backend specific data (bdata) pointer
+ * @default_value: a value to return, when no data can be read
+ *
+ * Reads a string data from the @bdata_ptr and moves the @bdata_ptr
+ * after that string. If the string cannot be read, then the @default_value
+ * is returned instead and the @bdata_ptr is left unchanged. The string
+ * might be previously stored with the camel_message_info_util_bdata_put_string().
+ *
+ * Returns: (transfer full): Newly allocated string, which was read, or
+ * dupped the @default_value, if the @bdata_ptr doesn't point to a string.
+ * Free returned pointer with g_free() when done with it.
+ *
+ * Since: 3.24
+ **/
+gchar *
+camel_message_info_util_bdata_get_string (/* const */ gchar **bdata_ptr,
+ const gchar *default_value)
+{
+ gint64 length, has_length;
+ gchar *orig_bdata_ptr;
+ gchar *result;
+
+ g_return_val_if_fail (bdata_ptr != NULL, NULL);
+
+ orig_bdata_ptr = *bdata_ptr;
+
+ length = camel_message_info_util_bdata_get_number (bdata_ptr, -1);
+
+ /* might be a '-' sign */
+ if (*bdata_ptr && **bdata_ptr == '-')
+ *bdata_ptr += 1;
+ else
+ length = -1;
+
+ if (length < 0 || !*bdata_ptr || !**bdata_ptr || *bdata_ptr == orig_bdata_ptr) {
+ *bdata_ptr = orig_bdata_ptr;
+
+ return g_strdup (default_value);
+ }
+
+ if (!length)
+ return g_strdup ("");
+
+ has_length = strlen (*bdata_ptr);
+ if (has_length < length)
+ length = has_length;
+
+ result = g_strndup (*bdata_ptr, length);
+ *bdata_ptr += length;
+
+ return result;
+}
+
+/**
+ * camel_message_info_util_bdata_put_string:
+ * @bdata_str: a #GString to store a backend specific data (bdata)
+ * @value: a value to store
+ *
+ * Puts the string @value at the end of the @bdata_str. In case the @bdata_str
+ * is not empty a space is added before the string @value. The stored value
+ * can be read back with the camel_message_info_util_bdata_get_string().
+ *
+ * The strings are encoded as "length-value", quotes for clarity only.
+ *
+ * Since: 3.24
+ **/
+void
+camel_message_info_util_bdata_put_string (GString *bdata_str,
+ const gchar *value)
+{
+ g_return_if_fail (bdata_str != NULL);
+ g_return_if_fail (value != NULL);
+
+ camel_message_info_util_bdata_put_number (bdata_str, strlen (value));
+
+ g_string_append_printf (bdata_str, "-%s", value);
+}
diff --git a/camel/camel-message-info.h b/camel/camel-message-info.h
index 6c4b163..ef73a6f 100644
--- a/camel/camel-message-info.h
+++ b/camel/camel-message-info.h
@@ -49,6 +49,7 @@ G_BEGIN_DECLS
/* Forward declarations */
struct _CamelFolderSummary;
+struct _CamelMIRecord;
/* A summary messageid is a 64 bit identifier (partial md5 hash) */
typedef struct _CamelSummaryMessageID {
@@ -106,9 +107,15 @@ struct _xCamelMessageInfoClass {
xCamelMessageInfo * (* clone) (const xCamelMessageInfo *mi,
struct _CamelFolderSummary *assign_summary);
+ gboolean (* load) (xCamelMessageInfo *mi,
+ const struct _CamelMIRecord *record,
+ /* const */ gchar **bdata_ptr);
+ gboolean (* save) (const xCamelMessageInfo *mi,
+ struct _CamelMIRecord *record,
+ GString *bdata_str);
guint32 (* get_flags) (const xCamelMessageInfo *mi);
gboolean (* set_flags) (xCamelMessageInfo *mi,
- CamelMessageFlags flags,
+ CamelMessageFlags mask,
guint32 set);
gboolean (* get_user_flag)
(const xCamelMessageInfo *mi,
@@ -117,6 +124,8 @@ struct _xCamelMessageInfoClass {
(xCamelMessageInfo *mi,
const gchar *name,
gboolean state);
+ const CamelNamedFlags * (* get_user_flags)
+ (const xCamelMessageInfo *mi);
CamelNamedFlags * (* dup_user_flags)
(const xCamelMessageInfo *mi);
gboolean (* take_user_flags)
@@ -127,6 +136,9 @@ struct _xCamelMessageInfoClass {
gboolean (* set_user_tag)(xCamelMessageInfo *mi,
const gchar *name,
const gchar *value);
+ const CamelNameValueArray *
+ (* get_user_tags)
+ (const xCamelMessageInfo *mi);
CamelNameValueArray * (* dup_user_tags)
(const xCamelMessageInfo *mi);
gboolean (* take_user_tags)
@@ -188,6 +200,12 @@ xCamelMessageInfo *
xCamelMessageInfo *
xcamel_message_info_clone (const xCamelMessageInfo *mi,
struct _CamelFolderSummary *assign_summary);
+gboolean camel_message_info_load (xCamelMessageInfo *mi,
+ const struct _CamelMIRecord *record,
+ /* const */ gchar **bdata_ptr);
+gboolean camel_message_info_save (const xCamelMessageInfo *mi,
+ struct _CamelMIRecord *record,
+ GString *bdata_str);
struct _CamelFolderSummary *
xcamel_message_info_ref_summary (const xCamelMessageInfo *mi);
void xcamel_message_info_property_lock
@@ -202,6 +220,9 @@ gboolean xcamel_message_info_get_folder_flagged
gboolean xcamel_message_info_set_folder_flagged
(xCamelMessageInfo *mi,
gboolean folder_flagged);
+gboolean xcamel_message_info_get_loading (const xCamelMessageInfo *mi);
+void xcamel_message_info_set_loading (const xCamelMessageInfo *mi,
+ gboolean loading);
const gchar * xcamel_message_info_get_uid (const xCamelMessageInfo *mi);
const gchar * xcamel_message_info_pooldup_uid (const xCamelMessageInfo *mi);
gboolean xcamel_message_info_set_uid (xCamelMessageInfo *mi,
@@ -217,6 +238,9 @@ gboolean xcamel_message_info_set_user_flag
(xCamelMessageInfo *mi,
const gchar *name,
gboolean state);
+const CamelNamedFlags *
+ xcamel_message_info_get_user_flags
+ (const xCamelMessageInfo *mi);
CamelNamedFlags *
xcamel_message_info_dup_user_flags
(const xCamelMessageInfo *mi);
@@ -231,6 +255,9 @@ gchar * xcamel_message_info_dup_user_tag (const xCamelMessageInfo *mi,
gboolean xcamel_message_info_set_user_tag (xCamelMessageInfo *mi,
const gchar *name,
const gchar *value);
+const CamelNameValueArray *
+ xcamel_message_info_get_user_tags
+ (const xCamelMessageInfo *mi);
CamelNameValueArray *
xcamel_message_info_dup_user_tags
(const xCamelMessageInfo *mi);
@@ -287,6 +314,19 @@ CamelNameValueArray *
gboolean xcamel_message_info_take_headers (xCamelMessageInfo *mi,
CamelNameValueArray *headers);
+/* Utility functions */
+gint64 camel_message_info_util_bdata_get_number
+ (/* const */ gchar **bdata_ptr,
+ gint64 default_value);
+void camel_message_info_util_bdata_put_number
+ (GString *bdata_str,
+ gint64 value);
+gchar * camel_message_info_util_bdata_get_string
+ (/* const */ gchar **bdata_ptr,
+ const gchar *default_value);
+void camel_message_info_util_bdata_put_string
+ (GString *bdata_str,
+ const gchar *value);
G_END_DECLS
#endif /* XCAMEL_MESSAGE_INFO_H */
diff --git a/camel/camel-vee-message-info.c b/camel/camel-vee-message-info.c
index 8c52b94..d604416 100644
--- a/camel/camel-vee-message-info.c
+++ b/camel/camel-vee-message-info.c
@@ -125,6 +125,12 @@ vee_message_info_set_user_flag (xCamelMessageInfo *mi,
vee_call_from_parent_mi (FALSE, gboolean, xcamel_message_info_set_user_flag, (orig_mi, name, state));
}
+static const CamelNamedFlags *
+vee_message_info_get_user_flags (const xCamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (NULL, const CamelNamedFlags *, xcamel_message_info_get_user_flags,
(orig_mi));
+}
+
static CamelNamedFlags *
vee_message_info_dup_user_flags (const xCamelMessageInfo *mi)
{
@@ -159,6 +165,12 @@ vee_message_info_dup_user_tags (const xCamelMessageInfo *mi)
vee_call_from_parent_mi (NULL, CamelNameValueArray *, xcamel_message_info_dup_user_tags, (orig_mi));
}
+static const CamelNameValueArray *
+vee_message_info_get_user_tags (const xCamelMessageInfo *mi)
+{
+ vee_call_from_parent_mi (NULL, const CamelNameValueArray *, xcamel_message_info_get_user_tags,
(orig_mi));
+}
+
static gboolean
vee_message_info_take_user_tags (xCamelMessageInfo *mi,
CamelNameValueArray *user_tags)
@@ -349,10 +361,12 @@ xcamel_vee_message_info_class_init (xCamelVeeMessageInfoClass *class)
mi_class->set_flags = vee_message_info_set_flags;
mi_class->get_user_flag = vee_message_info_get_user_flag;
mi_class->set_user_flag = vee_message_info_set_user_flag;
+ mi_class->get_user_flags = vee_message_info_get_user_flags;
mi_class->dup_user_flags = vee_message_info_dup_user_flags;
mi_class->take_user_flags = vee_message_info_take_user_flags;
mi_class->get_user_tag = vee_message_info_get_user_tag;
mi_class->set_user_tag = vee_message_info_set_user_tag;
+ mi_class->get_user_tags = vee_message_info_get_user_tags;
mi_class->dup_user_tags = vee_message_info_dup_user_tags;
mi_class->take_user_tags = vee_message_info_take_user_tags;
mi_class->get_subject = vee_message_info_get_subject;
diff --git a/camel/providers/imapx/camel-imapx-message-info.c
b/camel/providers/imapx/camel-imapx-message-info.c
index c000f14..609b83f 100644
--- a/camel/providers/imapx/camel-imapx-message-info.c
+++ b/camel/providers/imapx/camel-imapx-message-info.c
@@ -67,6 +67,31 @@ imapx_message_info_clone (const xCamelMessageInfo *mi,
return result;
}
+static gboolean
+imapx_message_info_load (xCamelMessageInfo *mi,
+ const CamelMIRecord *record,
+ /* const */ gchar **bdata_ptr)
+{
+ xCamelIMAPXMessageInfo *imi;
+
+ g_return_val_if_fail (XCAMEL_IS_IMAPX_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_ptr != NULL, FALSE);
+
+ if (!XCAMEL_MESSAGE_INFO_CLASS (xcamel_imapx_message_info_parent_class)->load ||
+ !XCAMEL_MESSAGE_INFO_CLASS (xcamel_imapx_message_info_parent_class)->load (mi, record, bdata_ptr))
+ return FALSE;
+
+ imi = XCAMEL_IMAPX_MESSAGE_INFO (mi);
+
+ /* Reset server-side information, which is not saved into the summary anyway. */
+ xcamel_imapx_message_info_set_server_flags (imi, 0);
+ xcamel_imapx_message_info_take_server_user_flags (imi, NULL);
+ xcamel_imapx_message_info_take_server_user_tags (imi, NULL);
+
+ return TRUE;
+}
+
static void
imapx_message_info_set_property (GObject *object,
guint property_id,
@@ -142,6 +167,7 @@ xcamel_imapx_message_info_class_init (xCamelIMAPXMessageInfoClass *class)
mi_class = XCAMEL_MESSAGE_INFO_CLASS (class);
mi_class->clone = imapx_message_info_clone;
+ mi_class->load = imapx_message_info_load;
object_class = G_OBJECT_CLASS (class);
object_class->set_property = imapx_message_info_set_property;
@@ -244,7 +270,7 @@ xcamel_imapx_message_info_set_server_flags (xCamelIMAPXMessageInfo *imi,
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !xcamel_message_info_get_loading (mi)) {
g_object_notify (G_OBJECT (imi), "server-flags");
xcamel_message_info_set_dirty (mi, TRUE);
}
@@ -310,7 +336,7 @@ xcamel_imapx_message_info_take_server_user_flags (xCamelIMAPXMessageInfo *imi,
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !xcamel_message_info_get_loading (mi)) {
g_object_notify (G_OBJECT (imi), "server-user-flags");
xcamel_message_info_set_dirty (mi, TRUE);
}
@@ -376,7 +402,7 @@ xcamel_imapx_message_info_take_server_user_tags (xCamelIMAPXMessageInfo *imi,
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !xcamel_message_info_get_loading (mi)) {
g_object_notify (G_OBJECT (imi), "server-user-tags");
xcamel_message_info_set_dirty (mi, TRUE);
}
diff --git a/camel/providers/local/camel-maildir-message-info.c
b/camel/providers/local/camel-maildir-message-info.c
index d833f41..84badca 100644
--- a/camel/providers/local/camel-maildir-message-info.c
+++ b/camel/providers/local/camel-maildir-message-info.c
@@ -66,6 +66,28 @@ maildir_message_info_clone (const xCamelMessageInfo *mi,
return result;
}
+static gboolean
+maildir_message_info_load (xCamelMessageInfo *mi,
+ const CamelMIRecord *record,
+ /* const */ gchar **bdata_ptr)
+{
+ xCamelMaildirMessageInfo *mmi;
+
+ g_return_val_if_fail (XCAMEL_IS_MAILDIR_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_ptr != NULL, FALSE);
+
+ if (!XCAMEL_MESSAGE_INFO_CLASS (xcamel_maildir_message_info_parent_class)->load ||
+ !XCAMEL_MESSAGE_INFO_CLASS (xcamel_maildir_message_info_parent_class)->load (mi, record,
bdata_ptr))
+ return FALSE;
+
+ mmi = XCAMEL_MAILDIR_MESSAGE_INFO (mi);
+
+ xcamel_maildir_message_info_take_filename (mmi, camel_maildir_summary_info_to_name (mmi));
+
+ return TRUE;
+}
+
static void
maildir_message_info_set_property (GObject *object,
guint property_id,
@@ -122,6 +144,7 @@ xcamel_maildir_message_info_class_init (xCamelMaildirMessageInfoClass *class)
mi_class = XCAMEL_MESSAGE_INFO_CLASS (class);
mi_class->clone = maildir_message_info_clone;
+ mi_class->load = maildir_message_info_load;
object_class = G_OBJECT_CLASS (class);
object_class->set_property = maildir_message_info_set_property;
@@ -190,6 +213,15 @@ gboolean
xcamel_maildir_message_info_set_filename (xCamelMaildirMessageInfo *mmi,
const gchar *filename)
{
+ g_return_val_if_fail (XCAMEL_IS_MAILDIR_MESSAGE_INFO (mmi), FALSE);
+
+ return xcamel_maildir_message_info_take_filename (mmi, g_strdup (filename));
+}
+
+gboolean
+xcamel_maildir_message_info_take_filename (xCamelMaildirMessageInfo *mmi,
+ gchar *filename)
+{
xCamelMessageInfo *mi;
gboolean changed;
@@ -203,12 +235,14 @@ xcamel_maildir_message_info_set_filename (xCamelMaildirMessageInfo *mmi,
if (changed) {
g_free (mmi->priv->filename);
- mmi->priv->filename = g_strdup (filename);
+ mmi->priv->filename = filename;
+ } else if (filename != mmi->priv->filename) {
+ g_free (filename);
}
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !xcamel_message_info_get_loading (mi)) {
g_object_notify (G_OBJECT (mmi), "filename");
xcamel_message_info_set_dirty (mi, TRUE);
}
diff --git a/camel/providers/local/camel-maildir-message-info.h
b/camel/providers/local/camel-maildir-message-info.h
index efba5b0..bd1840a 100644
--- a/camel/providers/local/camel-maildir-message-info.h
+++ b/camel/providers/local/camel-maildir-message-info.h
@@ -65,6 +65,9 @@ gchar * xcamel_maildir_message_info_dup_filename
gboolean xcamel_maildir_message_info_set_filename
(xCamelMaildirMessageInfo *mmi,
const gchar *filename);
+gboolean xcamel_maildir_message_info_take_filename
+ (xCamelMaildirMessageInfo *mmi,
+ gchar *filename);
G_END_DECLS
diff --git a/camel/providers/local/camel-mbox-message-info.c b/camel/providers/local/camel-mbox-message-info.c
index be330b9..38ed6a0 100644
--- a/camel/providers/local/camel-mbox-message-info.c
+++ b/camel/providers/local/camel-mbox-message-info.c
@@ -61,11 +61,60 @@ mbox_message_info_clone (const xCamelMessageInfo *mi,
return result;
}
+static gboolean
+mbox_message_info_load (xCamelMessageInfo *mi,
+ const CamelMIRecord *record,
+ /* const */ gchar **bdata_ptr)
+{
+ xCamelMboxMessageInfo *mmi;
+ gint64 offset;
+
+ g_return_val_if_fail (XCAMEL_IS_MBOX_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_ptr != NULL, FALSE);
+
+ if (!XCAMEL_MESSAGE_INFO_CLASS (xcamel_mbox_message_info_parent_class)->load ||
+ !XCAMEL_MESSAGE_INFO_CLASS (xcamel_mbox_message_info_parent_class)->load (mi, record, bdata_ptr))
+ return FALSE;
+
+ mmi = XCAMEL_MBOX_MESSAGE_INFO (mi);
+
+ offset = camel_message_info_util_bdata_get_number (bdata_ptr, -1);
+ if (offset < 0)
+ return FALSE;
+
+ xcamel_mbox_message_info_set_offset (mmi, offset);
+
+ return TRUE;
+}
+
+static gboolean
+mbox_message_info_save (const xCamelMessageInfo *mi,
+ CamelMIRecord *record,
+ GString *bdata_str)
+{
+ xCamelMboxMessageInfo *mmi;
+
+ g_return_val_if_fail (XCAMEL_IS_MBOX_MESSAGE_INFO (mi), FALSE);
+ g_return_val_if_fail (record != NULL, FALSE);
+ g_return_val_if_fail (bdata_str != NULL, FALSE);
+
+ if (!XCAMEL_MESSAGE_INFO_CLASS (xcamel_mbox_message_info_parent_class)->save ||
+ !XCAMEL_MESSAGE_INFO_CLASS (xcamel_mbox_message_info_parent_class)->save (mi, record, bdata_str))
+ return FALSE;
+
+ mmi = XCAMEL_MBOX_MESSAGE_INFO (mi);
+
+ camel_message_info_util_bdata_put_number (bdata_str, xcamel_mbox_message_info_get_offset (mmi));
+
+ return TRUE;
+}
+
static void
mbox_message_info_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
xCamelMboxMessageInfo *mmi = XCAMEL_MBOX_MESSAGE_INFO (object);
@@ -80,9 +129,9 @@ mbox_message_info_set_property (GObject *object,
static void
mbox_message_info_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
xCamelMboxMessageInfo *mmi = XCAMEL_MBOX_MESSAGE_INFO (object);
@@ -105,6 +154,8 @@ xcamel_mbox_message_info_class_init (xCamelMboxMessageInfoClass *class)
mi_class = XCAMEL_MESSAGE_INFO_CLASS (class);
mi_class->clone = mbox_message_info_clone;
+ mi_class->load = mbox_message_info_load;
+ mi_class->save = mbox_message_info_save;
object_class = G_OBJECT_CLASS (class);
object_class->set_property = mbox_message_info_set_property;
@@ -153,7 +204,7 @@ xcamel_mbox_message_info_get_offset (const xCamelMboxMessageInfo *mmi)
gboolean
xcamel_mbox_message_info_set_offset (xCamelMboxMessageInfo *mmi,
- goffset offset)
+ goffset offset)
{
xCamelMessageInfo *mi;
gboolean changed;
@@ -171,7 +222,7 @@ xcamel_mbox_message_info_set_offset (xCamelMboxMessageInfo *mmi,
xcamel_message_info_property_unlock (mi);
- if (changed) {
+ if (changed && !xcamel_message_info_get_loading (mi)) {
g_object_notify (G_OBJECT (mmi), "offset");
xcamel_message_info_set_dirty (mi, TRUE);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]