diff src/collect-io.c @ 138:71e1ebee420e

replaced gchar* path with FileData *fd
author nadvornik
date Tue, 11 Sep 2007 20:06:29 +0000
parents ebbff299ad0d
children f6e307c7bad6
line wrap: on
line diff
--- a/src/collect-io.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/collect-io.c	Tue Sep 11 20:06:29 2007 +0000
@@ -18,6 +18,7 @@
 #include "rcfile.h"
 #include "thumb.h"
 #include "ui_fileops.h"
+#include "filelist.h"
 
 
 #define GQVIEW_COLLECTION_MARKER "#GQview"
@@ -25,8 +26,14 @@
 #define GQVIEW_COLLECTION_FAIL_MIN     300
 #define GQVIEW_COLLECTION_FAIL_PERCENT 98
 
+typedef struct _CollectManagerEntry CollectManagerEntry;
 
 static void collection_load_thumb_step(CollectionData *cd);
+static gint collection_save_private(CollectionData *cd, const gchar *path);
+
+static CollectManagerEntry *collect_manager_get_entry(const gchar *path);
+static void collect_manager_entry_reset(CollectManagerEntry *entry);
+
 
 
 static gint scan_geometry(gchar *buffer, gint *x, gint *y, gint *w, gint *h)
@@ -52,10 +59,15 @@
 	gint success = TRUE;
 	guint total = 0;
 	guint fail = 0;
+	gboolean changed = FALSE;
+	CollectManagerEntry *entry = NULL;
 
 	collection_load_stop(cd);
 
-	if (flush) collect_manager_flush();
+	if (flush) 
+		collect_manager_flush();
+	else
+		entry = collect_manager_get_entry(path);
 
 	if (!append)
 		{
@@ -104,8 +116,11 @@
 		if (buf)
 			{
 			gint valid;
-
-			valid = (buf[0] == '/' && collection_add_check(cd, buf, FALSE, flush));
+			
+			if (!flush)
+				changed |= collect_manager_process_action(entry, &buf);
+			
+			valid = (buf[0] == '/' && collection_add_check(cd, file_data_new_simple(buf), FALSE, TRUE));
 			g_free(buf);
 
 			total++;
@@ -124,8 +139,26 @@
 		}
 
 	fclose(f);
+	
+	if (!flush)
+		{
+		gchar *buf = NULL;
+		while (collect_manager_process_action(entry, &buf))
+			{
+			collection_add_check(cd, file_data_new_simple(buf), FALSE, TRUE);
+			changed = TRUE;
+			g_free(buf);
+			}
+		}
 
 	cd->list = collection_list_sort(cd->list, cd->sort_method);
+	
+	if (!flush && changed && success)
+		collection_save_private(cd, path);
+		
+	if (!flush)
+		collect_manager_entry_reset(entry);
+	
 	if (!append) cd->changed = FALSE;
 
 	return success;
@@ -214,10 +247,10 @@
 				   cd);
 
 	/* start it */
-	if (!thumb_loader_start(cd->thumb_loader, ci->path))
+	if (!thumb_loader_start(cd->thumb_loader, ci->fd->path))
 		{
 		/* error, handle it, do next */
-		if (debug) printf("error loading thumb for %s\n", ci->path);
+		if (debug) printf("error loading thumb for %s\n", ci->fd->path);
 		collection_load_thumb_do(cd);
 		collection_load_thumb_step(cd);
 		}
@@ -290,7 +323,7 @@
 	while (work)
 		{
 		CollectInfo *ci = work->data;
-		if (fprintf(f, "\"%s\"\n", ci->path) < 0)
+		if (fprintf(f, "\"%s\"\n", ci->fd->path) < 0)
 			{
 			fclose(f);
 			printf("Error writing to %s\n", tmp_path);
@@ -386,11 +419,13 @@
 #define COLLECT_MANAGER_ACTIONS_PER_IDLE 1000
 #define COLLECT_MANAGER_FLUSH_DELAY      10000
 
-typedef struct _CollectManagerEntry CollectManagerEntry;
 struct _CollectManagerEntry
 {
 	gchar *path;
-	GList *action_list;
+	GList *add_list;
+	GHashTable *oldpath_hash;
+	GHashTable *newpath_hash;
+	gboolean empty;
 };
 
 typedef enum {
@@ -449,26 +484,11 @@
 	g_free(action);
 }
 
-static CollectManagerEntry *collect_manager_entry_new(const gchar *path)
-{
-	CollectManagerEntry *entry;
-
-	entry = g_new0(CollectManagerEntry, 1);
-	entry->path = g_strdup(path);
-	entry->action_list = NULL;
-
-	collection_manager_entry_list = g_list_append(collection_manager_entry_list, entry);
-
-	return entry;
-}
-
-static void collect_manager_entry_free(CollectManagerEntry *entry)
+static void collect_manager_entry_free_data(CollectManagerEntry *entry)
 {
 	GList *work;
 
-	collection_manager_entry_list = g_list_remove(collection_manager_entry_list, entry);
-
-	work = entry->action_list;
+	work = entry->add_list;
 	while (work)
 		{
 		CollectManagerAction *action;
@@ -478,12 +498,179 @@
 
 		collect_manager_action_unref(action);
 		}
-	g_list_free(entry->action_list);
+	g_list_free(entry->add_list);
+	g_hash_table_destroy(entry->oldpath_hash);
+	g_hash_table_destroy(entry->newpath_hash);
+}
+
+static void collect_manager_entry_init_data(CollectManagerEntry *entry)
+{
+	entry->add_list = NULL;
+	entry->oldpath_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify) collect_manager_action_unref);
+	entry->newpath_hash = g_hash_table_new(g_str_hash, g_str_equal);
+	entry->empty = TRUE;
+
+}
+
+static CollectManagerEntry *collect_manager_entry_new(const gchar *path)
+{
+	CollectManagerEntry *entry;
+
+	entry = g_new0(CollectManagerEntry, 1);
+	entry->path = g_strdup(path);
+	collect_manager_entry_init_data(entry);
+
+	collection_manager_entry_list = g_list_append(collection_manager_entry_list, entry);
+
+	return entry;
+}
+
+
+static void collect_manager_entry_free(CollectManagerEntry *entry)
+{
+	GList *work;
+
+	collection_manager_entry_list = g_list_remove(collection_manager_entry_list, entry);
+
+	collect_manager_entry_free_data(entry);
 
 	g_free(entry->path);
 	g_free(entry);
 }
 
+static void collect_manager_entry_reset(CollectManagerEntry *entry)
+{
+	collect_manager_entry_free_data(entry);
+	collect_manager_entry_init_data(entry);
+}
+
+static CollectManagerEntry *collect_manager_get_entry(const gchar *path)
+{
+	GList *work;
+
+	work = collection_manager_entry_list;
+	while (work)
+		{
+		CollectManagerEntry *entry;
+
+		entry = work->data;
+		work = work->next;
+		if (strcmp(entry->path, path) == 0) 
+			{
+			return entry;
+			}
+		}
+	return NULL;
+
+}
+
+static void collect_manager_entry_add_action(CollectManagerEntry *entry, CollectManagerAction *action)
+{
+
+	CollectManagerAction *orig_action;
+	
+	entry->empty = FALSE; 
+	
+	if (action->oldpath == NULL)
+		{
+		/* add file */
+		if (action->newpath == NULL)
+			{
+			return;
+			}
+		
+		orig_action = g_hash_table_lookup(entry->newpath_hash, action->newpath);
+		if (orig_action)
+			{
+			/* target already exists */
+			printf("collection manager failed to add another action for target %s in collection %s\n",
+				action->newpath, entry->path);
+			return;
+			}
+		entry->add_list = g_list_append(entry->add_list, action);
+		g_hash_table_insert(entry->newpath_hash, action->newpath, action);
+		collect_manager_action_ref(action);
+		return;
+		}
+
+	orig_action = g_hash_table_lookup(entry->newpath_hash, action->oldpath);
+	if (orig_action)
+		{
+		/* new action with the same file */
+		CollectManagerAction *new_action = collect_manager_action_new(orig_action->oldpath, action->newpath, action->type);
+		
+		if (new_action->oldpath)
+			{
+			g_hash_table_steal(entry->oldpath_hash, orig_action->oldpath);
+			g_hash_table_insert(entry->oldpath_hash, new_action->oldpath, new_action);
+			}
+		else
+			{
+			GList *work = g_list_find(entry->add_list, orig_action);
+			work->data = new_action;
+			}
+		
+		g_hash_table_steal(entry->newpath_hash, orig_action->newpath);
+		if (new_action->newpath) 
+			{
+			g_hash_table_insert(entry->newpath_hash, new_action->newpath, new_action); 
+			}
+		collect_manager_action_unref(orig_action);
+		return;
+		}
+
+
+	orig_action = g_hash_table_lookup(entry->oldpath_hash, action->oldpath);
+	if (orig_action)
+		{
+		/* another action for the same source, ignore */
+		printf("collection manager failed to add another action for source %s in collection %s\n",
+			action->oldpath, entry->path);
+		return;
+		}
+	
+	g_hash_table_insert(entry->oldpath_hash, action->oldpath, action);
+	if (action->newpath)
+		{
+		g_hash_table_insert(entry->newpath_hash, action->newpath, action); 
+		}
+	collect_manager_action_ref(action);
+}
+
+gint collect_manager_process_action(CollectManagerEntry *entry, gchar **path_ptr)
+{
+	gchar *path = *path_ptr;
+	CollectManagerAction *action;
+	
+	if (path == NULL)
+		{
+		/* get new files */
+		if (entry->add_list)
+			{
+			action = entry->add_list->data;
+			g_assert(action->oldpath == NULL);
+			entry->add_list = g_list_remove(entry->add_list, action);
+			path = g_strdup(action->newpath);
+			g_hash_table_remove(entry->newpath_hash, path);
+			collect_manager_action_unref(action);
+			}
+		*path_ptr = path;
+		return (path != NULL);
+		}
+		
+	action = g_hash_table_lookup(entry->oldpath_hash, path);
+	
+	if (action)
+		{
+		g_free(path);
+		path = g_strdup(action->newpath);
+		*path_ptr = path;
+		return TRUE;
+		}
+
+	return FALSE; /* no change */
+}
+
 static void collect_manager_refresh(void)
 {
 	GList *list = NULL;
@@ -563,8 +750,7 @@
 
 			if (action->type == COLLECTION_MANAGER_UPDATE)
 				{
-				entry->action_list = g_list_prepend(entry->action_list, action);
-				collect_manager_action_ref(action);
+				collect_manager_entry_add_action(entry, action);
 				}
 			else if (action->oldpath && action->newpath &&
 				 strcmp(action->newpath, entry->path) == 0)
@@ -580,9 +766,7 @@
 					{
 					action->newpath = NULL;
 					}
-
-				entry->action_list = g_list_prepend(entry->action_list, action);
-				collect_manager_action_ref(action);
+				collect_manager_entry_add_action(entry, action);
 				}
 
 			max--;
@@ -609,52 +793,14 @@
 {
 	CollectionData *cd;
 	gint success;
-	GList *work;
 
-	if (!entry->action_list) return FALSE;
+	if (entry->empty) return FALSE;
 
 	cd = collection_new(entry->path);
 	success = collection_load_private(cd, entry->path, FALSE, FALSE);
 
-	work = g_list_last(entry->action_list);
-	while (work)
-		{
-		CollectManagerAction *action;
-
-		action = work->data;
-		work = work->prev;
-
-		if (!action->oldpath)
-			{
-			/* add image */
-			if (collection_list_find(cd->list, action->newpath) == NULL)
-				{
-				collection_add_check(cd, action->newpath, FALSE, FALSE);
-				}
-			}
-		else if (action->newpath)
-			{
-			/* rename image */
-			while (collection_rename(cd, action->oldpath, action->newpath));
-			}
-		else
-			{
-			/* remove image */
-			while (collection_remove(cd, action->oldpath));
-			}
-		collect_manager_action_unref(action);
-		}
-
-	if (success && cd->changed)
-		{
-		collection_save_private(cd, entry->path);
-		if (debug) printf("collection manager updated: %s\n", entry->path);
-		}
 	collection_unref(cd);
 
-	g_list_free(entry->action_list);
-	entry->action_list = NULL;
-
 	return TRUE;
 }
 
@@ -675,6 +821,8 @@
 	return FALSE;
 }
 
+
+
 static gint collect_manager_process_cb(gpointer data)
 {
 	if (collection_manager_action_list) collect_manager_refresh();
@@ -735,50 +883,52 @@
 	collect_manager_timer_push(FALSE);
 }
 
-void collect_manager_moved(const gchar *oldpath, const gchar *newpath)
+void collect_manager_moved(FileData *fd)
 {
 	CollectManagerAction *action;
+	const gchar *oldpath = fd->change->source;
+	const gchar *newpath = fd->change->dest;
 
 	action = collect_manager_action_new(oldpath, newpath, COLLECTION_MANAGER_UPDATE);
 	collect_manager_add_action(action);
 }
 
-void collect_manager_add(const gchar *path, const gchar *collection)
+void collect_manager_add(FileData *fd, const gchar *collection)
 {
 	CollectManagerAction *action;
 	CollectWindow *cw;
 
-	if (!path || !collection) return;
+	if (!fd || !collection) return;
 
 	cw = collection_window_find_by_path(collection);
 	if (cw)
 		{
-		if (collection_list_find(cw->cd->list, path) == NULL)
+		if (collection_list_find(cw->cd->list, fd->path) == NULL)
 			{
-			collection_add(cw->cd, path, FALSE);
+			collection_add(cw->cd, fd, FALSE);
 			}
 		return;
 		}
 
-	action = collect_manager_action_new(path, collection, COLLECTION_MANAGER_ADD);
+	action = collect_manager_action_new(fd->path, collection, COLLECTION_MANAGER_ADD);
 	collect_manager_add_action(action);
 }
 
-void collect_manager_remove(const gchar *path, const gchar *collection)
+void collect_manager_remove(FileData *fd, const gchar *collection)
 {
 	CollectManagerAction *action;
 	CollectWindow *cw;
 
-	if (!path || !collection) return;
+	if (!fd || !collection) return;
 
 	cw = collection_window_find_by_path(collection);
 	if (cw)
 		{
-		while (collection_remove(cw->cd, path));
+		while (collection_remove(cw->cd, fd));
 		return;
 		}
 
-	action = collect_manager_action_new(path, collection, COLLECTION_MANAGER_REMOVE);
+	action = collect_manager_action_new(fd->path, collection, COLLECTION_MANAGER_REMOVE);
 	collect_manager_add_action(action);
 }