[gthumb] fixed catalog reordering when the catalog is sorted and/or filtered



commit 27b18e3cee9f0ce48b0381964154d0256cd846f9
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Thu Aug 12 21:36:43 2010 +0200

    fixed catalog reordering when the catalog is sorted and/or filtered
    
    [bug #619442]

 extensions/catalogs/gth-file-source-catalogs.c |   94 +++++++++++++++++++----
 extensions/file_manager/callbacks.c            |   20 ++++--
 extensions/file_manager/gth-reorder-task.c     |   15 +++-
 extensions/file_manager/gth-reorder-task.h     |    3 +-
 gthumb/gth-file-source.c                       |   22 ++++--
 gthumb/gth-file-source.h                       |    6 +-
 6 files changed, 121 insertions(+), 39 deletions(-)
---
diff --git a/extensions/catalogs/gth-file-source-catalogs.c b/extensions/catalogs/gth-file-source-catalogs.c
index 172fc75..4988f24 100644
--- a/extensions/catalogs/gth-file-source-catalogs.c
+++ b/extensions/catalogs/gth-file-source-catalogs.c
@@ -813,7 +813,8 @@ gth_file_source_catalogs_is_reorderable (GthFileSource *file_source)
 typedef struct {
 	GthFileSource *file_source;
 	GthFileData   *destination;
-	GList         *file_list; /* GFile * list */
+	GList         *visible_files; /* GFile list */
+	GList         *files_to_move; /* GFile list */
 	int            dest_pos;
 	ReadyCallback  callback;
 	gpointer       data;
@@ -825,7 +826,8 @@ static void
 reorder_data_free (ReorderData *reorder_data)
 {
 	gth_file_source_set_active (reorder_data->file_source, FALSE);
-	_g_object_list_unref (reorder_data->file_list);
+	_g_object_list_unref (reorder_data->visible_files);
+	_g_object_list_unref (reorder_data->files_to_move);
 	_g_object_unref (reorder_data->destination);
 	_g_object_unref (reorder_data->file_source);
 	g_free (reorder_data->new_order);
@@ -850,36 +852,89 @@ reorder_buffer_ready_cb (void     **buffer,
 }
 
 
+static int
+remove_from_file_list_and_get_position (GList **file_list,
+					GFile  *file)
+{
+	GList *scan;
+	int    i = 0;
+
+	for (scan = *file_list; scan; scan = scan->next, i++)
+		if (g_file_equal ((GFile *) scan->data, file))
+			break;
+
+	if (scan == NULL)
+		return -1;
+
+	*file_list = g_list_remove_link (*file_list, scan);
+
+	return i;
+}
+
+
 static int *
 reorder_catalog_list (GthCatalog *catalog,
-		      GList      *file_list,
+		      GList      *visible_files,
+		      GList      *files_to_move,
 		      int         dest_pos)
 {
 	GHashTable *positions;
-	int        *new_order;
+	GList      *new_visible_files;
 	GList      *scan;
+	int        *new_order;
 	int         pos;
-	GList      *all_files;
+	GList      *new_file_list;
+	GHashTable *visibles;
+
+	/* save the original positions */
 
 	positions = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, (GDestroyNotify) g_object_unref, NULL);
-	for (scan = gth_catalog_get_file_list (catalog), pos = 0; scan; scan = scan->next, pos++)
+	for (scan = visible_files, pos = 0; scan; scan = scan->next, pos++)
 		g_hash_table_insert (positions, g_object_ref ((GFile *) scan->data), GINT_TO_POINTER (pos));
 
-	for (scan = file_list; scan; scan = scan->next) {
-		int file_pos = gth_catalog_remove_file (catalog, (GFile *) scan->data);
+	/* create the new visible list */
+
+	new_visible_files = g_list_copy (visible_files);
+
+	for (scan = files_to_move; scan; scan = scan->next) {
+		int file_pos = remove_from_file_list_and_get_position (&new_visible_files, (GFile *) scan->data);
 		if (file_pos < dest_pos)
 			dest_pos--;
 	}
 
-	for (scan = file_list; scan; scan = scan->next)
-		if (gth_catalog_insert_file (catalog, (GFile *) scan->data, dest_pos))
-			dest_pos++;
+	for (scan = files_to_move; scan; scan = scan->next) {
+		new_visible_files = g_list_insert (new_visible_files, (GFile *) scan->data, dest_pos);
+		dest_pos++;
+	}
+
+	/* compute the new order */
 
-	all_files = gth_catalog_get_file_list (catalog);
-	new_order = g_new0 (int, g_list_length (all_files));
-	for (scan = all_files, pos = 0; scan; scan = scan->next, pos++)
+	new_order = g_new0 (int, g_list_length (new_visible_files));
+	for (scan = new_visible_files, pos = 0; scan; scan = scan->next, pos++)
 		new_order[pos] = GPOINTER_TO_INT (g_hash_table_lookup (positions, (GFile *) scan->data));
 
+	/* save the new order in the catalog, appending the hidden files at
+	 * the end. */
+
+	new_file_list = _g_object_list_ref (new_visible_files);
+
+	visibles = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, (GDestroyNotify) g_object_unref, NULL);
+	for (scan = new_visible_files; scan; scan = scan->next)
+		g_hash_table_insert (visibles, g_object_ref ((GFile *) scan->data), GINT_TO_POINTER (1));
+
+	new_file_list = g_list_reverse (new_file_list);
+	for (scan = gth_catalog_get_file_list (catalog); scan; scan = scan->next) {
+		GFile *file = scan->data;
+
+		if (g_hash_table_lookup (visibles, file) == NULL)
+			new_file_list = g_list_prepend (new_file_list, g_object_ref (file));
+	}
+	new_file_list = g_list_reverse (new_file_list);
+	gth_catalog_set_file_list (catalog, new_file_list);
+
+	_g_object_list_unref (new_file_list);
+	g_hash_table_destroy (visibles);
+	g_list_free (new_visible_files);
 	g_hash_table_destroy (positions);
 
 	return new_order;
@@ -904,7 +959,10 @@ reorder_catalog_ready_cb (GObject  *object,
 	}
 
 	catalog = (GthCatalog *) object;
-	reorder_data->new_order = reorder_catalog_list (catalog, reorder_data->file_list, reorder_data->dest_pos);
+	reorder_data->new_order = reorder_catalog_list (catalog,
+							reorder_data->visible_files,
+							reorder_data->files_to_move,
+							reorder_data->dest_pos);
 	gth_catalog_set_order (catalog, "general::unsorted", FALSE);
 
 	buffer = gth_catalog_to_data (catalog, &size);
@@ -925,7 +983,8 @@ reorder_catalog_ready_cb (GObject  *object,
 static void
 gth_file_source_catalogs_reorder (GthFileSource *file_source,
 				  GthFileData   *destination,
-				  GList         *file_list, /* GFile * list */
+				  GList         *visible_files, /* GFile list */
+				  GList         *files_to_move, /* GFile list */
 				  int            dest_pos,
 				  ReadyCallback  callback,
 				  gpointer       data)
@@ -940,7 +999,8 @@ gth_file_source_catalogs_reorder (GthFileSource *file_source,
 	reorder_data = g_new0 (ReorderData, 1);
 	reorder_data->file_source = g_object_ref (file_source);
 	reorder_data->destination = g_object_ref (destination);
-	reorder_data->file_list = _g_object_list_ref (file_list);
+	reorder_data->visible_files = _g_object_list_ref (visible_files);
+	reorder_data->files_to_move = _g_object_list_ref (files_to_move);
 	reorder_data->dest_pos = dest_pos;
 	reorder_data->callback = callback;
 	reorder_data->data = data;
diff --git a/extensions/file_manager/callbacks.c b/extensions/file_manager/callbacks.c
index eac732e..89e13ce 100644
--- a/extensions/file_manager/callbacks.c
+++ b/extensions/file_manager/callbacks.c
@@ -253,7 +253,7 @@ gth_file_list_drag_data_received (GtkWidget        *file_view,
 	GthBrowser  *browser = user_data;
 	gboolean     success = FALSE;
 	char       **uris;
-	GList       *file_list;
+	GList       *selected_files;
 
 	g_signal_stop_emission_by_name (file_view, "drag-data-received");
 
@@ -274,20 +274,28 @@ gth_file_list_drag_data_received (GtkWidget        *file_view,
 	gtk_drag_finish (context, success, FALSE, time);
 
 	uris = gtk_selection_data_get_uris (selection_data);
-	file_list = _g_file_list_new_from_uriv (uris);
-	if (file_list != NULL) {
+	selected_files = _g_file_list_new_from_uriv (uris);
+	if (selected_files != NULL) {
 		if (gtk_drag_get_source_widget (context) == file_view) {
+			GList       *file_data_list;
+			GList       *visible_files;
 			BrowserData *data;
 			GthTask     *task;
 
+			file_data_list = gth_file_store_get_visibles (gth_browser_get_file_store (browser));
+			visible_files = gth_file_data_list_to_file_list (file_data_list);
+
 			data = g_object_get_data (G_OBJECT (browser), BROWSER_DATA_KEY);
 			task = gth_reorder_task_new (gth_browser_get_location_source (browser),
 						     gth_browser_get_location_data (browser),
-						     file_list,
+						     visible_files,
+						     selected_files,
 						     data->drop_pos);
 			gth_browser_exec_task (browser, task, FALSE);
 
 			g_object_unref (task);
+			_g_object_list_unref (visible_files);
+			_g_object_list_unref (file_data_list);
 		}
 		else {
 			GthFileSource *file_source;
@@ -324,7 +332,7 @@ gth_file_list_drag_data_received (GtkWidget        *file_view,
 				task = gth_copy_task_new (file_source,
 							  gth_browser_get_location_data (browser),
 							  move,
-							  file_list);
+							  selected_files);
 				gth_browser_exec_task (browser, task, FALSE);
 
 				g_object_unref (task);
@@ -332,7 +340,7 @@ gth_file_list_drag_data_received (GtkWidget        *file_view,
 		}
 	}
 
-	_g_object_list_unref (file_list);
+	_g_object_list_unref (selected_files);
 	g_strfreev (uris);
 }
 
diff --git a/extensions/file_manager/gth-reorder-task.c b/extensions/file_manager/gth-reorder-task.c
index 0a00280..75d1cba 100644
--- a/extensions/file_manager/gth-reorder-task.c
+++ b/extensions/file_manager/gth-reorder-task.c
@@ -26,7 +26,8 @@
 struct _GthReorderTaskPrivate {
 	GthFileSource *file_source;
 	GthFileData   *destination;
-	GList         *files;
+	GList         *visible_files;
+	GList         *files_to_move;
 	int            new_pos;
 };
 
@@ -41,7 +42,8 @@ gth_reorder_task_finalize (GObject *object)
 
 	self = GTH_REORDER_TASK (object);
 
-	_g_object_list_unref (self->priv->files);
+	_g_object_list_unref (self->priv->visible_files);
+	_g_object_list_unref (self->priv->files_to_move);
 	_g_object_unref (self->priv->destination);
 	_g_object_unref (self->priv->file_source);
 
@@ -69,7 +71,8 @@ gth_reorder_task_exec (GthTask *task)
 
 	gth_file_source_reorder (self->priv->file_source,
 				 self->priv->destination,
-			         self->priv->files,
+			         self->priv->visible_files,
+			         self->priv->files_to_move,
 			         self->priv->new_pos,
 			         reorder_done_cb,
 			         self);
@@ -139,7 +142,8 @@ gth_reorder_task_get_type (void)
 GthTask *
 gth_reorder_task_new (GthFileSource *file_source,
 		      GthFileData   *destination,
-		      GList         *file_list,
+		      GList         *visible_files, /* GFile list */
+		      GList         *files_to_move, /* GFile list */
 		      int            new_pos)
 {
 	GthReorderTask *self;
@@ -149,7 +153,8 @@ gth_reorder_task_new (GthFileSource *file_source,
 	self->priv->file_source = g_object_ref (file_source);
 	self->priv->destination = g_object_ref (destination);
 	self->priv->new_pos = new_pos;
-	self->priv->files = _g_object_list_ref (file_list);
+	self->priv->visible_files = _g_object_list_ref (visible_files);
+	self->priv->files_to_move = _g_object_list_ref (files_to_move);
 
 	return (GthTask *) self;
 }
diff --git a/extensions/file_manager/gth-reorder-task.h b/extensions/file_manager/gth-reorder-task.h
index 64b712d..ded1100 100644
--- a/extensions/file_manager/gth-reorder-task.h
+++ b/extensions/file_manager/gth-reorder-task.h
@@ -50,7 +50,8 @@ struct _GthReorderTaskClass {
 GType         gth_reorder_task_get_type  (void);
 GthTask *     gth_reorder_task_new       (GthFileSource *file_source,
 					  GthFileData   *destination,
-					  GList         *file_list,
+					  GList         *visible_files, /* GFile list */
+					  GList         *files_to_move, /* GFile list */
 					  int            new_pos);
 
 G_END_DECLS
diff --git a/gthumb/gth-file-source.c b/gthumb/gth-file-source.c
index c250132..b31255d 100644
--- a/gthumb/gth-file-source.c
+++ b/gthumb/gth-file-source.c
@@ -94,7 +94,8 @@ typedef struct {
 
 typedef struct {
 	GthFileData   *destination;
-	GList         *file_list;
+	GList         *visible_files;
+	GList         *files_to_move;
 	int            dest_pos;
 	ReadyCallback  ready_callback;
 	gpointer       data;
@@ -345,7 +346,8 @@ gth_file_source_queue_copy (GthFileSource    *file_source,
 static void
 gth_file_source_queue_reorder (GthFileSource    *file_source,
 			       GthFileData      *destination,
-			       GList            *file_list,
+			       GList            *visible_files, /* GFile list */
+			       GList            *files_to_move, /* GFile list */
 			       int               dest_pos,
 			       ReadyCallback     ready_callback,
 			       gpointer          data)
@@ -356,7 +358,8 @@ gth_file_source_queue_reorder (GthFileSource    *file_source,
 	async_op->file_source = file_source;
 	async_op->op = FILE_SOURCE_OP_REORDER;
 	async_op->data.reorder.destination = gth_file_data_dup (destination);
-	async_op->data.reorder.file_list = _g_file_list_dup (file_list);
+	async_op->data.reorder.visible_files = _g_file_list_dup (visible_files);
+	async_op->data.reorder.files_to_move = _g_file_list_dup (files_to_move);
 	async_op->data.reorder.dest_pos = dest_pos;
 	async_op->data.reorder.ready_callback = ready_callback;
 	async_op->data.reorder.data = data;
@@ -437,7 +440,8 @@ gth_file_source_exec_next_in_queue (GthFileSource *file_source)
 	case FILE_SOURCE_OP_REORDER:
 		gth_file_source_reorder (file_source,
 					 async_op->data.reorder.destination,
-					 async_op->data.reorder.file_list,
+					 async_op->data.reorder.visible_files,
+					 async_op->data.reorder.files_to_move,
 					 async_op->data.reorder.dest_pos,
 				         async_op->data.reorder.ready_callback,
 					 async_op->data.reorder.data);
@@ -659,7 +663,8 @@ base_is_reorderable (GthFileSource *file_source)
 static void
 base_reorder (GthFileSource *file_source,
 	      GthFileData   *destination,
-	      GList         *file_list, /* GFile * list */
+	      GList         *visible_files, /* GFile list */
+	      GList         *files_to_move, /* GFile list */
 	      int            dest_pos,
 	      ReadyCallback  callback,
 	      gpointer       data)
@@ -1150,15 +1155,16 @@ gth_file_source_is_reorderable (GthFileSource *file_source)
 void
 gth_file_source_reorder (GthFileSource *file_source,
 			 GthFileData   *destination,
-		         GList         *file_list, /* GFile * list */
+		         GList         *visible_files, /* GFile list */
+		         GList         *files_to_move, /* GFile list */
 		         int            dest_pos,
 		         ReadyCallback  callback,
 		         gpointer       data)
 {
 	if (gth_file_source_is_active (file_source)) {
-		gth_file_source_queue_reorder (file_source, destination, file_list, dest_pos, callback, data);
+		gth_file_source_queue_reorder (file_source, destination, visible_files, files_to_move, dest_pos, callback, data);
 		return;
 	}
-	GTH_FILE_SOURCE_GET_CLASS (G_OBJECT (file_source))->reorder (file_source, destination, file_list, dest_pos, callback, data);
+	GTH_FILE_SOURCE_GET_CLASS (G_OBJECT (file_source))->reorder (file_source, destination, visible_files, files_to_move, dest_pos, callback, data);
 }
 
diff --git a/gthumb/gth-file-source.h b/gthumb/gth-file-source.h
index b4bfa5a..84057c3 100644
--- a/gthumb/gth-file-source.h
+++ b/gthumb/gth-file-source.h
@@ -115,7 +115,8 @@ struct _GthFileSourceClass
 	gboolean     (*is_reorderable)        (GthFileSource    *file_source);
 	void         (*reorder)               (GthFileSource    *file_source,
 					       GthFileData      *destination,
-					       GList            *file_list, /* GFile * list */
+					       GList            *visible_files, /* GFile list */
+					       GList            *files_to_move, /* GFile list */
 					       int               dest_pos,
 					       ReadyCallback     callback,
 					       gpointer          data);
@@ -191,7 +192,8 @@ void           gth_file_source_monitor_directory     (GthFileSource    *file_sou
 gboolean       gth_file_source_is_reorderable        (GthFileSource    *file_source);
 void           gth_file_source_reorder               (GthFileSource    *file_source,
 						      GthFileData      *destination,
-						      GList            *file_list, /* GFile * list */
+						      GList            *visible_files, /* GFile list */
+						      GList            *files_to_move, /* GFile list */
 						      int               dest_pos,
 						      ReadyCallback     callback,
 						      gpointer          data);



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