Re: Patch: add header flag "calendar"



El vie, 18-12-2009 a las 13:04 +0100, Philip Van Hoof escribió:
> On Fri, 2009-12-18 at 12:36 +0100, José Dapena Paz wrote:
> 
> > 	Then we need to find a different way. The approach taken in camel is
> > storing this kind of information in the user flags, which is not
> > supported in camel lite (and also, not exposed in any way to tinymail).
> > As far as I remember, this is one of the things removed to keep small
> > tinymail/camel-lite folder summary storage.
> > 
> > 	Or we can just add the user flags in this way:
> > 	* CamelMessageInfo: same API
> > 	* Add API to TnyHeader to get/set these flags
> > 	* Add a way to know the degree of support for these flags in the header
> > (no support, only memory storage, both memory and persistent storage).
> > 
> > 	void tny_header_set_user_flag (TnyHeader *header, const gchar *name, gboolean flag)
> > 	void tny_header_get_user_flags (TnyHeader *header, TnyList *flags);
> > 
> > 	TnyHeaderSupportFlagsType tny_header_support_user_flags (TnyHeader *header);
> > 	^----- How could this be better implemented? :m
> > 
> > 	Same for camel. We recover the userflags field. By default we would
> > only support storage in memory, and we could allow to set in some way if
> > support is also available to storage in disk. This info would be stored
> > in the CamelFolderSummary. This way, if we have (as we have now) some
> > provider that don't use the camel-lite summary, and provides special
> > flags, we could add access to it.
> 
> 
> This sounds good to me

	This patch implements the proposal for user flags. Finally it's a bit
different: we have a method tny_header_get_user_flag, and no way to
retrieve all the available headers. This is just to mimic the behavior
of the camel backend.

	Also, default implementation in camel is not persistent (and then, no
changes in summary format). But other backends may implement persistent
storage or some or all user flags.

	Attached is the patch implementation.


> 
> 


-- 
José Dapena Paz <jdapena igalia com>
Igalia
diff --git a/libtinymail-camel/camel-lite/camel/camel-folder-summary.c b/libtinymail-camel/camel-lite/camel/camel-folder-summary.c
index 228c768..a5db51c 100644
--- a/libtinymail-camel/camel-lite/camel/camel-folder-summary.c
+++ b/libtinymail-camel/camel-lite/camel/camel-folder-summary.c
@@ -2373,6 +2373,8 @@ message_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h)
 	if (mi->date_sent <= 0)
 		mi->date_sent = time (NULL);
 
+	mi->user_flags = NULL;
+
 	msgid = camel_header_msgid_decode(camel_header_raw_find(&h, "message-id", NULL));
 	if (msgid) {
 		md5_get_digest(msgid, strlen(msgid), digest);
@@ -3600,8 +3602,8 @@ static CamelMessageInfo *
 message_info_clone(CamelFolderSummary *s, const CamelMessageInfo *mi)
 {
 	CamelMessageInfoBase *to, *from = (CamelMessageInfoBase *)mi;
-#ifdef NON_TINYMAIL_FEATURES
 	CamelFlag *flag;
+#ifdef NON_TINYMAIL_FEATURES
 	CamelTag *tag;
 #endif
 	to = (CamelMessageInfoBase *)camel_message_info_new(s);
@@ -3632,13 +3634,13 @@ message_info_clone(CamelFolderSummary *s, const CamelMessageInfo *mi)
 	}
 #endif
 
-#ifdef NON_TINYMAIL_FEATURES
 	flag = from->user_flags;
 	while (flag) {
 		camel_flag_set(&to->user_flags, flag->name, TRUE);
 		flag = flag->next;
 	}
 
+#ifdef NON_TINYMAIL_FEATURES
 	tag = from->user_tags;
 	while (tag) {
 		camel_tag_set(&to->user_tags, tag->name, tag->value);
@@ -3771,7 +3773,11 @@ info_time(const CamelMessageInfo *mi, int id)
 static gboolean
 info_user_flag(const CamelMessageInfo *mi, const char *id)
 {
-	return FALSE;
+	if (g_strcmp0 (id, CAMEL_MESSAGE_INFO_SUPPORT_FLAGS_ANY_USER_FLAG) == 0) {
+		return TRUE;
+	} else {
+		return camel_flag_get(&((CamelMessageInfoBase *)mi)->user_flags, id);
+	}
 }
 
 static const char *
@@ -4013,9 +4019,7 @@ info_set_user_flag(CamelMessageInfo *info, const char *name, gboolean value)
 
 	g_static_rec_mutex_lock (&global_lock);
 
-#ifdef NON_TINYMAIL_FEATURES
 	res = camel_flag_set(&mi->user_flags, name, value);
-#endif
 
 	/* TODO: check this item is still in the summary first */
 	if (mi->summary && res && mi->summary->folder && mi->uid) {
diff --git a/libtinymail-camel/camel-lite/camel/camel-folder-summary.h b/libtinymail-camel/camel-lite/camel/camel-folder-summary.h
index 1ae0211..83d4094 100644
--- a/libtinymail-camel/camel-lite/camel/camel-folder-summary.h
+++ b/libtinymail-camel/camel-lite/camel/camel-folder-summary.h
@@ -33,6 +33,11 @@
 #define CAMEL_FOLDER_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_folder_summary_get_type (), CamelFolderSummaryClass)
 #define CAMEL_IS_FOLDER_SUMMARY(obj)      CAMEL_CHECK_TYPE (obj, camel_folder_summary_get_type ())
 
+#define CAMEL_MESSAGE_INFO_SUPPORT_FLAGS_ANY_USER_FLAG "__message_info_support_flags_any"
+#define CAMEL_MESSAGE_INFO_SUPPORT_FLAGS_SOME_USER_FLAG "__message_info_support_flags_some"
+#define CAMEL_MESSAGE_INFO_SUPPORT_PERMANENT_FLAGS_ANY_USER_FLAG "__message_info_support_permanent_flags_any"
+#define CAMEL_MESSAGE_INFO_SUPPORT_PERMANENT_FLAGS_SOME_USER_FLAG "__message_info_support_permanent_flags_some"
+
 G_BEGIN_DECLS
 
 struct _CamelFolder;
@@ -99,6 +104,7 @@ typedef enum _CamelMessageFlags {
 /* Changes to system flags will NOT trigger a folder changed event */
 #define CAMEL_MESSAGE_SYSTEM_MASK (0x1fff << 12)
 
+
 typedef struct _CamelFlag {
 	struct _CamelFlag *next;
 	char name[1];		/* name allocated as part of the structure */
@@ -179,7 +185,8 @@ struct _CamelMessageInfoBase {
 	time_t date_sent;                  /* 4 bytes */
 	time_t date_received;              /* 4 bytes */
 
-                                          /* 56 bytes */
+        struct _CamelFlag *user_flags;     /* 4 bytes */
+                                          /* 60 bytes */
 };
 
 
diff --git a/libtinymail-camel/tny-camel-bs-msg-header.c b/libtinymail-camel/tny-camel-bs-msg-header.c
index 3cdf0b5..1aae700 100644
--- a/libtinymail-camel/tny-camel-bs-msg-header.c
+++ b/libtinymail-camel/tny-camel-bs-msg-header.c
@@ -146,6 +146,30 @@ tny_camel_bs_msg_header_unset_flag (TnyHeader *self, TnyHeaderFlags mask)
 	return;
 }
 
+static gboolean
+tny_camel_bs_msg_header_get_user_flag (TnyHeader *self, const gchar *id)
+{
+	return FALSE;
+}
+
+static void
+tny_camel_bs_msg_header_set_user_flag (TnyHeader *self, const gchar *id)
+{
+	return;
+}
+
+static void
+tny_camel_bs_msg_header_unset_user_flag (TnyHeader *self, const gchar *id)
+{
+	return;
+}
+
+static gboolean
+tny_camel_bs_msg_header_support_user_flags (TnyHeader *self)
+{
+	return TNY_HEADER_SUPPORT_FLAGS_NONE;
+}
+
 static time_t
 tny_camel_bs_msg_header_get_date_received (TnyHeader *self)
 {
@@ -265,6 +289,10 @@ tny_header_init (gpointer g, gpointer iface_data)
 	klass->set_flag= tny_camel_bs_msg_header_set_flag;
 	klass->unset_flag= tny_camel_bs_msg_header_unset_flag;
 	klass->get_flags= tny_camel_bs_msg_header_get_flags;
+	klass->set_user_flag= tny_camel_bs_msg_header_set_user_flag;
+	klass->unset_user_flag= tny_camel_bs_msg_header_unset_user_flag;
+	klass->get_user_flag= tny_camel_bs_msg_header_get_user_flag;
+	klass->support_user_flags = tny_camel_bs_msg_header_support_user_flags;
 
 	return;
 }
diff --git a/libtinymail-camel/tny-camel-header.c b/libtinymail-camel/tny-camel-header.c
index 8c33257..d62ea17 100644
--- a/libtinymail-camel/tny-camel-header.c
+++ b/libtinymail-camel/tny-camel-header.c
@@ -202,6 +202,51 @@ tny_camel_header_unset_flag (TnyHeader *self, TnyHeaderFlags mask)
 	return;
 }
 
+static gboolean
+tny_camel_header_get_user_flag (TnyHeader *self, const gchar *id)
+{
+	TnyCamelHeader *me = TNY_CAMEL_HEADER (self);
+	gboolean retval;
+
+	retval = camel_message_info_user_flag (me->info, id);
+
+	return retval;
+}
+
+static void
+tny_camel_header_set_user_flag (TnyHeader *self, const gchar *id)
+{
+	TnyCamelHeader *me = TNY_CAMEL_HEADER (self);
+
+	camel_message_info_set_user_flag (me->info, id, TRUE);
+}
+
+static void
+tny_camel_header_unset_user_flag (TnyHeader *self, const gchar *id)
+{
+	TnyCamelHeader *me = TNY_CAMEL_HEADER (self);
+
+	camel_message_info_set_user_flag (me->info, id, FALSE);
+}
+
+static TnyHeaderSupportFlags
+tny_camel_header_support_user_flags (TnyHeader *self)
+{
+	TnyCamelHeader *me = TNY_CAMEL_HEADER (self);
+	TnyHeaderSupportFlags flags = TNY_HEADER_SUPPORT_FLAGS_NONE;
+
+	if (camel_message_info_user_flag (me->info, CAMEL_MESSAGE_INFO_SUPPORT_FLAGS_ANY_USER_FLAG))
+		flags |= TNY_HEADER_SUPPORT_FLAGS_ANY;
+	if (camel_message_info_user_flag (me->info, CAMEL_MESSAGE_INFO_SUPPORT_FLAGS_SOME_USER_FLAG))
+		flags |= TNY_HEADER_SUPPORT_FLAGS_SOME;
+	if (camel_message_info_user_flag (me->info, CAMEL_MESSAGE_INFO_SUPPORT_PERMANENT_FLAGS_ANY_USER_FLAG))
+		flags |= TNY_HEADER_SUPPORT_PERSISTENT_FLAGS_ANY;
+	if (camel_message_info_user_flag (me->info, CAMEL_MESSAGE_INFO_SUPPORT_PERMANENT_FLAGS_SOME_USER_FLAG))
+		flags |= TNY_HEADER_SUPPORT_PERSISTENT_FLAGS_SOME;
+
+	return flags;
+}
+
 static time_t
 tny_camel_header_get_date_received (TnyHeader *self)
 {
@@ -383,6 +428,10 @@ tny_header_init (gpointer g, gpointer iface_data)
 	klass->set_flag= tny_camel_header_set_flag;
 	klass->unset_flag= tny_camel_header_unset_flag;
 	klass->get_flags= tny_camel_header_get_flags;
+	klass->set_user_flag = tny_camel_header_set_user_flag;
+	klass->get_user_flag = tny_camel_header_get_user_flag;
+	klass->unset_user_flag = tny_camel_header_unset_user_flag;
+	klass->support_user_flags = tny_camel_header_support_user_flags;
 
 	return;
 }
diff --git a/libtinymail-camel/tny-camel-msg-header.c b/libtinymail-camel/tny-camel-msg-header.c
index e5067e5..608d250 100644
--- a/libtinymail-camel/tny-camel-msg-header.c
+++ b/libtinymail-camel/tny-camel-msg-header.c
@@ -298,6 +298,54 @@ tny_camel_msg_header_unset_flag (TnyHeader *self, TnyHeaderFlags mask)
 	return;
 }
 
+static void
+tny_camel_msg_header_set_user_flag (TnyHeader *self, const gchar *id)
+{
+	TnyCamelMsgHeader *me = TNY_CAMEL_MSG_HEADER (self);
+
+	if (me->decorated) {
+		tny_header_set_user_flag (me->decorated, id);
+	}
+
+	return;
+}
+
+static void
+tny_camel_msg_header_unset_user_flag (TnyHeader *self, const gchar *id)
+{
+	TnyCamelMsgHeader *me = TNY_CAMEL_MSG_HEADER (self);
+
+	if (me->decorated) {
+		tny_header_unset_user_flag (me->decorated, id);
+	}
+
+	return;
+}
+
+static gboolean
+tny_camel_msg_header_get_user_flag (TnyHeader *self, const gchar *id)
+{
+	TnyCamelMsgHeader *me = TNY_CAMEL_MSG_HEADER (self);
+
+	if (me->decorated) {
+		return tny_header_get_user_flag (me->decorated, id);
+	} else {
+		return FALSE;
+	}
+}
+
+static TnyHeaderSupportFlags
+tny_camel_msg_header_support_user_flags (TnyHeader *self)
+{
+	TnyCamelMsgHeader *me = TNY_CAMEL_MSG_HEADER (self);
+
+	if (me->decorated) {
+		return tny_header_support_user_flags (me->decorated);
+	} else {
+		return TNY_HEADER_SUPPORT_FLAGS_NONE;
+	}
+}
+
 static time_t
 tny_camel_msg_header_get_date_received (TnyHeader *self)
 {
@@ -564,6 +612,10 @@ tny_header_init (gpointer g, gpointer iface_data)
 	klass->set_flag= tny_camel_msg_header_set_flag;
 	klass->unset_flag= tny_camel_msg_header_unset_flag;
 	klass->get_flags= tny_camel_msg_header_get_flags;
+	klass->set_user_flag= tny_camel_msg_header_set_user_flag;
+	klass->unset_user_flag= tny_camel_msg_header_unset_user_flag;
+	klass->get_user_flag= tny_camel_msg_header_get_user_flag;
+	klass->support_user_flags= tny_camel_msg_header_support_user_flags;
 
 	return;
 }
diff --git a/libtinymail/tny-expunged-header.c b/libtinymail/tny-expunged-header.c
index b84f75d..16d4e99 100644
--- a/libtinymail/tny-expunged-header.c
+++ b/libtinymail/tny-expunged-header.c
@@ -145,6 +145,28 @@ tny_expunged_header_unset_flag (TnyHeader *self, TnyHeaderFlags mask)
 {
 }
 
+static gboolean
+tny_expunged_header_get_user_flag (TnyHeader *self, const gchar *id)
+{
+	return FALSE;
+}
+
+static void
+tny_expunged_header_set_user_flag (TnyHeader *self, const gchar *id)
+{
+}
+
+static void
+tny_expunged_header_unset_user_flag (TnyHeader *self, const gchar *id)
+{
+}
+
+static TnyHeaderSupportFlags
+tny_expunged_header_support_user_flags (TnyHeader *self)
+{
+	return TNY_HEADER_SUPPORT_FLAGS_NONE;
+}
+
 static void
 tny_expunged_header_finalize (GObject *object)
 {
@@ -180,6 +202,10 @@ tny_header_init (TnyHeaderIface *klass)
 	klass->get_flags= tny_expunged_header_get_flags;
 	klass->set_flag= tny_expunged_header_set_flag;
 	klass->unset_flag= tny_expunged_header_unset_flag;
+	klass->get_user_flag= tny_expunged_header_get_user_flag;
+	klass->set_user_flag= tny_expunged_header_set_user_flag;
+	klass->unset_user_flag= tny_expunged_header_unset_user_flag;
+	klass->support_user_flags= tny_expunged_header_support_user_flags;
 }
 
 static void
diff --git a/libtinymail/tny-header.c b/libtinymail/tny-header.c
index af43582..6dfda97 100644
--- a/libtinymail/tny-header.c
+++ b/libtinymail/tny-header.c
@@ -532,6 +532,76 @@ tny_header_set_flag (TnyHeader *self, TnyHeaderFlags mask)
 }
 
 /**
+ * tny_header_set_user_flag:
+ * @self: a #TnyHeader
+ * @name: name of the flag to set
+ * 
+ * Set as %TRUE the user flag with name @name.
+ *
+ * since: 1.0
+ * audience: application-developer
+ **/
+void 
+tny_header_set_user_flag (TnyHeader *self, const gchar *name)
+{
+#ifdef DBC /* require */
+	g_assert (TNY_IS_HEADER (self));
+	g_assert (TNY_HEADER_GET_IFACE (self)->set_user_flag!= NULL);
+#endif
+
+	TNY_HEADER_GET_IFACE (self)->set_user_flag(self, name);
+
+	return;
+}
+
+/**
+ * tny_header_unset_user_flag:
+ * @self: a #TnyHeader
+ * @name: name of the flag to unset
+ * 
+ * Set as %FALSE (not set) the user flag with name @name. This is
+ * the same as removing the flag.
+ *
+ * since: 1.0
+ * audience: application-developer
+ **/
+void 
+tny_header_unset_user_flag (TnyHeader *self, const gchar *name)
+{
+#ifdef DBC /* require */
+	g_assert (TNY_IS_HEADER (self));
+	g_assert (TNY_HEADER_GET_IFACE (self)->unset_user_flag!= NULL);
+#endif
+
+	TNY_HEADER_GET_IFACE (self)->unset_user_flag(self, name);
+
+	return;
+}
+
+/**
+ * tny_header_get_user_flag:
+ * @self: a #TnyHeader
+ * @name: name of the flag
+ * 
+ * Get if a user flag with name @name is set.
+ *
+ * Returns: %TRUE if flag is set, %FALSE otherwise
+ *
+ * since: 1.0
+ * audience: application-developer
+ **/
+gboolean 
+tny_header_get_user_flag (TnyHeader *self, const gchar *name)
+{
+#ifdef DBC /* require */
+	g_assert (TNY_IS_HEADER (self));
+	g_assert (TNY_HEADER_GET_IFACE (self)->get_user_flag!= NULL);
+#endif
+
+	return TNY_HEADER_GET_IFACE (self)->get_user_flag(self, name);
+}
+
+/**
  * tny_header_get_priority:
  * @self: a #TnyHeader
  * 
@@ -610,6 +680,26 @@ tny_header_unset_flag (TnyHeader *self, TnyHeaderFlags mask)
 	return;
 }
 
+/**
+ * tny_header_support_user_flags:
+ * @self: a #TnyHeader
+ *
+ * Tells if user flags are supported in this header. It depends mostly on the
+ * provider implementation.
+ *
+ * since: 1.0
+ * audience: application-developer
+ **/
+TnyHeaderSupportFlags
+tny_header_support_user_flags (TnyHeader *self)
+{
+#ifdef DBC /* require */
+	g_assert (TNY_IS_HEADER (self));
+	g_assert (TNY_HEADER_GET_IFACE (self)->support_user_flags!= NULL);
+#endif
+
+	return TNY_HEADER_GET_IFACE (self)->support_user_flags (self);
+}
 
 static void
 tny_header_base_init (gpointer g_class)
@@ -694,3 +784,34 @@ tny_header_flags_get_type (void)
 	g_once (&once, tny_header_flags_register_type, NULL);
 	return GPOINTER_TO_UINT (once.retval);
 }
+
+static gpointer
+tny_header_support_flags_register_type (gpointer notused)
+{
+	GType etype = 0;
+	static const GFlagsValue values[] = {
+		{ TNY_HEADER_SUPPORT_FLAGS_NONE, "TNY_HEADER_SUPPORT_FLAGS_NONE", "none" },
+		{ TNY_HEADER_SUPPORT_FLAGS_ANY, "TNY_HEADER_SUPPORT_FLAGS_ANY", "any" },
+		{ TNY_HEADER_SUPPORT_FLAGS_SOME, "TNY_HEADER_SUPPORT_FLAGS_SOME", "some" },
+		{ TNY_HEADER_SUPPORT_PERSISTENT_FLAGS_ANY, "TNY_HEADER_SUPPORT_PERSISTENT_FLAGS_ANY", "persistent_any" },
+		{ TNY_HEADER_SUPPORT_PERSISTENT_FLAGS_SOME, "TNY_HEADER_SUPPORT_PERSISTENT_FLAGS_SOME", "persistent_some" },
+		{ 0, NULL, NULL }
+	};
+	etype = g_flags_register_static ("TnyHeaderSupportFlags", values);
+	return GUINT_TO_POINTER (etype);
+}
+
+/**
+ * tny_header_support_flags_get_type:
+ *
+ * GType system helper function
+ *
+ * returns: a #GType
+ **/
+GType
+tny_header_support_flags_get_type (void)
+{
+	static GOnce once = G_ONCE_INIT;
+	g_once (&once, tny_header_support_flags_register_type, NULL);
+	return GPOINTER_TO_UINT (once.retval);
+}
diff --git a/libtinymail/tny-header.h b/libtinymail/tny-header.h
index ddd73a3..ea078fd 100644
--- a/libtinymail/tny-header.h
+++ b/libtinymail/tny-header.h
@@ -44,6 +44,7 @@ G_BEGIN_DECLS
 #define TNY_HEADER_GET_IFACE(inst)  (G_TYPE_INSTANCE_GET_INTERFACE ((inst), TNY_TYPE_HEADER, TnyHeaderIface))
 
 #define TNY_TYPE_HEADER_FLAGS (tny_header_flags_get_type())
+#define TNY_TYPE_HEADER_SUPPORT_FLAGS (tny_header_support_flags_get_type ())
 
 #ifndef TNY_SHARED_H
 typedef struct _TnyHeader TnyHeader;
@@ -70,6 +71,14 @@ typedef enum
 
 #define TNY_HEADER_FLAG_PRIORITY_MASK (1<<9|1<<10)
 
+typedef enum
+{
+	TNY_HEADER_SUPPORT_FLAGS_NONE = 0,
+	TNY_HEADER_SUPPORT_FLAGS_ANY = 1<<0,
+	TNY_HEADER_SUPPORT_FLAGS_SOME = 1<<1,
+	TNY_HEADER_SUPPORT_PERSISTENT_FLAGS_ANY = 1<<2,
+	TNY_HEADER_SUPPORT_PERSISTENT_FLAGS_SOME = 1<<3,
+} TnyHeaderSupportFlags;
 
 struct _TnyHeaderIface
 {
@@ -96,10 +105,15 @@ struct _TnyHeaderIface
 	TnyHeaderFlags (*get_flags) (TnyHeader *self);
 	void (*set_flag) (TnyHeader *self, TnyHeaderFlags mask);
 	void (*unset_flag) (TnyHeader *self, TnyHeaderFlags mask);
+	gboolean (*get_user_flag) (TnyHeader *self, const gchar *id);
+	void (*set_user_flag) (TnyHeader *self, const gchar *id);
+	void (*unset_user_flag) (TnyHeader *self, const gchar *id);
+	TnyHeaderSupportFlags (*support_user_flags) (TnyHeader *self);
 };
 
 GType tny_header_get_type (void);
 GType tny_header_flags_get_type (void);
+GType tny_header_support_flags_get_type (void);
 
 gchar* tny_header_dup_uid (TnyHeader *self);
 gchar* tny_header_dup_bcc (TnyHeader *self);
@@ -122,6 +136,10 @@ TnyFolder* tny_header_get_folder (TnyHeader *self);
 TnyHeaderFlags tny_header_get_flags (TnyHeader *self);
 void tny_header_set_flag (TnyHeader *self, TnyHeaderFlags mask);
 void tny_header_unset_flag (TnyHeader *self, TnyHeaderFlags mask);
+void tny_header_set_user_flag (TnyHeader *self, const gchar *name);
+void tny_header_unset_user_flag (TnyHeader *self, const gchar *name);
+gboolean tny_header_get_user_flag (TnyHeader *self, const gchar *name);
+TnyHeaderSupportFlags tny_header_support_user_flags (TnyHeader *self);
 
 TnyHeaderFlags tny_header_get_priority (TnyHeader *self);
 void tny_header_set_priority (TnyHeader *self, TnyHeaderFlags priority);


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