[gmime] use event listeners to uncache message headers



commit da11b4a11fb4b278c2e8fa96a31cca603cafc684
Author: Jeffrey Stedfast <fejj gnome org>
Date:   Wed Apr 29 07:47:07 2009 -0400

    use event listeners to uncache message headers
    
    2009-04-29  Jeffrey Stedfast  <fejj novell com>
    
    	* gmime/gmime-events.[c,h]: Don't require a GObject owner.
    
    	* gmime/gmime-message.c (g_mime_message_set_mime_part): Add a
    	mime_part_headers_changed listener.
    	(g_mime_message_finalize): Remove the listener.
    	(mime_part_headers_changed): Uncache the message header stream.
    	(message_get_headers): Removed hack.
    	(message_write_to_stream): Same.
    
    	* gmime/gmime-header.c (g_mime_header_list_set_stream): Emit a
    	changed event.
    	(g_mime_header_iter_set_value): Call set_stream() instead of
    	setting the stream to NULL ourselves. Also causes a changed event
    	to be emitted.
    	(g_mime_header_list_prepend): Same.
    	(g_mime_header_list_append): Here too.
    	(g_mime_header_list_set): And here.
    	(g_mime_header_list_remove): Same.
---
 ChangeLog             |   19 +++++++++++++++++++
 gmime/gmime-events.c  |    6 +++---
 gmime/gmime-events.h  |    5 ++---
 gmime/gmime-header.c  |   41 ++++++++++++++++++++++++-----------------
 gmime/gmime-message.c |   42 ++++++++++++++++++++++++++++--------------
 5 files changed, 76 insertions(+), 37 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2259191..2f1e727 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2009-04-29  Jeffrey Stedfast  <fejj novell com>
+
+	* gmime/gmime-message.c (g_mime_message_set_mime_part): Add a
+	mime_part_headers_changed listener.
+	(g_mime_message_finalize): Remove the listener.
+	(mime_part_headers_changed): Uncache the message header stream.
+	(message_get_headers): Removed hack.
+	(message_write_to_stream): Same.
+
+	* gmime/gmime-header.c (g_mime_header_list_set_stream): Emit a
+	changed event.
+	(g_mime_header_iter_set_value): Call set_stream() instead of
+	setting the stream to NULL ourselves. Also causes a changed event
+	to be emitted.
+	(g_mime_header_list_prepend): Same.
+	(g_mime_header_list_append): Here too.
+	(g_mime_header_list_set): And here.
+	(g_mime_header_list_remove): Same.
+
 2009-04-28  Jeffrey Stedfast  <fejj novell com>
 
 	* gmime/gmime-part.c (g_mime_part_get_best_content_encoding): New
diff --git a/gmime/gmime-events.c b/gmime/gmime-events.c
index fcfbbf4..3ce74fa 100644
--- a/gmime/gmime-events.c
+++ b/gmime/gmime-events.c
@@ -57,21 +57,21 @@ event_listener_free (EventListener *listener)
 
 
 struct _GMimeEvent {
-	GObject *owner;
+	gpointer owner;
 	List list;
 };
 
 
 /**
  * g_mime_event_new:
- * @owner: a #GObject; typically the one that will own this event
+ * @owner: a pointer to the object owning this event
  *
  * Creates a new #GMimeEvent context.
  *
  * Returns: a newly allocated #GMimeEvent context.
  **/
 GMimeEvent *
-g_mime_event_new (GObject *owner)
+g_mime_event_new (gpointer owner)
 {
 	GMimeEvent *event;
 	
diff --git a/gmime/gmime-events.h b/gmime/gmime-events.h
index 1755075..4100795 100644
--- a/gmime/gmime-events.h
+++ b/gmime/gmime-events.h
@@ -23,15 +23,14 @@
 #define __GMIME_EVENTS_H__
 
 #include <glib.h>
-#include <glib-object.h>
 
 G_BEGIN_DECLS
 
-typedef void (* GMimeEventCallback) (GObject *sender, gpointer args, gpointer user_data);
+typedef void (* GMimeEventCallback) (gpointer sender, gpointer args, gpointer user_data);
 
 typedef struct _GMimeEvent GMimeEvent;
 
-G_GNUC_INTERNAL GMimeEvent *g_mime_event_new (GObject *owner);
+G_GNUC_INTERNAL GMimeEvent *g_mime_event_new (gpointer owner);
 G_GNUC_INTERNAL void g_mime_event_destroy (GMimeEvent *event);
 
 G_GNUC_INTERNAL void g_mime_event_add (GMimeEvent *event, GMimeEventCallback callback, gpointer user_data);
diff --git a/gmime/gmime-header.c b/gmime/gmime-header.c
index 23e5014..18397ec 100644
--- a/gmime/gmime-header.c
+++ b/gmime/gmime-header.c
@@ -26,10 +26,11 @@
 #include <string.h>
 #include <ctype.h>
 
+#include "gmime-stream-mem.h"
 #include "gmime-common.h"
 #include "gmime-header.h"
+#include "gmime-events.h"
 #include "gmime-utils.h"
-#include "gmime-stream-mem.h"
 
 #include "list.h"
 
@@ -67,6 +68,7 @@ struct _GMimeHeader {
 struct _GMimeHeaderList {
 	GMimeStream *stream;
 	GHashTable *writers;
+	GMimeEvent *changed;
 	GHashTable *hash;
 	guint32 version;
 	List list;
@@ -534,6 +536,7 @@ g_mime_header_list_new (void)
 	headers->hash = g_hash_table_new (g_mime_strcase_hash,
 					  g_mime_strcase_equal);
 	list_init (&headers->list);
+	headers->changed = g_mime_event_new (headers);
 	headers->stream = NULL;
 	headers->version = 0;
 	
@@ -568,6 +571,8 @@ g_mime_header_list_destroy (GMimeHeaderList *headers)
 	if (headers->stream)
 		g_object_unref (headers->stream);
 	
+	g_mime_event_destroy (headers->changed);
+	
 	g_slice_free (GMimeHeaderList, headers);
 }
 
@@ -594,10 +599,7 @@ g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const ch
 	list_append (&headers->list, (ListNode *) header);
 	g_hash_table_replace (headers->hash, header->name, header);
 	
-	if (headers->stream) {
-		g_object_unref (headers->stream);
-		headers->stream = NULL;
-	}
+	g_mime_header_list_set_stream (headers, NULL);
 }
 
 
@@ -625,10 +627,7 @@ g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const cha
 	if (!g_hash_table_lookup (headers->hash, name))
 		g_hash_table_insert (headers->hash, header->name, header);
 	
-	if (headers->stream) {
-		g_object_unref (headers->stream);
-		headers->stream = NULL;
-	}
+	g_mime_header_list_set_stream (headers, NULL);
 }
 
 
@@ -702,10 +701,7 @@ g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *
 		g_hash_table_insert (headers->hash, header->name, header);
 	}
 	
-	if (headers->stream) {
-		g_object_unref (headers->stream);
-		headers->stream = NULL;
-	}
+	g_mime_header_list_set_stream (headers, NULL);
 }
 
 
@@ -749,10 +745,7 @@ g_mime_header_list_remove (GMimeHeaderList *headers, const char *name)
 	list_unlink ((ListNode *) header);
 	g_mime_header_free (header);
 	
-	if (headers->stream) {
-		g_object_unref (headers->stream);
-		headers->stream = NULL;
-	}
+	g_mime_header_list_set_stream (headers, NULL);
 	
 	return TRUE;
 }
@@ -954,6 +947,9 @@ g_mime_header_list_set_stream (GMimeHeaderList *headers, GMimeStream *stream)
 	g_return_if_fail (stream == NULL || GMIME_IS_STREAM (stream));
 	g_return_if_fail (headers != NULL);
 	
+	if (headers->stream == stream)
+		return;
+	
 	if (stream)
 		g_object_ref (stream);
 	
@@ -961,6 +957,8 @@ g_mime_header_list_set_stream (GMimeHeaderList *headers, GMimeStream *stream)
 		g_object_unref (headers->stream);
 	
 	headers->stream = stream;
+	
+	g_mime_event_emit (headers->changed, NULL);
 }
 
 
@@ -979,3 +977,12 @@ g_mime_header_list_get_stream (GMimeHeaderList *headers)
 	
 	return headers->stream;
 }
+
+
+GMimeEvent *
+_g_mime_header_list_get_changed_event (GMimeHeaderList *headers)
+{
+	g_return_val_if_fail (headers != NULL, NULL);
+	
+	return headers->changed;
+}
diff --git a/gmime/gmime-message.c b/gmime/gmime-message.c
index 66e8b4e..720e92f 100644
--- a/gmime/gmime-message.c
+++ b/gmime/gmime-message.c
@@ -46,6 +46,7 @@
  * A #GMimeMessage represents an rfc822 message.
  **/
 
+extern GMimeEvent *_g_mime_header_list_get_changed_event (GMimeHeaderList *headers);
 
 static void g_mime_message_class_init (GMimeMessageClass *klass);
 static void g_mime_message_init (GMimeMessage *message, GMimeMessageClass *klass);
@@ -143,6 +144,13 @@ g_mime_message_class_init (GMimeMessageClass *klass)
 }
 
 static void
+mime_part_headers_changed (GMimeHeaderList *headers, gpointer args, GMimeMessage *message)
+{
+	/* clear the message's header stream */
+	g_mime_header_list_set_stream (((GMimeObject *) message)->headers, NULL);
+}
+
+static void
 connect_changed_event (GMimeMessage *message, GMimeRecipientType type)
 {
 	InternetAddressList *list;
@@ -225,6 +233,7 @@ static void
 g_mime_message_finalize (GObject *object)
 {
 	GMimeMessage *message = (GMimeMessage *) object;
+	GMimeEvent *changed;
 	guint i;
 	
 	g_free (message->from);
@@ -243,8 +252,11 @@ g_mime_message_finalize (GObject *object)
 	g_free (message->message_id);
 	
 	/* unref child mime part */
-	if (message->mime_part)
+	if (message->mime_part) {
+		changed = _g_mime_header_list_get_changed_event (message->mime_part->headers);
+		g_mime_event_remove (changed, (GMimeEventCallback) mime_part_headers_changed, message);
 		g_object_unref (message->mime_part);
+	}
 	
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -943,11 +955,6 @@ message_get_headers (GMimeObject *object)
 		/* if the mime part has raw headers, then it contains the message headers as well */
 		g_mime_header_list_write_to_stream (message->mime_part->headers, stream);
 	} else {
-		/* Note: if the user changed the mime_part's headers,
-		 * we need to unset our cached header stream or it
-		 * won't reflect the changes. */
-		g_mime_header_list_set_stream (object->headers, NULL);
-		
 		g_mime_header_list_write_to_stream (object->headers, stream);
 		if (message->mime_part) {
 			if (g_mime_object_get_header (message->mime_part, "Content-Type"))
@@ -972,11 +979,6 @@ message_write_to_stream (GMimeObject *object, GMimeStream *stream)
 	
 	if (message->mime_part) {
 		if (!g_mime_header_list_get_stream (message->mime_part->headers)) {
-			/* Note: if the user changed the mime_part's headers,
-			 * we need to unset our cached header stream or it
-			 * won't reflect the changes. */
-			g_mime_header_list_set_stream (object->headers, NULL);
-			
 			if ((nwritten = g_mime_header_list_write_to_stream (object->headers, stream)) == -1)
 				return -1;
 			
@@ -1442,17 +1444,29 @@ g_mime_message_get_mime_part (GMimeMessage *message)
 void
 g_mime_message_set_mime_part (GMimeMessage *message, GMimeObject *mime_part)
 {
+	GMimeEvent *changed;
+	
+	g_return_if_fail (mime_part == NULL || GMIME_IS_OBJECT (mime_part));
 	g_return_if_fail (GMIME_IS_MESSAGE (message));
-	g_return_if_fail (GMIME_IS_OBJECT (mime_part));
 	
-	g_object_ref (mime_part);
-	g_mime_header_list_set_stream (mime_part->headers, NULL);
+	if (message->mime_part == mime_part)
+		return;
 	
 	if (message->mime_part) {
+		changed = _g_mime_header_list_get_changed_event (message->mime_part->headers);
+		g_mime_event_remove (changed, (GMimeEventCallback) mime_part_headers_changed, message);
+		
 		g_mime_header_list_set_stream (message->mime_part->headers, NULL);
 		g_object_unref (message->mime_part);
 	}
 	
+	if (mime_part) {
+		changed = _g_mime_header_list_get_changed_event (mime_part->headers);
+		g_mime_header_list_set_stream (mime_part->headers, NULL);
+		g_mime_event_add (changed, (GMimeEventCallback) mime_part_headers_changed, message);
+		g_object_ref (mime_part);
+	}
+	
 	g_mime_header_list_set_stream (((GMimeObject *) message)->headers, NULL);
 	
 	message->mime_part = mime_part;



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