Revision 437e6f11b1b4135556057db73061de861c27c862

sadrul at pidgin.im sadrul at pidgin.im
Wed Apr 4 04:36:36 EDT 2007


o   -----------------------------------------------------------------
|   Revision: 437e6f11b1b4135556057db73061de861c27c862
|   Ancestor: c207c7837fe3e356cf1a6653e950074aaac10658
|   Author: sadrul at pidgin.im
|   Date: 2007-04-04T08:33:50
|   Branch: im.pidgin.pidgin
|   
|   Modified files:
|           finch/libgnt/gntfilesel.c finch/libgnt/gntfilesel.h
|   
|   ChangeLog: 
|   
|   Allow using different methods for reading directory entries.
|   
|   ============================================================
|   --- finch/libgnt/gntfilesel.c	d801f524e90a0c44c22a79c05ac0cce584b501e0
|   +++ finch/libgnt/gntfilesel.c	2e03db8d836c1587e2d25cbd0f1693ae97dbd0d5
|   @@ -11,7 +11,9 @@
|    #include <sys/stat.h>
|    #include <unistd.h>
|    
|   +#if 0
|    #include <glob.h>
|   +#endif
|    
|    enum
|    {
|   @@ -87,12 +89,76 @@ is_tagged(GntFileSel *sel, const char *f
|    	return find;
|    }
|    
|   +GntFile* gnt_file_new_dir(const char *name)
|   +{
|   +	GntFile *file = g_new0(GntFile, 1);
|   +	file->basename = g_strdup(name);
|   +	file->type = GNT_FILE_DIR;
|   +	return file;
|   +}
|   +
|   +GntFile* gnt_file_new(const char *name, unsigned long size)
|   +{
|   +	GntFile *file = g_new0(GntFile, 1);
|   +	file->basename = g_strdup(name);
|   +	file->type = GNT_FILE_REGULAR;
|   +	file->size = size;
|   +	return file;
|   +}
|   +
|    static gboolean
|   -location_changed(GntFileSel *sel, GError **err)
|   +local_read_fn(const char *path, GList **files, GError **error)
|    {
|    	GDir *dir;
|   +	GntFile *file;
|    	const char *str;
|   +	
|   +	dir = g_dir_open(path, 0, error);
|   +	if (dir == NULL || (error && *error)) {
|   +		return FALSE;
|   +	}
|    
|   +	*files = NULL;
|   +	if (*path != '\0' && strcmp(path, G_DIR_SEPARATOR_S)) {
|   +		file = gnt_file_new_dir("..");
|   +		*files = g_list_prepend(*files, file);
|   +	}
|   +
|   +	while ((str = g_dir_read_name(dir)) != NULL) {
|   +		char *fp = g_build_filename(path, str, NULL);
|   +		struct stat st;
|   +
|   +		if (stat(fp, &st)) {
|   +			g_printerr("Error stating location %s\n", fp);
|   +		} else {
|   +			if (S_ISDIR(st.st_mode)) {
|   +				file = gnt_file_new_dir(str);
|   +			} else {
|   +				file = gnt_file_new(str, (long)st.st_size);
|   +			}
|   +			*files = g_list_prepend(*files, file);
|   +		}
|   +		g_free(fp);
|   +	}
|   +
|   +	*files = g_list_reverse(*files);
|   +	return TRUE;
|   +}
|   +
|   +static void
|   +gnt_file_free(GntFile *file)
|   +{
|   +	g_free(file->fullpath);
|   +	g_free(file->basename);
|   +	g_free(file);
|   +}
|   +
|   +static gboolean
|   +location_changed(GntFileSel *sel, GError **err)
|   +{
|   +	GList *files, *iter;
|   +	gboolean success;
|   +
|    	if (!sel->dirs)
|    		return TRUE;
|    
|   @@ -105,42 +171,43 @@ location_changed(GntFileSel *sel, GError
|    			gnt_widget_draw(GNT_WIDGET(sel));
|    		return TRUE;
|    	}
|   +
|   +	/* XXX:\
|   +	 * XXX: This is blocking.
|   +	 * XXX:/
|   +	 */
|   +	files = NULL;
|   +	if (sel->read_fn)
|   +		success = sel->read_fn(sel->current, &files, err);
|   +	else
|   +		success = local_read_fn(sel->current, &files, err);
|    	
|   -	dir = g_dir_open(sel->current, 0, err);
|   -	if (dir == NULL || *err) {
|   +	if (!success || *err) {
|    		g_printerr("GntFileSel: error opening location %s (%s)\n",
|    			sel->current, *err ? (*err)->message : "reason unknown");
|    		return FALSE;
|    	}
|    
|   -	if (*sel->current != '\0' && strcmp(sel->current, G_DIR_SEPARATOR_S))
|   -		gnt_tree_add_row_after(GNT_TREE(sel->dirs), g_strdup(".."),
|   -				gnt_tree_create_row(GNT_TREE(sel->dirs), ".."), NULL, NULL);
|   +	for (iter = files; iter; iter = iter->next) {
|   +		GntFile *file = iter->data;
|   +		char *str = file->basename;
|   +		if (file->type == GNT_FILE_DIR) {
|   +			gnt_tree_add_row_after(GNT_TREE(sel->dirs), g_strdup(str),
|   +					gnt_tree_create_row(GNT_TREE(sel->dirs), str), NULL, NULL);
|   +			if (sel->multiselect && sel->dirsonly && is_tagged(sel, str))
|   +				gnt_tree_set_row_flags(GNT_TREE(sel->dirs), (gpointer)str, GNT_TEXT_FLAG_BOLD);
|   +		} else if (!sel->dirsonly) {
|   +			char size[128];
|   +			snprintf(size, sizeof(size), "%ld", file->size);
|    
|   -	while ((str = g_dir_read_name(dir)) != NULL) {
|   -		char *fp = g_build_filename(sel->current, str, NULL);
|   -		struct stat st;
|   -
|   -		if (stat(fp, &st)) {
|   -			g_printerr("Error stating location %s\n", fp);
|   -		} else {
|   -			if (S_ISDIR(st.st_mode)) {
|   -				gnt_tree_add_row_after(GNT_TREE(sel->dirs), g_strdup(str),
|   -						gnt_tree_create_row(GNT_TREE(sel->dirs), str), NULL, NULL);
|   -				if (sel->multiselect && sel->dirsonly && is_tagged(sel, str))
|   -					gnt_tree_set_row_flags(GNT_TREE(sel->dirs), (gpointer)str, GNT_TEXT_FLAG_BOLD);
|   -			} else if (!sel->dirsonly) {
|   -				char size[128];
|   -				snprintf(size, sizeof(size), "%ld", (long)st.st_size);
|   -
|   -				gnt_tree_add_row_after(GNT_TREE(sel->files), g_strdup(str),
|   -						gnt_tree_create_row(GNT_TREE(sel->files), str, size, ""), NULL, NULL);
|   -				if (sel->multiselect && is_tagged(sel, str))
|   -					gnt_tree_set_row_flags(GNT_TREE(sel->files), (gpointer)str, GNT_TEXT_FLAG_BOLD);
|   -			}
|   +			gnt_tree_add_row_after(GNT_TREE(sel->files), g_strdup(str),
|   +					gnt_tree_create_row(GNT_TREE(sel->files), str, size, ""), NULL, NULL);
|   +			if (sel->multiselect && is_tagged(sel, str))
|   +				gnt_tree_set_row_flags(GNT_TREE(sel->files), (gpointer)str, GNT_TEXT_FLAG_BOLD);
|    		}
|   -		g_free(fp);
|    	}
|   +	g_list_foreach(files, (GFunc)gnt_file_free, NULL);
|   +	g_list_free(files);
|    	if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(sel), GNT_WIDGET_MAPPED))
|    		gnt_widget_draw(GNT_WIDGET(sel));
|    	return TRUE;
|   @@ -151,8 +218,13 @@ dir_key_pressed(GntTree *tree, const cha
|    {
|    	if (strcmp(key, "\r") == 0) {
|    		char *str = g_strdup(gnt_tree_get_selection_data(tree));
|   -		char *path = g_build_filename(sel->current, str, NULL);
|   -		char *dir = g_path_get_basename(sel->current);
|   +		char *path, *dir;
|   +
|   +		if (!str)
|   +			return TRUE;
|   +		
|   +		path = g_build_filename(sel->current, str, NULL);
|   +		dir = g_path_get_basename(sel->current);
|    		if (!gnt_file_sel_set_current_location(sel, path)) {
|    			gnt_tree_set_selected(tree, str);
|    		} else if (strcmp(str, "..") == 0) {
|   @@ -169,64 +241,67 @@ location_key_pressed(GntTree *tree, cons
|    static gboolean
|    location_key_pressed(GntTree *tree, const char *key, GntFileSel *sel)
|    {
|   -	if (strcmp(key, "\r") == 0) {
|   -		int count;
|   -		glob_t gl;
|   -		char *path;
|   -		char *str;
|   -		struct stat st;
|   -		int glob_ret;
|   +	char *path;
|   +	char *str;
|   +#if 0
|   +	int count;
|   +	glob_t gl;
|   +	struct stat st;
|   +	int glob_ret;
|   +#endif
|   +	if (strcmp(key, "\r"))
|   +		return FALSE;
|    
|   -		str = (char*)gnt_entry_get_text(GNT_ENTRY(sel->location));
|   -		if (*str == G_DIR_SEPARATOR)
|   -			path = g_strdup(str);
|   -		else
|   -			path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", sel->current, str);
|   -		str = process_path(path);
|   -		g_free(path);
|   -		path = str;
|   +	str = (char*)gnt_entry_get_text(GNT_ENTRY(sel->location));
|   +	if (*str == G_DIR_SEPARATOR)
|   +		path = g_strdup(str);
|   +	else
|   +		path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", sel->current, str);
|   +	str = process_path(path);
|   +	g_free(path);
|   +	path = g_path_get_dirname(str);
|   +	g_free(str);
|    
|   -		if (!stat(path, &st)) {
|   -			if (S_ISDIR(st.st_mode)) {
|   -				gnt_file_sel_set_current_location(sel, path);
|   -				goto success;
|   -			}
|   -		}
|   +	if (!gnt_file_sel_set_current_location(sel, path)) {
|   +		g_free(path);
|   +		return FALSE;
|   +	}
|   +#if 0
|   +	/* XXX: there needs to be a way to allow other methods for globbing,
|   +	 * like the read_fn stuff. */
|   +	glob_ret = glob(path, GLOB_MARK, NULL, &gl);
|   +	if (!glob_ret) {  /* XXX: do something with the return value */
|   +		char *loc = g_path_get_dirname(gl.gl_pathv[0]);
|    
|   -		glob_ret = glob(path, GLOB_MARK, NULL, &gl);
|   -		if (!glob_ret) {  /* XXX: do something with the return value */
|   -			char *loc = g_path_get_dirname(gl.gl_pathv[0]);
|   -
|   -			stat(gl.gl_pathv[0], &st);
|   -			gnt_file_sel_set_current_location(sel, loc);  /* XXX: check the return value */
|   -			g_free(loc);
|   -			if (!S_ISDIR(st.st_mode) && !sel->dirsonly) {
|   -				gnt_tree_remove_all(GNT_TREE(sel->files));
|   -				for (count = 0; count < gl.gl_pathc; count++) {
|   -					char *tmp = process_path(gl.gl_pathv[count]);
|   -					loc = g_path_get_dirname(tmp);
|   -					if (g_utf8_collate(sel->current, loc) == 0) {
|   -						char *base = g_path_get_basename(tmp);
|   -						char size[128];
|   -						snprintf(size, sizeof(size), "%ld", (long)st.st_size);
|   -						gnt_tree_add_row_after(GNT_TREE(sel->files), base,
|   -								gnt_tree_create_row(GNT_TREE(sel->files), base, size, ""), NULL, NULL);
|   -					}
|   -					g_free(loc);
|   -					g_free(tmp);
|   +		stat(gl.gl_pathv[0], &st);
|   +		gnt_file_sel_set_current_location(sel, loc);  /* XXX: check the return value */
|   +		g_free(loc);
|   +		if (!S_ISDIR(st.st_mode) && !sel->dirsonly) {
|   +			gnt_tree_remove_all(GNT_TREE(sel->files));
|   +			for (count = 0; count < gl.gl_pathc; count++) {
|   +				char *tmp = process_path(gl.gl_pathv[count]);
|   +				loc = g_path_get_dirname(tmp);
|   +				if (g_utf8_collate(sel->current, loc) == 0) {
|   +					char *base = g_path_get_basename(tmp);
|   +					char size[128];
|   +					snprintf(size, sizeof(size), "%ld", (long)st.st_size);
|   +					gnt_tree_add_row_after(GNT_TREE(sel->files), base,
|   +							gnt_tree_create_row(GNT_TREE(sel->files), base, size, ""), NULL, NULL);
|    				}
|   -				gnt_widget_draw(sel->files);
|   +				g_free(loc);
|   +				g_free(tmp);
|    			}
|   -		} else if (sel->files) {
|   -			gnt_tree_remove_all(GNT_TREE(sel->files));
|    			gnt_widget_draw(sel->files);
|    		}
|   -		globfree(&gl);
|   -success:
|   -		g_free(path);
|   -		return TRUE;
|   +	} else if (sel->files) {
|   +		gnt_tree_remove_all(GNT_TREE(sel->files));
|   +		gnt_widget_draw(sel->files);
|    	}
|   -	return FALSE;
|   +	globfree(&gl);
|   +success:
|   +#endif
|   +	g_free(path);
|   +	return TRUE;
|    }
|    
|    static void
|   @@ -329,6 +404,24 @@ clear_tags(GntBindable *bind, GList *nul
|    	return TRUE;
|    }
|    
|   +static gboolean
|   +up_directory(GntBindable *bind, GList *null)
|   +{
|   +	char *path, *dir;
|   +	GntFileSel *sel = GNT_FILE_SEL(bind);
|   +	if (!gnt_widget_has_focus(sel->dirs) &&
|   +			!gnt_widget_has_focus(sel->files))
|   +		return FALSE;
|   +
|   +	path = g_build_filename(sel->current, "..", NULL);
|   +	dir = g_path_get_basename(sel->current);
|   +	if (gnt_file_sel_set_current_location(sel, path))
|   +		gnt_tree_set_selected(GNT_TREE(sel->dirs), dir);
|   +	g_free(dir);
|   +	g_free(path);
|   +	return TRUE;
|   +}
|   +
|    static void
|    gnt_file_sel_class_init(GntFileSelClass *klass)
|    {
|   @@ -350,6 +443,7 @@ gnt_file_sel_class_init(GntFileSelClass 
|    
|    	gnt_bindable_class_register_action(bindable, "toggle-tag", toggle_tag_selection, "t", NULL);
|    	gnt_bindable_class_register_action(bindable, "clear-tags", clear_tags, "c", NULL);
|   +	gnt_bindable_class_register_action(bindable, "up-directory", up_directory, GNT_KEY_BACKSPACE, NULL);
|    	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
|    
|    	GNTDEBUG;
|   @@ -505,3 +599,9 @@ GList *gnt_file_sel_get_selected_multi_f
|    	return list;
|    }
|    
|   +void gnt_file_sel_set_read_fn(GntFileSel *sel, gboolean (*read_fn)(const char *path, GList **files, GError **error))
|   +{
|   +	sel->read_fn = read_fn;
|   +}
|   +
|   +
|   ============================================================
|   --- finch/libgnt/gntfilesel.h	f8ef0ccc30968d6335477df5db8bb59193adea8a
|   +++ finch/libgnt/gntfilesel.h	4c9b6fadb1111c4208a44cc5e7a1af7cae1511f5
|   @@ -20,6 +20,7 @@ typedef struct _GntFileSelClass		GntFile
|    typedef struct _GntFileSel			GntFileSel;
|    typedef struct _GntFileSelPriv		GntFileSelPriv;
|    typedef struct _GntFileSelClass		GntFileSelClass;
|   +typedef struct _GntFile             GntFile;
|    
|    struct _GntFileSel
|    {
|   @@ -39,6 +40,8 @@ struct _GntFileSel
|    	gboolean dirsonly;   /* Show only directories */
|        gboolean multiselect;
|        GList *tags;         /* List of tagged files when multiselect is set */
|   +
|   +	gboolean (*read_fn)(const char *path, GList **files, GError **error);
|    };
|    
|    struct _GntFileSelClass
|   @@ -52,6 +55,20 @@ struct _GntFileSelClass
|    	void (*gnt_reserved4)(void);
|    };
|    
|   +typedef enum _GntFileType
|   +{
|   +	GNT_FILE_REGULAR,
|   +	GNT_FILE_DIR
|   +} GntFileType;
|   +
|   +struct _GntFile
|   +{
|   +	char *fullpath;
|   +	char *basename;
|   +	GntFileType type;
|   +	unsigned long size;
|   +};
|   +
|    G_BEGIN_DECLS
|    
|    GType gnt_file_sel_get_gtype(void);
|   @@ -76,6 +93,12 @@ void gnt_file_sel_set_suggested_filename
|    
|    void gnt_file_sel_set_suggested_filename(GntFileSel *sel, const char *suggest);
|    
|   +void gnt_file_sel_set_read_fn(GntFileSel *sel, gboolean (*read_fn)(const char *path, GList **files, GError **error));
|   +
|   +GntFile* gnt_file_new(const char *name, unsigned long size);
|   +
|   +GntFile* gnt_file_new_dir(const char *name);
|   +
|    G_END_DECLS
|    
|    #endif /* GNT_FILE_SEL_H */

To get the patch for this revision, please do this:
mtn log --last 1 --diffs --from 437e6f11b1b4135556057db73061de861c27c862


More information about the Commits mailing list