[Nautilus-list] Icon directory contents caching



Here is a first rough cut at removing all the stats that the icon-factory 
does.

There are a couple of issues. 

First of all, where it used to use gnome_vfs_icon_path_from_filename() i 
now load it manually. This function looks at the files installed in the 
gnome-prefix. It now uses the hardcoded /usr, but it really should use the 
gnome-libs prefix, or otherwise the nautilus prefix.

There is a small change in behaviour. When it can't find an icon in the 
current or default theme, it used to look for icons in the global dir 
/usr/share/pixmap and /usr/share/pixmap/$theme_name. Now it only looks in 
/usr/share/pixmap. Is this a problem? I thought the original behaviour was 
sort of strange.

I didn't change the code for the theme_is_in_user_directory case. Partly 
because of laziness, but partly because that code seems kind of broken.
It always seems to read the default icons from the user directory if 
theme_is_in_user_directory, ignoring default_theme_is_in_user_directory. 
It could be made to work with the cache, simplifying the code, if 
fill_theme_icon_dir_cache() took an theme_is_in_user_directory argument 
and fill_default_icon_dir_cache() took a 
default_theme_is_in_user_directory argument.  

Here is the patch:

Index: nautilus-icon-factory.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-icon-factory.c,v
retrieving revision 1.230
diff -u -p -r1.230 nautilus-icon-factory.c
--- nautilus-icon-factory.c	2001/10/05 23:30:27	1.230
+++ nautilus-icon-factory.c	2001/10/06 02:36:37
@@ -64,6 +64,8 @@
 #include <librsvg/rsvg.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
 
 /* List of suffixes to search when looking for an icon file. */
 static const char *icon_file_name_suffixes[] =
@@ -888,13 +890,190 @@ get_icon_name_for_file (NautilusFile *fi
         }
 }
 
+typedef struct {
+	char *directory;
+	char **files;
+} IconDirCache;
+
+static void
+icon_dir_cache_free (IconDirCache *cache)
+{
+	char **file;
+	
+	g_free (cache->directory);
+	file = cache->files;;
+	while (*file) {
+		g_free (*file);
+		file++;
+	}
+	g_free (cache->files);
+
+	g_free (cache);
+}
+
+static gboolean
+icon_dir_cache_contains (IconDirCache *cache, char *name)
+{
+	char **file;
+	
+	file = cache->files;
+
+	while (*file != NULL) {
+		if (strcmp (*file, name) == 0) {
+			return TRUE;
+		}
+		file++;
+	}
+	
+	return FALSE;
+}
+
+static IconDirCache *
+icon_dir_cache_new (char *dir_name)
+{
+	GPtrArray *names;
+	DIR *dir;
+	struct dirent *dirent;
+	IconDirCache *cache;
+
+	cache = g_new (IconDirCache, 1);
+	cache->directory = g_strdup (dir_name);
+	
+	names = g_ptr_array_new ();
+
+	dir = opendir(dir_name);
+
+	if (dir) {
+		while ((dirent = readdir (dir)) != NULL) {
+			g_ptr_array_add (names, g_strdup (dirent->d_name));
+		}
+		closedir (dir);
+	}
+	g_ptr_array_add (names, NULL);
+	
+	cache->files = (char **) names->pdata;
+	g_ptr_array_free (names, FALSE);
+	
+	return cache;
+}
+
+static char *cached_theme = NULL;
+static IconDirCache *themed_icon_dir_cache = NULL;
+static IconDirCache *default_icon_dir_cache = NULL;
+static GList *global_icon_dir_caches = NULL;
+
+static void
+invalidate_icon_dir_caches (void)
+{
+	GList *l;
+	IconDirCache *cache;
+	
+	g_free (cached_theme);
+	cached_theme = NULL;
+	if (themed_icon_dir_cache) {
+		icon_dir_cache_free (themed_icon_dir_cache);
+		themed_icon_dir_cache = NULL;
+	}
+	
+	if (default_icon_dir_cache) {
+		icon_dir_cache_free (default_icon_dir_cache);
+		default_icon_dir_cache = NULL;
+	}
+	
+	l = global_icon_dir_caches;
+	while (l) {
+		cache = l->data;
+		icon_dir_cache_free (cache);
+		l = l->next;
+	}
+	g_list_free (global_icon_dir_caches);
+	global_icon_dir_caches = NULL;
+}
+
+static void
+fill_theme_icon_dir_cache (const char *theme)
+{
+	char *pixmap_dir;
+	char *theme_dir;
+
+	if (cached_theme && strcmp (theme, cached_theme) == 0) {
+		return;
+	}
+
+	/* Free old cached data */
+	g_free (cached_theme);
+	if (themed_icon_dir_cache) {
+		icon_dir_cache_free (themed_icon_dir_cache);
+	}
+	
+	pixmap_dir = nautilus_get_pixmap_directory ();
+	theme_dir = nautilus_make_path (pixmap_dir, theme);
+
+	cached_theme = g_strdup (theme);
+	themed_icon_dir_cache = icon_dir_cache_new (theme_dir);
+
+	g_free (theme_dir);
+	g_free (pixmap_dir);
+
+}
+
+static void
+fill_default_icon_dir_cache (void)
+{
+	char *pixmap_dir;
+	
+	if (default_icon_dir_cache != NULL) {
+		return;
+	}
+
+	pixmap_dir = nautilus_get_pixmap_directory ();
+	default_icon_dir_cache = icon_dir_cache_new (pixmap_dir);
+	g_free (pixmap_dir);
+}
+
+static void
+fill_global_icon_dir_caches (void)
+{
+	const char *gnome_var;
+	char *dirname;
+	char **paths, **temp_paths;
+	IconDirCache *cache;
+
+	if (global_icon_dir_caches != NULL) {
+		return;
+	}
+
+	gnome_var = g_getenv ("GNOME_PATH");
+
+	if (gnome_var == NULL) {
+		gnome_var = "/usr"; /* FIXME: should be NAUTILUS_PREFIX or better, the gnome prefix? */
+	}
+
+	paths = g_strsplit (gnome_var, ":", 0); 
+
+	for (temp_paths = paths; *temp_paths != NULL; temp_paths++) {
+		dirname = g_strconcat (*temp_paths, "/share/pixmaps", NULL);
+		cache = icon_dir_cache_new (dirname);
+		global_icon_dir_caches = g_list_append (global_icon_dir_caches, cache);
+		g_free (dirname);
+	}
+
+	g_strfreev (paths);
+}
+
+
+
 static char *
 make_full_icon_path (const char *path,
 		     const char *suffix,
+		     const char *theme,
 		     gboolean theme_is_in_user_directory)
 {
 	char *partial_path, *full_path;
 	char *user_directory, *themes_directory;
+	char *themed_icon_name;
+	IconDirCache *cache;
+	GList *l;
 	
 	partial_path = g_strconcat (path, suffix, NULL);
 
@@ -904,21 +1083,50 @@ make_full_icon_path (const char *path,
 
 	/* Build a path for this icon, depending on the theme_is_in_user_directory boolean. */
 	if (theme_is_in_user_directory) {
+		if (theme == NULL) {
+			themed_icon_name = g_strdup (partial_path);
+		} else {
+			themed_icon_name = g_strconcat (theme, "/", partial_path, NULL);
+		}
+		
 		user_directory = nautilus_get_user_directory ();
 		themes_directory = nautilus_make_path (user_directory, "themes");
-		full_path = nautilus_make_path (themes_directory, partial_path);
+		full_path = nautilus_make_path (themes_directory, themed_icon_name);
 		g_free (user_directory);
 		g_free (themes_directory);
+		g_free (themed_icon_name);
 		if (!g_file_exists (full_path)) {
 			g_free (full_path);
 			full_path = NULL;
 		}
 	} else {
-		full_path = nautilus_pixmap_file (partial_path);
+		if (theme != NULL) {
+			fill_theme_icon_dir_cache (theme);
+			cache = themed_icon_dir_cache;
+		} else {
+			fill_default_icon_dir_cache ();
+			cache = default_icon_dir_cache;
+		}
+
+		full_path = NULL;
+		if (icon_dir_cache_contains (cache, partial_path)) {
+			full_path = nautilus_make_path (cache->directory, partial_path);
+		} 
 	}
-	
+
+	/* Didn't find the icon in the current or default theme, lets look for a global icon */
 	if (full_path == NULL) {
-		full_path = gnome_vfs_icon_path_from_filename (partial_path);
+		fill_global_icon_dir_caches ();
+
+		l = global_icon_dir_caches;
+		while (l) {
+			cache = l->data;
+			if (icon_dir_cache_contains (cache, partial_path)) {
+				full_path = nautilus_make_path (cache->directory, partial_path);
+				break;
+			} 
+			l = l->next;
+		}
 	}
 
 	g_free (partial_path);
@@ -969,7 +1177,7 @@ get_themed_icon_file_path (const char *t
 {
 	guint i;
 	gboolean include_size;
-	char *themed_icon_name, *partial_path, *path, *aa_path, *xml_path;
+	char *partial_path, *path, *aa_path, *xml_path;
 	xmlDocPtr doc;
 	xmlNodePtr node;
 	char *size_as_string, *property;
@@ -979,12 +1187,6 @@ get_themed_icon_file_path (const char *t
 	
 	g_assert (icon_name != NULL);
 
-	if (theme_name == NULL || icon_name[0] == '/') {
-		themed_icon_name = g_strdup (icon_name);
-	} else {
-		themed_icon_name = g_strconcat (theme_name, "/", icon_name, NULL);
-	}
-
 	include_size = icon_size != NAUTILUS_ICON_SIZE_STANDARD;
 	factory = get_icon_factory ();
 	
@@ -993,10 +1195,10 @@ get_themed_icon_file_path (const char *t
 		if (include_size && strcasecmp (icon_file_name_suffixes[i], ".svg") != 0) {
 			/* Build a path for this icon. */
 			partial_path = g_strdup_printf ("%s-%u",
-							themed_icon_name,
+							icon_name,
 							icon_size);
 		} else {
-			partial_path = g_strdup (themed_icon_name);
+			partial_path = g_strdup (icon_name);
 		}
 		
 		/* if we're in anti-aliased mode, try for an optimized one first */
@@ -1004,6 +1206,7 @@ get_themed_icon_file_path (const char *t
 			aa_path = g_strconcat (partial_path, "-aa", NULL);
 			path = make_full_icon_path (aa_path,
 						    icon_file_name_suffixes[i],
+						    theme_name,
 						    theme_is_in_user_directory);
 			g_free (aa_path);
 		
@@ -1019,6 +1222,7 @@ get_themed_icon_file_path (const char *t
 						
 		path = make_full_icon_path (partial_path,
 					    icon_file_name_suffixes[i],
+					    theme_name,
 					    theme_is_in_user_directory);
 		g_free (partial_path);
 
@@ -1035,8 +1239,9 @@ get_themed_icon_file_path (const char *t
 	if (path != NULL && details != NULL) {
 		memset (&details->text_rect, 0, sizeof (details->text_rect));
 
-		xml_path = make_full_icon_path (themed_icon_name,
+		xml_path = make_full_icon_path (icon_name,
 						".xml",
+						theme_name,
 						theme_is_in_user_directory);
 
 		doc = xmlParseFile (xml_path);
@@ -1104,7 +1309,6 @@ get_themed_icon_file_path (const char *t
 			path = NULL;
 		}
 	}
-	g_free (themed_icon_name);
 
 	return path;
 }
@@ -1206,6 +1410,8 @@ icon_theme_changed_callback (gpointer us
 	load_thumbnail_frames (get_icon_factory ());	
 	g_free (theme_preference);
 	g_free (icon_theme);
+
+	invalidate_icon_dir_caches ();
 }
 
 static void

/ Alex









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