Compare commits
	
		
			No commits in common. "c64686480500cbcd744f029f4bd5bd5d3003e989" and "44f2f5d4f52fd64e84d3e26588ac74ce4601758c" have entirely different histories.
		
	
	
		
			c646864805
			...
			44f2f5d4f5
		
	
		
							
								
								
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							| @ -1,4 +1,4 @@ | |||||||
| Copyright (c) 2021 - 2023, Přemysl Eric Janouch <p@janouch.name> | Copyright (c) 2021 - 2022, Přemysl Eric Janouch <p@janouch.name> | ||||||
| 
 | 
 | ||||||
| Permission to use, copy, modify, and/or distribute this software for any | Permission to use, copy, modify, and/or distribute this software for any | ||||||
| purpose with or without fee is hereby granted. | purpose with or without fee is hereby granted. | ||||||
|  | |||||||
							
								
								
									
										200
									
								
								fiv-io.c
									
									
									
									
									
								
							
							
						
						
									
										200
									
								
								fiv-io.c
									
									
									
									
									
								
							| @ -3052,14 +3052,6 @@ model_entry_finalize(FivIoModelEntry *entry) | |||||||
| 	g_free(entry->collate_key); | 	g_free(entry->collate_key); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static GArray * |  | ||||||
| model_entry_array_new(void) |  | ||||||
| { |  | ||||||
| 	GArray *a = g_array_new(FALSE, TRUE, sizeof(FivIoModelEntry)); |  | ||||||
| 	g_array_set_clear_func(a, (GDestroyNotify) model_entry_finalize); |  | ||||||
| 	return a; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct _FivIoModel { | struct _FivIoModel { | ||||||
| 	GObject parent_instance; | 	GObject parent_instance; | ||||||
| 	GPatternSpec **supported_patterns; | 	GPatternSpec **supported_patterns; | ||||||
| @ -3159,16 +3151,23 @@ model_compare(gconstpointer a, gconstpointer b, gpointer user_data) | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static gboolean | static void | ||||||
| model_reload_to(FivIoModel *self, GFile *directory, | model_resort(FivIoModel *self) | ||||||
| 	GArray *subdirs, GArray *files, GError **error) |  | ||||||
| { | { | ||||||
| 	if (subdirs) | 	g_array_sort_with_data(self->subdirs, model_compare, self); | ||||||
| 		g_array_set_size(subdirs, 0); | 	g_array_sort_with_data(self->files, model_compare, self); | ||||||
| 	if (files) |  | ||||||
| 		g_array_set_size(files, 0); |  | ||||||
| 
 | 
 | ||||||
| 	GFileEnumerator *enumerator = g_file_enumerate_children(directory, | 	g_signal_emit(self, model_signals[FILES_CHANGED], 0); | ||||||
|  | 	g_signal_emit(self, model_signals[SUBDIRECTORIES_CHANGED], 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static gboolean | ||||||
|  | model_reload(FivIoModel *self, GError **error) | ||||||
|  | { | ||||||
|  | 	g_array_set_size(self->subdirs, 0); | ||||||
|  | 	g_array_set_size(self->files, 0); | ||||||
|  | 
 | ||||||
|  | 	GFileEnumerator *enumerator = g_file_enumerate_children(self->directory, | ||||||
| 		G_FILE_ATTRIBUTE_STANDARD_TYPE "," | 		G_FILE_ATTRIBUTE_STANDARD_TYPE "," | ||||||
| 		G_FILE_ATTRIBUTE_STANDARD_NAME "," | 		G_FILE_ATTRIBUTE_STANDARD_NAME "," | ||||||
| 		G_FILE_ATTRIBUTE_STANDARD_TARGET_URI "," | 		G_FILE_ATTRIBUTE_STANDARD_TARGET_URI "," | ||||||
| @ -3176,8 +3175,12 @@ model_reload_to(FivIoModel *self, GFile *directory, | |||||||
| 		G_FILE_ATTRIBUTE_TIME_MODIFIED "," | 		G_FILE_ATTRIBUTE_TIME_MODIFIED "," | ||||||
| 		G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, | 		G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, | ||||||
| 		G_FILE_QUERY_INFO_NONE, NULL, error); | 		G_FILE_QUERY_INFO_NONE, NULL, error); | ||||||
| 	if (!enumerator) | 	if (!enumerator) { | ||||||
|  | 		// Note that this has had a side-effect of clearing all entries.
 | ||||||
|  | 		g_signal_emit(self, model_signals[FILES_CHANGED], 0); | ||||||
|  | 		g_signal_emit(self, model_signals[SUBDIRECTORIES_CHANGED], 0); | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	GFileInfo *info = NULL; | 	GFileInfo *info = NULL; | ||||||
| 	GFile *child = NULL; | 	GFile *child = NULL; | ||||||
| @ -3189,20 +3192,12 @@ model_reload_to(FivIoModel *self, GFile *directory, | |||||||
| 			g_clear_error(&e); | 			g_clear_error(&e); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		if (!info) | 		if (!info) | ||||||
| 			break; | 			break; | ||||||
| 		if (self->filtering && g_file_info_get_is_hidden(info)) | 		if (self->filtering && g_file_info_get_is_hidden(info)) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		GArray *target = NULL; |  | ||||||
| 		if (g_file_info_get_file_type(info) == G_FILE_TYPE_DIRECTORY) |  | ||||||
| 			target = subdirs; |  | ||||||
| 		else if (!self->filtering || |  | ||||||
| 			model_supports(self, g_file_info_get_name(info))) |  | ||||||
| 			target = files; |  | ||||||
| 		if (!target) |  | ||||||
| 			continue; |  | ||||||
| 
 |  | ||||||
| 		FivIoModelEntry entry = {.uri = g_file_get_uri(child), | 		FivIoModelEntry entry = {.uri = g_file_get_uri(child), | ||||||
| 			.target_uri = g_strdup(g_file_info_get_attribute_string( | 			.target_uri = g_strdup(g_file_info_get_attribute_string( | ||||||
| 				info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI))}; | 				info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI))}; | ||||||
| @ -3219,148 +3214,21 @@ model_reload_to(FivIoModel *self, GFile *directory, | |||||||
| 		entry.collate_key = g_utf8_collate_key_for_filename(parse_name, -1); | 		entry.collate_key = g_utf8_collate_key_for_filename(parse_name, -1); | ||||||
| 		g_free(parse_name); | 		g_free(parse_name); | ||||||
| 
 | 
 | ||||||
| 		g_array_append_val(target, entry); | 		const char *name = g_file_info_get_name(info); | ||||||
|  | 		if (g_file_info_get_file_type(info) == G_FILE_TYPE_DIRECTORY) | ||||||
|  | 			g_array_append_val(self->subdirs, entry); | ||||||
|  | 		else if (!self->filtering || model_supports(self, name)) | ||||||
|  | 			g_array_append_val(self->files, entry); | ||||||
|  | 		else | ||||||
|  | 			model_entry_finalize(&entry); | ||||||
| 	} | 	} | ||||||
| 	g_object_unref(enumerator); | 	g_object_unref(enumerator); | ||||||
| 
 | 
 | ||||||
| 	if (subdirs) | 	// We also emit change signals there, indirectly.
 | ||||||
| 		g_array_sort_with_data(subdirs, model_compare, self); | 	model_resort(self); | ||||||
| 	if (files) |  | ||||||
| 		g_array_sort_with_data(files, model_compare, self); |  | ||||||
| 	return TRUE; | 	return TRUE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static gboolean |  | ||||||
| model_reload(FivIoModel *self, GError **error) |  | ||||||
| { |  | ||||||
| 	// Note that this will clear all entries on failure.
 |  | ||||||
| 	gboolean result = model_reload_to( |  | ||||||
| 		self, self->directory, self->subdirs, self->files, error); |  | ||||||
| 
 |  | ||||||
| 	g_signal_emit(self, model_signals[FILES_CHANGED], 0); |  | ||||||
| 	g_signal_emit(self, model_signals[SUBDIRECTORIES_CHANGED], 0); |  | ||||||
| 	return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| model_resort(FivIoModel *self) |  | ||||||
| { |  | ||||||
| 	g_array_sort_with_data(self->subdirs, model_compare, self); |  | ||||||
| 	g_array_sort_with_data(self->files, model_compare, self); |  | ||||||
| 
 |  | ||||||
| 	g_signal_emit(self, model_signals[FILES_CHANGED], 0); |  | ||||||
| 	g_signal_emit(self, model_signals[SUBDIRECTORIES_CHANGED], 0); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 |  | ||||||
| 
 |  | ||||||
| // This would be more efficient iteratively, but it's not that important.
 |  | ||||||
| static GFile * |  | ||||||
| model_last_deep_subdirectory(FivIoModel *self, GFile *directory) |  | ||||||
| { |  | ||||||
| 	GFile *result = NULL; |  | ||||||
| 	GArray *subdirs = model_entry_array_new(); |  | ||||||
| 	if (!model_reload_to(self, directory, subdirs, NULL, NULL)) |  | ||||||
| 		goto out; |  | ||||||
| 
 |  | ||||||
| 	if (subdirs->len) { |  | ||||||
| 		GFile *last = g_file_new_for_uri( |  | ||||||
| 			g_array_index(subdirs, FivIoModelEntry, subdirs->len - 1).uri); |  | ||||||
| 		result = model_last_deep_subdirectory(self, last); |  | ||||||
| 		g_object_unref(last); |  | ||||||
| 	} else { |  | ||||||
| 		result = g_object_ref(directory); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| out: |  | ||||||
| 	g_array_free(subdirs, TRUE); |  | ||||||
| 	return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| GFile * |  | ||||||
| fiv_io_model_get_previous_directory(FivIoModel *self) |  | ||||||
| { |  | ||||||
| 	g_return_val_if_fail(FIV_IS_IO_MODEL(self), NULL); |  | ||||||
| 
 |  | ||||||
| 	GFile *parent_directory = g_file_get_parent(self->directory); |  | ||||||
| 	if (!parent_directory) |  | ||||||
| 		return NULL; |  | ||||||
| 
 |  | ||||||
| 	GFile *result = NULL; |  | ||||||
| 	GArray *subdirs = model_entry_array_new(); |  | ||||||
| 	if (!model_reload_to(self, parent_directory, subdirs, NULL, NULL)) |  | ||||||
| 		goto out; |  | ||||||
| 
 |  | ||||||
| 	for (gsize i = 0; i < subdirs->len; i++) { |  | ||||||
| 		GFile *file = g_file_new_for_uri( |  | ||||||
| 			g_array_index(subdirs, FivIoModelEntry, i).uri); |  | ||||||
| 		if (g_file_equal(file, self->directory)) { |  | ||||||
| 			g_object_unref(file); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		g_clear_object(&result); |  | ||||||
| 		result = file; |  | ||||||
| 	} |  | ||||||
| 	if (result) { |  | ||||||
| 		GFile *last = model_last_deep_subdirectory(self, result); |  | ||||||
| 		g_object_unref(result); |  | ||||||
| 		result = last; |  | ||||||
| 	} else { |  | ||||||
| 		result = g_object_ref(parent_directory); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| out: |  | ||||||
| 	g_object_unref(parent_directory); |  | ||||||
| 	g_array_free(subdirs, TRUE); |  | ||||||
| 	return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // This would be more efficient iteratively, but it's not that important.
 |  | ||||||
| static GFile * |  | ||||||
| model_next_directory_within_parents(FivIoModel *self, GFile *directory) |  | ||||||
| { |  | ||||||
| 	GFile *parent_directory = g_file_get_parent(directory); |  | ||||||
| 	if (!parent_directory) |  | ||||||
| 		return NULL; |  | ||||||
| 
 |  | ||||||
| 	GFile *result = NULL; |  | ||||||
| 	GArray *subdirs = model_entry_array_new(); |  | ||||||
| 	if (!model_reload_to(self, parent_directory, subdirs, NULL, NULL)) |  | ||||||
| 		goto out; |  | ||||||
| 
 |  | ||||||
| 	gboolean found_self = FALSE; |  | ||||||
| 	for (gsize i = 0; i < subdirs->len; i++) { |  | ||||||
| 		result = g_file_new_for_uri( |  | ||||||
| 			g_array_index(subdirs, FivIoModelEntry, i).uri); |  | ||||||
| 		if (found_self) |  | ||||||
| 			goto out; |  | ||||||
| 
 |  | ||||||
| 		found_self = g_file_equal(result, directory); |  | ||||||
| 		g_clear_object(&result); |  | ||||||
| 	} |  | ||||||
| 	if (!result) |  | ||||||
| 		result = model_next_directory_within_parents(self, parent_directory); |  | ||||||
| 
 |  | ||||||
| out: |  | ||||||
| 	g_object_unref(parent_directory); |  | ||||||
| 	g_array_free(subdirs, TRUE); |  | ||||||
| 	return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| GFile * |  | ||||||
| fiv_io_model_get_next_directory(FivIoModel *self) |  | ||||||
| { |  | ||||||
| 	g_return_val_if_fail(FIV_IS_IO_MODEL(self), NULL); |  | ||||||
| 
 |  | ||||||
| 	if (self->subdirs->len) { |  | ||||||
| 		return g_file_new_for_uri( |  | ||||||
| 			g_array_index(self->subdirs, FivIoModelEntry, 0).uri); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return model_next_directory_within_parents(self, self->directory); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| @ -3480,8 +3348,12 @@ fiv_io_model_init(FivIoModel *self) | |||||||
| 		self->supported_patterns[n] = g_pattern_spec_new(globs[n]); | 		self->supported_patterns[n] = g_pattern_spec_new(globs[n]); | ||||||
| 	g_strfreev(globs); | 	g_strfreev(globs); | ||||||
| 
 | 
 | ||||||
| 	self->files = model_entry_array_new(); | 	self->files = g_array_new(FALSE, TRUE, sizeof(FivIoModelEntry)); | ||||||
| 	self->subdirs = model_entry_array_new(); | 	self->subdirs = g_array_new(FALSE, TRUE, sizeof(FivIoModelEntry)); | ||||||
|  | 	g_array_set_clear_func( | ||||||
|  | 		self->subdirs, (GDestroyNotify) model_entry_finalize); | ||||||
|  | 	g_array_set_clear_func( | ||||||
|  | 		self->files, (GDestroyNotify) model_entry_finalize); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| gboolean | gboolean | ||||||
|  | |||||||
							
								
								
									
										5
									
								
								fiv-io.h
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								fiv-io.h
									
									
									
									
									
								
							| @ -130,11 +130,6 @@ gboolean fiv_io_model_open(FivIoModel *self, GFile *directory, GError **error); | |||||||
| /// There is no ownership transfer, and the object may be NULL.
 | /// There is no ownership transfer, and the object may be NULL.
 | ||||||
| GFile *fiv_io_model_get_location(FivIoModel *self); | GFile *fiv_io_model_get_location(FivIoModel *self); | ||||||
| 
 | 
 | ||||||
| /// Returns the previous VFS directory in order, or NULL.
 |  | ||||||
| GFile *fiv_io_model_get_previous_directory(FivIoModel *self); |  | ||||||
| /// Returns the next VFS directory in order, or NULL.
 |  | ||||||
| GFile *fiv_io_model_get_next_directory(FivIoModel *self); |  | ||||||
| 
 |  | ||||||
| typedef struct { | typedef struct { | ||||||
| 	gchar *uri;                         ///< GIO URI
 | 	gchar *uri;                         ///< GIO URI
 | ||||||
| 	gchar *target_uri;                  ///< GIO URI for any target
 | 	gchar *target_uri;                  ///< GIO URI for any target
 | ||||||
|  | |||||||
							
								
								
									
										35
									
								
								fiv.c
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								fiv.c
									
									
									
									
									
								
							| @ -120,10 +120,8 @@ static struct key_group help_keys_browser[] = { | |||||||
| 	{"General: Navigation", help_keys_navigation}, | 	{"General: Navigation", help_keys_navigation}, | ||||||
| 	{"General: View", help_keys_view}, | 	{"General: View", help_keys_view}, | ||||||
| 	{"Navigation", (struct key[]) { | 	{"Navigation", (struct key[]) { | ||||||
| 		{"<Alt>Home", "Go home"}, |  | ||||||
| 		{"<Alt>Up", "Go to parent directory"}, | 		{"<Alt>Up", "Go to parent directory"}, | ||||||
| 		{"bracketleft", "Go to previous directory in tree"}, | 		{"<Alt>Home", "Go home"}, | ||||||
| 		{"bracketright", "Go to next directory in tree"}, |  | ||||||
| 		{"Return", "Open selected item"}, | 		{"Return", "Open selected item"}, | ||||||
| 		{"<Alt>Return", "Show file information"}, | 		{"<Alt>Return", "Show file information"}, | ||||||
| 		{} | 		{} | ||||||
| @ -1090,30 +1088,6 @@ on_view_drag_data_received(G_GNUC_UNUSED GtkWidget *widget, | |||||||
| 	g_strfreev(uris); | 	g_strfreev(uris); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void |  | ||||||
| on_dir_previous(void) |  | ||||||
| { |  | ||||||
| 	GFile *directory = fiv_io_model_get_previous_directory(g.model); |  | ||||||
| 	if (directory) { |  | ||||||
| 		gchar *uri = g_file_get_uri(directory); |  | ||||||
| 		g_object_unref(directory); |  | ||||||
| 		load_directory(uri); |  | ||||||
| 		g_free(uri); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| on_dir_next(void) |  | ||||||
| { |  | ||||||
| 	GFile *directory = fiv_io_model_get_next_directory(g.model); |  | ||||||
| 	if (directory) { |  | ||||||
| 		gchar *uri = g_file_get_uri(directory); |  | ||||||
| 		g_object_unref(directory); |  | ||||||
| 		load_directory(uri); |  | ||||||
| 		g_free(uri); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void | static void | ||||||
| on_toolbar_zoom(G_GNUC_UNUSED GtkButton *button, gpointer user_data) | on_toolbar_zoom(G_GNUC_UNUSED GtkButton *button, gpointer user_data) | ||||||
| { | { | ||||||
| @ -1448,13 +1422,6 @@ on_key_press_browser_paned(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event, | |||||||
| 				!gtk_widget_is_visible(g.browser_sidebar)); | 				!gtk_widget_is_visible(g.browser_sidebar)); | ||||||
| 			return TRUE; | 			return TRUE; | ||||||
| 
 | 
 | ||||||
| 		case GDK_KEY_bracketleft: |  | ||||||
| 			on_dir_previous(); |  | ||||||
| 			return TRUE; |  | ||||||
| 		case GDK_KEY_bracketright: |  | ||||||
| 			on_dir_next(); |  | ||||||
| 			return TRUE; |  | ||||||
| 
 |  | ||||||
| 		case GDK_KEY_Escape: | 		case GDK_KEY_Escape: | ||||||
| 			fiv_browser_select(FIV_BROWSER(g.browser), NULL); | 			fiv_browser_select(FIV_BROWSER(g.browser), NULL); | ||||||
| 			return TRUE; | 			return TRUE; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user