[evolution-rss] fix display of feed images, correctly process delete feeds, update feed list on deletion



commit 00ee5a7ddc800ec2610d79a2cf21d0df6c4a6450
Author: Lucian Langa <lucilanga gnome org>
Date:   Tue Jul 28 21:06:06 2009 +0300

    fix display of feed images, correctly process delete feeds, update feed list on deletion

 TODO                     |    3 +-
 src/misc.c               |    6 ++
 src/misc.h               |    1 +
 src/rss-config-factory.c |   23 +++---
 src/rss-config-factory.h |    2 +-
 src/rss.c                |  186 ++++++++++++++++++++++++++++++++++++----------
 6 files changed, 169 insertions(+), 52 deletions(-)
---
diff --git a/TODO b/TODO
index f8e9143..9f9dd3e 100644
--- a/TODO
+++ b/TODO
@@ -38,10 +38,11 @@
 	* gtkhtml does not handle &#xD; construct
 	* switch webkit -> gecko leads to crash on pfree()
 	* show feed icons in send & receive dialog
-	* favicon is not displayed rght after it is fetched
 	* cancel fetching comments when summary display is changed
 	* detect duplicate items by content not by feedid
 	* make gtkhtml rendering non-bloking
  	* check webkit user agent
 	* use ellipsize in web auth dialog
 	* check feed_folders for errors
+	* check rss_delete_feed for race condition when deletion of camel folder
+	* make clist update feed list information
diff --git a/src/misc.c b/src/misc.c
index 1a03e4b..9573fd5 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -49,6 +49,12 @@ print_hash(gpointer key, gpointer value, gpointer user_data)
 {
  	g_print("key:%s, value:%s\n", (gchar *)key, (gchar *)value);
 }
+
+void
+print_hash_int(gpointer key, gpointer value, gpointer user_data)
+{
+ 	g_print("key:%s, value:%d\n", (gchar *)key, (int)value);
+}
  
 void
 free_hash(gpointer key, gpointer value, gpointer user_data)
diff --git a/src/misc.h b/src/misc.h
index a91b9cf..9f1f87f 100644
--- a/src/misc.h
+++ b/src/misc.h
@@ -36,6 +36,7 @@ void header_decode_lwsp(const char **in);
 char *decode_token (const char **in);
 gchar *encode_rfc2047(gchar *str);
 void print_hash(gpointer key, gpointer value, gpointer user_data);
+void print_hash_int(gpointer key, gpointer value, gpointer user_data);
 gboolean feed_is_new(gchar *file_name, gchar *needle);
 void write_feed_status_line(gchar *file, gchar *needle);
 
diff --git a/src/rss-config-factory.c b/src/rss-config-factory.c
index 177a5ee..83b58b5 100644
--- a/src/rss-config-factory.c
+++ b/src/rss-config-factory.c
@@ -107,6 +107,7 @@ typedef struct _setupfeed {
 
 static void feeds_dialog_edit(GtkDialog *d, gpointer data);
 void decorate_import_cookies_fs (gpointer data);
+gboolean store_redrawing = FALSE;
 
 static void
 set_sensitive (GtkCellLayout   *cell_layout,
@@ -316,7 +317,7 @@ construct_list(gpointer key, gpointer value, gpointer user_data)
                 0, g_hash_table_lookup(rf->hre, lookup_key(key)),
                 1, name,
                 2, g_hash_table_lookup(rf->hrt, lookup_key(key)),
-		3, key,
+		3, g_strdup(key),
 		4, full_path,
                 -1);
 	g_free(name);
@@ -657,12 +658,17 @@ create_dialog_add(gchar *url, gchar *feed_text)
 	return feed;
 }
 
-void
+gboolean
 store_redraw(GtkTreeView *data)
 {
-        GtkTreeModel *model = gtk_tree_view_get_model (data);
-	gtk_list_store_clear(GTK_LIST_STORE(model));
-        g_hash_table_foreach(rf->hrname, construct_list, model);
+	if (!store_redrawing) {
+		store_redrawing = 1;
+        	GtkTreeModel *model = gtk_tree_view_get_model (data);
+		gtk_list_store_clear(GTK_LIST_STORE(model));
+        	g_hash_table_foreach(rf->hrname, construct_list, model);
+		store_redrawing = 0;
+	}
+	return FALSE;
 }
 
 ////////////////////
@@ -1681,14 +1687,11 @@ construct_opml_line(gpointer key, gpointer value, gpointer user_data)
         gchar *type = g_hash_table_lookup(rf->hrt, value);
         gchar *url_esc = g_markup_escape_text(url, strlen(url));
         gchar *key_esc = g_markup_escape_text(key, strlen(key));
-	g_print("value:%s\n", g_hash_table_lookup(rf->hrname_r, value));
-	g_print("name:%s\n", g_path_get_dirname(g_hash_table_lookup(rf->hrname_r, value)));
-
 
+#if 0
 CamelFolderInfo *info;
 	CamelStore *store = mail_component_peek_local_store(NULL);
         CamelException ex;
-        gint response;
         guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_FAST;
 
 
@@ -1702,7 +1705,7 @@ CamelFolderInfo *info;
 
 out:
         camel_store_free_folder_info(store, info);
-
+#endif
 
         //gchar *tmp = g_strdup_printf("<outline text=\"%s\" title=\"%s\" type=\"%s\" xmlUrl=\"%s\" htmlUrl=\"%s\"/>\n",
         gchar *tmp = g_strdup_printf("<outline text=\"%s\" title=\"%s\" type=\"rss\" xmlUrl=\"%s\" htmlUrl=\"%s\"/>\n",
diff --git a/src/rss-config-factory.h b/src/rss-config-factory.h
index 722368f..6139174 100644
--- a/src/rss-config-factory.h
+++ b/src/rss-config-factory.h
@@ -21,7 +21,7 @@
 
 #define SQLITE_MAGIC "SQLite format 3"
 
-void store_redraw(GtkTreeView *data);
+gboolean store_redraw(GtkTreeView *data);
 void import_dialog_response(GtkWidget *selector, guint response, gpointer user_data);
 void del_days_cb (GtkWidget *widget, add_feed *data);
 void delete_feed_folder_alloc(gchar *old_name);
diff --git a/src/rss.c b/src/rss.c
index 3a25f03..e4f27e8 100644
--- a/src/rss.c
+++ b/src/rss.c
@@ -214,7 +214,7 @@ finish_image (SoupMessage *msg, CamelStream *user_data);
 #else
 finish_image (SoupSession *soup_sess, SoupMessage *msg, CamelStream *user_data);
 #endif
-static void
+void
 #if LIBSOUP_VERSION < 2003000
 finish_create_image (SoupMessage *msg, gchar *user_data);
 #else
@@ -233,6 +233,27 @@ guint fallback_engine(void);
 gchar *print_comments(gchar *url, gchar *stream);
 static void refresh_cb (GtkWidget *button, EMFormatHTMLPObject *pobject);
 void dup_auth_data(gchar *origurl, gchar *url);
+gboolean display_folder_icon(GtkTreeStore *store, gchar *key);
+
+typedef struct _FEED_IMAGE {
+	gchar *img_file;
+	CamelStream *feed_fs;
+	gchar *key;
+} FEED_IMAGE;
+
+static void
+#if LIBSOUP_VERSION < 2003000
+finish_create_icon (SoupMessage *msg, FEED_IMAGE *user_data);
+#else
+finish_create_icon (SoupSession *soup_sess, SoupMessage *msg, FEED_IMAGE *user_data);
+#endif
+static void
+#if LIBSOUP_VERSION < 2003000
+finish_create_icon_stream (SoupMessage *msg, FEED_IMAGE *user_data);
+#else
+finish_create_icon_stream (SoupSession *soup_sess, SoupMessage *msg, FEED_IMAGE *user_data);
+#endif
+GtkTreeStore *evolution_store = NULL;
 
 /*======================================================================*/
 
@@ -2215,7 +2236,9 @@ out:	return;
 void org_gnome_cooly_folder_icon(void *ep, EMEventTargetCustomIcon *t)
 {
 	static gboolean initialised = FALSE;
+#if (EVOLUTION_VERSION < 22703)
 	GdkPixbuf *icon, *pixbuf;
+#endif
 
 	gchar *main_folder = get_main_folder();
 	if (t->folder_name == NULL 
@@ -2227,45 +2250,42 @@ void org_gnome_cooly_folder_icon(void *ep, EMEventTargetCustomIcon *t)
 	if (!rss_folder)
 		goto out;
 	if (!icons)
-		icons = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+		icons = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
 	gchar *ofolder = g_hash_table_lookup(rf->feed_folders, rss_folder);
 	gchar *key = g_hash_table_lookup(rf->hrname,
 				ofolder ? ofolder : rss_folder);
 	if (!key)
 		goto normal;
 
+	if (!evolution_store)
+		evolution_store = t->store;
+
 #if (EVOLUTION_VERSION >= 22703)
 	if (!(g_hash_table_lookup(icons, key))) {
 #else
 	if (!(icon = g_hash_table_lookup(icons, key))) {
 #endif
   		if (gconf_client_get_bool (rss_gconf, GCONF_KEY_FEED_ICON, NULL)) {
-			gchar *feed_dir = rss_component_peek_base_directory(mail_component_peek());
-        		gchar *feed_file = g_strdup_printf("%s/%s.img", feed_dir, key);
 //        		if (g_file_test(feed_file, G_FILE_TEST_EXISTS)) {
 					// unfortunately e_icon_factory_get_icon return broken image in case of error
 					// we use gdk_pixbuf_new_from_file to test the validity of the image file
-					pixbuf = gdk_pixbuf_new_from_file(feed_file, NULL);
-					if (pixbuf) {
 #if (EVOLUTION_VERSION >= 22703)
-						icon = e_icon_factory_get_icon (feed_file, GTK_ICON_SIZE_DIALOG);
-						g_hash_table_insert(icons, g_strdup(key), GINT_TO_POINTER(1));
-						gtk_icon_theme_add_builtin_icon(key,
-							GTK_ICON_SIZE_INVALID,
-							icon);
-						gtk_tree_store_set(
-                					t->store, t->iter,
-                					COL_STRING_ICON_NAME, key,
-                					-1);
+			if (display_folder_icon(t->store, key))
+				goto out;
 #else
-						icon = e_icon_factory_get_icon (feed_file, E_ICON_SIZE_MENU);
-						g_hash_table_insert(icons, g_strdup(key), icon);
-						g_object_set (t->renderer, "pixbuf", icon, "visible", 1, NULL);
+			gchar *feed_dir = rss_component_peek_base_directory(mail_component_peek());
+			gchar *feed_file = g_strdup_printf("%s/%s.img", feed_dir, key);
+			pixbuf = gdk_pixbuf_new_from_file(feed_file, NULL);
+			g_free(feed_file);
+			g_free(feed_dir);
+
+			if (pixbuf) {
+				icon = e_icon_factory_get_icon (feed_file, E_ICON_SIZE_MENU);
+				g_hash_table_insert(icons, g_strdup(key), icon);
+				g_object_set (t->renderer, "pixbuf", icon, "visible", 1, NULL);
+			} else
+				goto out;
 #endif
-						g_object_unref(pixbuf);
-						goto out;
-					}
-//			}
 		}
 	} else {
 #if (EVOLUTION_VERSION >= 22703)
@@ -3207,11 +3227,11 @@ finish_update_feed_image (SoupSession *soup_sess, SoupMessage *msg, gpointer use
 {
 	xmlChar *icon = NULL;
 	gchar *icon_url = NULL;
+	FEED_IMAGE *fi = NULL;
         gchar *feed_dir = rss_component_peek_base_directory(mail_component_peek());
 	gchar *url = (gchar *)user_data;
 	gchar *key = gen_md5(url);
-        gchar *feed_file = g_strdup_printf("%s/%s.img", feed_dir, key);
-	g_free(key);
+        gchar *img_file = g_strdup_printf("%s/%s.img", feed_dir, key);
         g_free(feed_dir);
 	gchar *urldir = g_path_get_dirname(url);
 	gchar *server = get_server_from_uri(url);
@@ -3246,12 +3266,15 @@ finish_update_feed_image (SoupSession *soup_sess, SoupMessage *msg, gpointer use
 			icon_url = (char *)icon;
 
 		dup_auth_data(url, g_strdup(icon_url));
+		fi = g_new0(FEED_IMAGE, 1);
+		fi->img_file = g_strdup(img_file);
+		fi->key = g_strdup(key);
 		fetch_unblocking(
 			g_strdup(icon_url),
 			textcb,
 			NULL,
-			(gpointer)finish_create_image,
-			g_strdup(feed_file),	// we need to dupe key here
+			(gpointer)finish_create_icon,
+			fi,
 			0,
 //			&err);			// because we might lose it if
 			NULL);
@@ -3259,29 +3282,36 @@ finish_update_feed_image (SoupSession *soup_sess, SoupMessage *msg, gpointer use
                 //              r->image = NULL;
 		icon_url = g_strconcat(urldir, "/favicon.ico", NULL);
 		dup_auth_data(url, g_strdup(icon_url));
+		fi = g_new0(FEED_IMAGE, 1);
+		fi->img_file = g_strdup(img_file);
+		fi->key = g_strdup(key);
 		fetch_unblocking(
 				g_strdup(icon_url),
 				textcb,
 				NULL,
-				(gpointer)finish_create_image,
-				g_strdup(feed_file),	// we need to dupe key here
+				(gpointer)finish_create_icon,
+				fi,
 				0,
 //				&err);			// because we might lose it if
 				NULL);
 		g_free(icon_url);
 		icon_url = g_strconcat(server, "/favicon.ico", NULL);
 		dup_auth_data(url, g_strdup(icon_url));
+		fi = g_new0(FEED_IMAGE, 1);
+		fi->img_file = g_strdup(img_file);
+		fi->key = g_strdup(key);
 		fetch_unblocking(
 				g_strdup(icon_url),
 				textcb,
 				NULL,
-				(gpointer)finish_create_image,
-				g_strdup(feed_file),	// we need to dupe key here
+				(gpointer)finish_create_icon,
+				fi,
 				0,
 //				&err);			// because we might lose it if
 				NULL);
 	}
-	g_free(feed_file);
+	g_free(key);
+	g_free(img_file);
 	g_free(icon_url);
 	g_free(server);
 	g_free(urldir);
@@ -3344,6 +3374,7 @@ update_feed_image(RDF *r)
 {
         GError *err = NULL;
 	gchar *key = gen_md5(r->uri);
+	FEED_IMAGE *fi = g_new0(FEED_IMAGE, 1);
 	gchar *image = r->image;
 	if (!check_update_feed_image(key))
 		goto out;
@@ -3351,17 +3382,20 @@ update_feed_image(RDF *r)
         if (!g_file_test(feed_dir, G_FILE_TEST_EXISTS))
             g_mkdir_with_parents (feed_dir, 0755);
         gchar *feed_file = g_strdup_printf("%s/%s.img", feed_dir, key);
+	d(g_print("feed_image() tmpurl:%s\n", feed_file));
         g_free(feed_dir);
         if (!g_file_test(feed_file, G_FILE_TEST_EXISTS)) {
 	if (image) {		//we need to validate image here with load_pixbuf
 		CamelStream *feed_fs = camel_stream_fs_new_with_name(feed_file,
 			O_RDWR|O_CREAT, 0666);
 		dup_auth_data(r->uri, image);
+		fi->feed_fs = feed_fs;
+		fi->key = g_strdup(key);
                 fetch_unblocking(image,
                                 textcb,
                                 NULL,
-                                (gpointer)finish_image,
-                                feed_fs,
+                                (gpointer)finish_create_icon_stream,
+                                fi,
                                 0,
                                 &err);
                 if (err) {
@@ -3507,9 +3541,12 @@ rss_delete_feed(gchar *full_path, gboolean folder)
 	gchar *tmp;
         CamelStore *store = mail_component_peek_local_store(NULL);
 	gchar *name = extract_main_folder(full_path);
+	g_print("name to delete:%s\n", name);
 	if (!name)
 		return;
-        delete_feed_folder_alloc(lookup_feed_folder(name));
+	gchar *real_name = g_hash_table_lookup(rf->feed_folders, name);
+	if (!real_name)
+		real_name = name;
         camel_exception_init (&ex);
         rss_delete_folders (store, full_path, &ex);
         if (camel_exception_is_set (&ex)) {
@@ -3518,7 +3555,7 @@ rss_delete_feed(gchar *full_path, gboolean folder)
                 camel_exception_clear (&ex);
         }
         //also remove status file
-        gchar *tkey = g_hash_table_lookup(rf->hrname, name);
+        gchar *tkey = g_hash_table_lookup(rf->hrname, real_name);
 	if (!tkey)
 		return;
         gchar *url =  g_hash_table_lookup(rf->hr, tkey);
@@ -3537,8 +3574,10 @@ rss_delete_feed(gchar *full_path, gboolean folder)
         unlink(tmp);
 	g_free(tmp);
 out:	if (folder)
-		remove_feed_hash(name);
+		remove_feed_hash(real_name);
+        delete_feed_folder_alloc(name);
 	g_free(name);
+	g_idle_add(store_redraw, GTK_TREE_VIEW(rf->treeview));
         save_gconf_feed();
 }
 
@@ -4586,20 +4625,87 @@ finish_image (SoupSession *soup_sess, SoupMessage *msg, CamelStream *user_data)
 
 static void
 #if LIBSOUP_VERSION < 2003000
-finish_create_image (SoupMessage *msg, gchar *user_data)
+finish_create_icon (SoupMessage *msg, FEED_IMAGE *user_data)
 #else
-finish_create_image (SoupSession *soup_sess, SoupMessage *msg, gchar *user_data)
+finish_create_icon (SoupSession *soup_sess, SoupMessage *msg, FEED_IMAGE *user_data)
 #endif
 {
-	d(g_print("finish_image(): status:%d, user_data:%s\n", msg->status_code, user_data));
+	d(g_print("finish_image(): status:%d, user_data:%s\n", msg->status_code, user_data->img_file));
 	if (404 != msg->status_code) {
-		CamelStream *feed_fs = camel_stream_fs_new_with_name(user_data,
+		CamelStream *feed_fs = camel_stream_fs_new_with_name(user_data->img_file,
 			O_RDWR|O_CREAT, 0666);
 		finish_image(soup_sess, msg, feed_fs);
+		display_folder_icon(evolution_store, user_data->key);
 	}
+	g_free(user_data->key);
 	g_free(user_data);
 }
 
+static void
+#if LIBSOUP_VERSION < 2003000
+finish_create_icon_stream (SoupMessage *msg, FEED_IMAGE *user_data)
+#else
+finish_create_icon_stream (SoupSession *soup_sess, SoupMessage *msg, FEED_IMAGE *user_data)
+#endif
+{
+	finish_image(soup_sess, msg, user_data->feed_fs);
+	display_folder_icon(evolution_store, user_data->key);
+	g_free(user_data->key);
+	g_free(user_data);
+}
+
+gboolean
+display_folder_icon(GtkTreeStore *tree_store, gchar *key)
+{
+	gchar *feed_dir = rss_component_peek_base_directory(mail_component_peek());
+	gchar *img_file = g_strdup_printf("%s/%s.img", feed_dir, key);
+	GdkPixbuf *icon, *pixbuf;
+	gboolean result = FALSE;
+	GtkTreeIter iter;
+	GtkTreePath *path;
+	GtkTreeRowReference *row;
+	EMFolderTreeModel *mod = (EMFolderTreeModel *)tree_store;
+	struct _EMFolderTreeModelStoreInfo *si;
+	CamelStore *store = mail_component_peek_local_store(NULL);
+	CamelFolder *rss_folder;
+
+	pixbuf = gdk_pixbuf_new_from_file(img_file, NULL);
+
+	if (pixbuf) {
+		gchar *name = g_hash_table_lookup(rf->hrname_r, key);
+		gchar *full_name = g_strdup_printf("%s/%s", get_main_folder(),
+							lookup_feed_folder(name));
+        	rss_folder = camel_store_get_folder (store, full_name, 0, NULL);
+		if (!rss_folder) {
+			g_free(full_name);
+			result = FALSE; 
+			goto out;
+		}
+		icon = e_icon_factory_get_icon (img_file, GTK_ICON_SIZE_DIALOG);
+		g_hash_table_insert(icons, g_strdup(key), GINT_TO_POINTER(1));
+		gtk_icon_theme_add_builtin_icon(key,
+						GTK_ICON_SIZE_INVALID,
+						icon);
+		si = g_hash_table_lookup (mod->store_hash, store);
+		row = g_hash_table_lookup (si->full_hash, full_name);
+		path = gtk_tree_row_reference_get_path (row);
+        	gtk_tree_model_get_iter ((GtkTreeModel *)tree_store, &iter, path);
+		gtk_tree_path_free (path);
+
+		gtk_tree_store_set(
+				tree_store, &iter,
+				COL_STRING_ICON_NAME, key,
+				-1);
+		g_free(full_name);
+		camel_object_unref (rss_folder);
+		g_object_unref(pixbuf);
+		result = TRUE;
+	}
+out:	g_free(img_file);
+	g_free(feed_dir);
+	return result;
+}
+
 #define CAMEL_DATA_CACHE_BITS (6)
 #define CAMEL_DATA_CACHE_MASK ((1<<CAMEL_DATA_CACHE_BITS)-1)
 



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