[evolution-rss] make displaying of articles asynchronous



commit 1c1957cef824d62d1019cf3669116b2dd49f21c0
Author: Lucian Langa <lucilanga gnome org>
Date:   Thu Apr 7 20:50:50 2011 +0300

    make displaying of articles asynchronous

 src/parser.c          |  108 +++++++++++++++++++++++++++++++++++++++--------
 src/parser.h          |    7 +++-
 src/rss-status-icon.c |  113 ++++++++++++++++++++++++++++++-------------------
 src/rss-status-icon.h |   10 ++++-
 src/rss.c             |   94 ++++++++++++++++++++--------------------
 5 files changed, 220 insertions(+), 112 deletions(-)
---
diff --git a/src/parser.c b/src/parser.c
index 2d7b2a3..844946f 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -44,7 +44,14 @@ extern int rss_verbose_debug;
 #include "misc.h"
 #include "network-soup.h"
 
+typedef struct {
+	RDF *r;
+	GQueue *status_msg;
+} AsyncData;
+
 extern GConfClient *rss_gconf;
+void asyncr_context_free(AsyncData *asyncr);
+GQueue *display_channel_items_sync(AsyncData *ayncr);
 
 /************ RDF Parser *******************/
 
@@ -1217,24 +1224,26 @@ refresh_mail_folder(CamelFolder *mail_folder)
 	camel_folder_thaw(mail_folder);
 }
 
-gchar *
-update_channel(RDF *r)
+GQueue *
+display_channel_items_sync(AsyncData *asyncr)
 {
 	FILE *fr, *fw;
-	guint i;
-	gchar *sender;
-	xmlNodePtr el;
-	gchar *subj;
-	create_feed *CF;
+	RDF *r = asyncr->r;
+	GQueue *status_msg = asyncr->status_msg;
+	GtkWidget *progress = r->progress;
 	gchar *chn_name = r->title;
 	gchar *url = r->uri;
 	GArray *item = r->item;
-	GtkWidget *progress = r->progress;
-	gchar *buf, *safes, *feed_dir, *feed_name;
-	gchar *msg, *safchn;
-	gboolean freeze = FALSE;
 	CamelFolder *mail_folder = NULL;
+	gchar *sender;
+	gboolean freeze = FALSE;
 	gchar *article_uid = NULL;
+	gchar *safes, *feed_dir, *feed_name;
+	gchar *msg, *safchn;
+	create_feed *CF;
+	gchar *subj;
+	xmlNodePtr el;
+	guint i;
 
 	safes = encode_rfc2047(chn_name);
 	safchn = g_strchomp (g_strdup(chn_name));
@@ -1243,19 +1252,18 @@ update_channel(RDF *r)
 	g_free(safes);
 
 	migrate_crc_md5(chn_name, url);
-	buf = gen_md5(url);
+	r->feedid = gen_md5(url);
 	feed_dir = rss_component_peek_base_directory();
 	if (!g_file_test(feed_dir, G_FILE_TEST_EXISTS))
 		g_mkdir_with_parents (feed_dir, 0755);
 
-	feed_name = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", feed_dir, buf);
+	feed_name = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", feed_dir, r->feedid);
 	g_free(feed_dir);
 
 	fr = fopen(feed_name, "r");
 	fw = fopen(feed_name, "a+");
 
 	for (i=0; NULL != (el = g_array_index(item, xmlNodePtr, i)); i++) {
-		update_sr_message();
 		update_progress_text(chn_name);
 		if (rf->cancel || rf->cancel_all || rf->display_cancel)
 			break;
@@ -1279,7 +1287,7 @@ update_channel(RDF *r)
 			r, &article_uid);
 		g_array_append_val(r->uids, article_uid);
 		if (!CF) continue;
-		CF->feedid = g_strdup(buf);
+		CF->feedid = g_strdup(r->feedid);
 		CF->sender = g_strdup(sender);
 		if (r->prefix)
 			CF->full_path = g_build_path(
@@ -1291,7 +1299,6 @@ update_channel(RDF *r)
 		if (!mail_folder) {
 			mail_folder = check_feed_folder(CF->full_path);
 		}
-
 		subj = g_strdup(CF->subj);
 
 		ftotal++;
@@ -1316,11 +1323,12 @@ update_channel(RDF *r)
 
 done:		farticle++;
 		d("put success()\n");
-		update_status_icon(chn_name, subj);
+		update_status_icon_text(status_msg, chn_name, subj);
 		g_free(subj);
 	}
 	if (freeze)
 		refresh_mail_folder(mail_folder);
+
 	if (mail_folder) {
 		if ((rf->import || feed_new)
 		&& (!rf->cancel && !rf->cancel_all && !rf->display_cancel)) {
@@ -1340,7 +1348,71 @@ done:		farticle++;
 	if (fw) fclose(fw);
 
 	g_free(feed_name);
-	return buf;
+	return status_msg;
+}
+
+static void
+display_channel_items_thread (GSimpleAsyncResult *simple,
+	GObject *object,
+	GCancellable *cancellable)
+{
+	AsyncData *asyncr;
+	GError *error = NULL;
+
+	asyncr = g_simple_async_result_get_op_res_gpointer (simple);
+	asyncr->status_msg = display_channel_items_sync(asyncr);
+
+	if (error != NULL) {
+		g_simple_async_result_set_from_error (simple, error);
+		g_error_free (error);
+	}
+}
+
+void
+asyncr_context_free(AsyncData *asyncr)
+{
+	d("free r-> components\n");
+	if (asyncr->r->maindate)
+		g_free(asyncr->r->maindate);
+	g_array_free(asyncr->r->item, TRUE);
+	g_free(asyncr->r->feedid);
+	if (asyncr->r->uids)
+		g_array_free(asyncr->r->uids, TRUE);
+	if (asyncr->r->cache)
+		xmlFreeDoc(asyncr->r->cache);
+	if (asyncr->r->type)
+		g_free(asyncr->r->type);
+	if (asyncr->r->version)
+		g_free(asyncr->r->version);
+	g_free(asyncr->r);
+	g_free(asyncr);
+}
+
+
+void
+display_channel_items (RDF *r,
+	gint io_priority,
+	GCancellable *cancellable,
+	GAsyncReadyCallback callback,
+	gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	AsyncData *data;
+
+	data = g_new0(AsyncData, 1);
+	data->r = r;
+	data->status_msg = user_data;
+
+	simple = g_simple_async_result_new (
+		NULL, callback, user_data, display_channel_items);
+
+	g_simple_async_result_set_op_res_gpointer (
+		simple, data, (GDestroyNotify)asyncr_context_free);
+
+	g_simple_async_result_run_in_thread (
+		simple, display_channel_items_thread, io_priority, cancellable);
+
+	g_object_unref (simple);
 }
 
 gchar *
diff --git a/src/parser.h b/src/parser.h
index 0889355..b52c9db 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -21,7 +21,12 @@
 
 #include <mail/em-format-html.h>
 
-gchar *update_channel(RDF *r);
+void display_channel_items (RDF *r,
+	gint io_priority,
+	GCancellable *cancellable,
+	GAsyncReadyCallback callback,
+	gpointer user_data);
+
 xmlDoc *rss_html_url_decode(const char *html, int len);
 
 const char *layer_find (xmlNodePtr node,
diff --git a/src/rss-status-icon.c b/src/rss-status-icon.c
index 93d77b8..35cd411 100644
--- a/src/rss-status-icon.c
+++ b/src/rss-status-icon.c
@@ -25,10 +25,19 @@
 
 GtkStatusIcon *status_icon = NULL;
 gboolean winstatus;
-gchar *flat_status_msg;
 extern GtkWidget *evo_window;
 extern GQueue *status_msg;
 
+void status_text_free(StatusText *st);
+
+void
+status_text_free(StatusText *st)
+{
+	g_free(st->chn_name);
+	g_free(st->title);
+	g_free(st);
+}
+
 void
 icon_activated (GtkStatusIcon *icon, gpointer pnotify)
 {
@@ -51,6 +60,8 @@ icon_activated (GtkStatusIcon *icon, gpointer pnotify)
 		g_free(folder_name);
 		rss_select_folder(real_name);
 	}
+	g_queue_foreach(status_msg, (GFunc)status_text_free, NULL);
+	status_msg = g_queue_new();
 }
 
 gboolean
@@ -102,19 +113,27 @@ flicker_stop(gpointer user_data)
 	return FALSE;
 }
 
-
 void
-flaten_status(gpointer msg, gpointer user_data)
+flatten_status(StatusText *st, gchar **user_data)
 {
-	if (strlen(msg)) {
-		if (flat_status_msg)
-			flat_status_msg = g_strconcat(
-						flat_status_msg,
-						msg,
+	gchar *temp = NULL;
+	if (strlen(st->chn_name)) {
+		gchar *total;
+		gchar *tchn, *ttit;
+		tchn = g_markup_escape_text (st->chn_name, -1);
+		ttit = g_markup_escape_text (st->title, -1);
+		total = g_strdup_printf("<b>%s</b>\n%s\n", tchn, ttit);
+		g_free(tchn);
+		g_free(ttit);
+		if (*user_data)
+			temp = g_strconcat(
+						*user_data,
+						total,
 						NULL);
 		else
-			flat_status_msg = g_strdup(msg);
+			temp = g_strdup(total);
 	}
+	*user_data = temp;
 }
 
 void
@@ -155,50 +174,56 @@ toggle_window(void)
 }
 
 void
-update_status_icon(const char *channel, gchar *title)
+update_status_icon(GQueue *status)
 {
-	gchar *total;
 	gchar *iconfile;
-	gchar *tchn, *ttit;
-	GConfClient *client = gconf_client_get_default();
-	if (gconf_client_get_bool (client, GCONF_KEY_STATUS_ICON, NULL)) {
-		tchn = g_markup_escape_text (channel, -1);
-		ttit = g_markup_escape_text (title, -1);
-		total = g_strdup_printf("<b>%s</b>\n%s\n", tchn, ttit);
-		g_free(tchn);
-		g_free(ttit);
-		create_status_icon();
-		iconfile = g_build_filename (EVOLUTION_ICONDIR,
+	StatusText *channel;
+	gchar *flat = NULL;
+	if (g_queue_is_empty(status))
+		return;
+	create_status_icon();
+	iconfile = g_build_filename (EVOLUTION_ICONDIR,
 			"rss-icon-unread.png",
 			NULL);
-		gtk_status_icon_set_from_file (
-			status_icon,
-			iconfile);
-		g_free(iconfile);
-		g_queue_push_tail(status_msg, total);
-		if (g_queue_get_length(status_msg) == 6)
-			g_queue_pop_head(status_msg);
-		g_queue_foreach(status_msg, flaten_status, flat_status_msg);
+	gtk_status_icon_set_from_file (
+		status_icon,
+		iconfile);
+	g_free(iconfile);
+	channel = g_queue_peek_tail(status);
+	g_queue_foreach(status, (GFunc)flatten_status, &flat);
+	if (flat)
 #if GTK_CHECK_VERSION (2,16,0)
-		gtk_status_icon_set_tooltip_markup (status_icon, flat_status_msg);
+		gtk_status_icon_set_tooltip_markup (status_icon, flat);
 #else
-		gtk_status_icon_set_tooltip (status_icon, flat_status_msg);
+		gtk_status_icon_set_tooltip (status_icon, flat);
 #endif
 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 22
-		if (gconf_client_get_bool (client, GCONF_KEY_BLINK_ICON, NULL)
-		&& !gtk_status_icon_get_blinking(status_icon))
-			gtk_status_icon_set_blinking (status_icon, TRUE);
-		g_timeout_add(15 * 1000, flicker_stop, NULL);
+	if (gconf_client_get_bool (client, GCONF_KEY_BLINK_ICON, NULL)
+	&& !gtk_status_icon_get_blinking(status_icon))
+		gtk_status_icon_set_blinking (status_icon, TRUE);
+	g_timeout_add(15 * 1000, flicker_stop, NULL);
 #endif
-		gtk_status_icon_set_has_tooltip (status_icon, TRUE);
-		g_object_set_data_full (
-			G_OBJECT (status_icon), "uri",
-			lookup_feed_folder((gchar *)channel),
-			(GDestroyNotify) g_free);
-		g_free(flat_status_msg);
-//		g_free(total);
-		flat_status_msg = NULL;
+	gtk_status_icon_set_has_tooltip (status_icon, TRUE);
+	g_object_set_data_full (
+		G_OBJECT (status_icon), "uri",
+		lookup_feed_folder((gchar *)channel->chn_name),
+		(GDestroyNotify) g_free);
+	g_free(flat);
+}
+
+void
+update_status_icon_text(GQueue *status, const char *channel, gchar *title)
+{
+	StatusText *st = g_new0 (StatusText, 1);
+	st->chn_name = g_strdup(channel);
+	st->title = g_strdup(title);
+	g_queue_push_tail(status, st);
+	if (g_queue_get_length(status) == 6) {
+		StatusText *tmp = g_queue_peek_head(status);
+		g_free(tmp->chn_name);
+		g_free(tmp->title);
+		g_free(tmp);
+		g_queue_pop_head(status);
 	}
-	g_object_unref(client);
 }
 
diff --git a/src/rss-status-icon.h b/src/rss-status-icon.h
index 0fa11fe..54ae7c5 100644
--- a/src/rss-status-icon.h
+++ b/src/rss-status-icon.h
@@ -16,10 +16,16 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
+typedef struct {
+	gchar *chn_name;
+	gchar *title;
+} StatusText;
+
 void icon_activated (GtkStatusIcon *icon, gpointer pnotify);
 gboolean button_press_cb (GtkWidget *widget, GdkEventButton *event, gpointer data);
 void create_status_icon(void);
 gboolean flicker_stop(gpointer user_data);
-void flaten_status(gpointer msg, gpointer user_data);
+void flatten_status(StatusText *st, gchar **user_data);
 void toggle_window(void);
-void update_status_icon(const char *channel, gchar *title);
+void update_status_icon(GQueue *status);
+void update_status_icon_text(GQueue *status_msg, const char *channel, gchar *title);
diff --git a/src/rss.c b/src/rss.c
index 0855d1b..8447327 100644
--- a/src/rss.c
+++ b/src/rss.c
@@ -247,7 +247,6 @@ gboolean browser_fetching = 0;	//mycall event could be triggered
 gint browser_fill = 0;	//how much data currently written to browser
 
 gchar *process_feed(RDF *r);
-gboolean display_feed(RDF *r);
 gchar *display_doc (RDF *r);
 gchar *display_comments (RDF *r, EMFormatHTML *format);
 void check_folders(void);
@@ -1686,7 +1685,8 @@ gecko_click(GtkMozEmbed *mozembed, gpointer dom_event, gpointer user_data)
 	if (button == 2)
 		gtk_menu_popup (
 			GTK_MENU (menu),
-			NULL, NULL, NULL, NULL,
+			NULL, NULL,
+			gtk_status_icon_position_menu, user_data,
 			0, GDK_CURRENT_TIME);
 #else
 	emp = em_popup_new("org.gnome.evolution.mail.formathtmldisplay.popup");
@@ -1703,9 +1703,10 @@ gecko_click(GtkMozEmbed *mozembed, gpointer dom_event, gpointer user_data)
 	menu = e_popup_create_menu_once((EPopup *)emp, NULL, 0);
 
 	if (button == 2)
-		gtk_menu_popup(
-			menu,
-			NULL, NULL, NULL, NULL,
+		gtk_menu_popup (
+			GTK_MENU (menu),
+			NULL, NULL,
+			gtk_status_icon_position_menu, user_data,
 			button,
 			gtk_get_current_event_time());
 #endif
@@ -3139,8 +3140,6 @@ add:
 			store_redraw(GTK_TREE_VIEW(rf->treeview));
 		save_gconf_feed();
 
-//		if (feed->validate && !(rf->import && rf->display_cancel))
-//			display_feed(r);
 		g_idle_add(
 			(GSourceFunc)display_feed_async,
 			g_strdup(chn_name));
@@ -3160,8 +3159,6 @@ add:
 			xmlFreeDoc(r->cache);
 		if (r->type)
 			g_free(r->type);
-		if (r->uids)
-			g_array_free(r->uids, TRUE);
 		if (r)
 			g_free(r);
 		if (content)
@@ -3282,12 +3279,14 @@ setup_feed(add_feed *feed)
 void
 update_sr_message(void)
 {
-	if (flabel && farticle) {
-		gchar *fmsg = g_strdup_printf(
+	gchar *fmsg = NULL;
+	if (G_IS_OBJECT(rf->label) && farticle) {
+		fmsg = g_strdup_printf(
 				_("Getting message %d of %d"),
 				farticle,
 				ftotal);
-		gtk_label_set_text (GTK_LABEL (flabel), fmsg);
+		if (G_IS_OBJECT(rf->label))
+			gtk_label_set_text (GTK_LABEL (rf->label), fmsg);
 		g_free(fmsg);
 	}
 }
@@ -3470,7 +3469,6 @@ generic_finish_feed(rfMessage *msg, gpointer user_data)
 	if (msg->status_code == SOUP_STATUS_CANCELLED)
 		goto out;
 
-
 	response = g_string_new_len(msg->body, msg->length);
 
 	g_print("feed %s\n", (gchar *)user_data);
@@ -3490,15 +3488,15 @@ generic_finish_feed(rfMessage *msg, gpointer user_data)
 			NULL, title, tmsg);
 		g_free(tmsg);
 		g_free(title);
-		goto cleanup;
+		goto out;
 	}
 
 	if (msg->status_code == SOUP_STATUS_CANCELLED)
-		goto cleanup;
+		goto out;
 
 	if (!deleted) {
 		if (!user_data || !lookup_key(user_data))
-			goto cleanup;
+			goto out;
 		r->uri =  g_hash_table_lookup(
 				rf->hr, lookup_key(user_data));
 
@@ -3519,19 +3517,15 @@ generic_finish_feed(rfMessage *msg, gpointer user_data)
 					g_strdup(chn_name));
 				save_gconf_feed();
 				update_ttl(md5, r->ttl);
-				//save_data = user_data;
 				user_data = chn_name;
 			}
 			if (g_hash_table_lookup(rf->hrdel_feed, lookup_key(user_data)))
 				get_feed_age(r, user_data);
 		}
 	}
-	//ftotal+=r->total;
 	update_sr_message();
 	g_string_free(response, 1);
 
-//tout:
-
 	if (rf->sr_feed && !deleted) {
 		gchar *furl = g_markup_printf_escaped(
 				"<b>%s</b>: %s",
@@ -3564,15 +3558,6 @@ generic_finish_feed(rfMessage *msg, gpointer user_data)
 		rf->progress_bar = NULL;
 		rf->info = NULL;
 	}
-cleanup:if (r->cache)
-		xmlFreeDoc(r->cache);
-	if (r->type)
-		g_free(r->type);
-	if (r->version)
-		g_free(r->version);
-	if (r->uids)
-		g_array_free(r->uids, TRUE);
-	g_free(r);
 out:	if (chn_name) { //user_data
 		//not sure why it dies here
 		if (!rf->cancel && !rf->cancel_all)
@@ -4750,9 +4735,6 @@ org_gnome_evolution_rss(void *ep, EMEventTargetSendReceive *t)
 	cancel_button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
 
 	status_label = gtk_label_new (_("Waiting..."));
-//                status_label = e_clipped_label_new (
-//                    "www",
-//                  PANGO_WEIGHT_BOLD, 1.0);
 
 	gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
 	gtk_misc_set_alignment (GTK_MISC (status_label), 0, .5);
@@ -4969,7 +4951,7 @@ e_plugin_lib_enable(EPlugin *ep, int enable)
 #endif
 			rss_soup_init();
 			d("init_gdbus()\n");
-			/*G D-BUS init*/
+			/*GD-BUS init*/
 			init_gdbus ();
 			prepare_hashes();
 			if (gconf_client_get_bool (rss_gconf, GCONF_KEY_STATUS_ICON, NULL))
@@ -5431,7 +5413,7 @@ process_attachments(create_feed *CF)
 		CFL = g_new0(cfl, 1);
 		CFL->url = l->data;
 		CFL->CF = CF;
-		d("attachment file:%s\n", l->data)
+		d("attachment file:%s\n", (gchar *)l->data)
 		CF->attachmentsqueue++;
 		download_unblocking(
 			CFL->url,
@@ -5475,7 +5457,8 @@ finish_attachment (SoupSession *soup_sess,
 		1,
 		user_data->file);
 #endif
-out:	fclose(user_data->file);
+out:	if (user_data->file)
+		fclose(user_data->file);
 
 	rf->enclist = g_list_remove(rf->enclist, user_data->url);
 	if (user_data->CF->attachmentsqueue)
@@ -5549,7 +5532,8 @@ finish_enclosure (SoupSession *soup_sess,
 		1,
 		CFL->file);
 #endif
-out:	fclose(CFL->file);
+out:	if (CFL->file)
+		fclose(CFL->file);
 	CF->efile = CFL->file;
 	CF->enclurl = CF->encl;
 	CF->encl = g_strdup(CFL->name);
@@ -5641,24 +5625,40 @@ process_feed(RDF *r)
 	return NULL;
 }
 
-gboolean
-display_feed(RDF *r)
+typedef struct {
+	RDF *r;
+	GQueue *status_msg;
+} AsyncData;
+
+void
+display_doc_finish (GObject *o, GAsyncResult *result, gpointer user_data);
+
+void
+display_doc_finish (GObject *o, GAsyncResult *result, gpointer user_data)
 {
-	r->feedid = update_channel(r);
-	if (r->maindate)
-		g_free(r->maindate);
-	g_array_free(r->item, TRUE);
-	g_free(r->feedid);
-	return 0;
+	GSimpleAsyncResult *simple;
+	AsyncData *asyncr;
+	GConfClient *client = gconf_client_get_default();
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+	asyncr = g_simple_async_result_get_op_res_gpointer (simple);
+	if (gconf_client_get_bool (client, GCONF_KEY_STATUS_ICON, NULL)) {
+		update_status_icon(asyncr->status_msg);
+	}
+	g_object_unref(client);
 }
 
 gchar *
 display_doc (RDF *r)
 {
 	gchar *title = NULL;
-	if ((title = process_feed(r)))
-		display_feed(r);
-	return title;
+	if ((title = process_feed(r))) {
+		update_sr_message();
+		display_channel_items (r,
+			0,
+			G_PRIORITY_DEFAULT, display_doc_finish, status_msg);
+	}
+	return g_strdup(title);
 }
 
 void delete_oldest_article(CamelFolder *folder, guint unread);



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