[gthumb/ext] added infrastructure to reorder files in a catalog



commit 8a67257b59d9a871e01d62e6dd18a6c29af5f6d5
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sun Aug 23 23:02:53 2009 +0200

    added infrastructure to reorder files in a catalog

 extensions/catalogs/dlg-add-to-catalog.c       |    1 +
 extensions/catalogs/gth-catalog.c              |    3 +-
 extensions/catalogs/gth-catalog.h              |    1 +
 extensions/catalogs/gth-file-source-catalogs.c |  146 +++++++++++++++++-
 extensions/file_manager/Makefile.am            |    2 +
 extensions/file_manager/callbacks.c            |  194 ++++++++++++++++++------
 extensions/file_manager/gth-reorder-task.c     |  156 +++++++++++++++++++
 extensions/file_manager/gth-reorder-task.h     |   59 +++++++
 gthumb/gth-file-source.c                       |  100 ++++++++++++-
 gthumb/gth-file-source.h                       |   14 ++
 gthumb/gth-file-view.c                         |   12 ++
 gthumb/gth-file-view.h                         |   12 ++
 gthumb/gth-icon-view.c                         |   34 ++++
 gthumb/gth-main.c                              |    2 +-
 gthumb/gth-main.h                              |    2 +-
 gthumb/gth-tags-entry.c                        |    2 +-
 gthumb/gth-tags-file.c                         |    2 +-
 gthumb/gth-tags-file.h                         |    2 +-
 18 files changed, 682 insertions(+), 62 deletions(-)
---
diff --git a/extensions/catalogs/dlg-add-to-catalog.c b/extensions/catalogs/dlg-add-to-catalog.c
index c8f437c..dce60ae 100644
--- a/extensions/catalogs/dlg-add-to-catalog.c
+++ b/extensions/catalogs/dlg-add-to-catalog.c
@@ -141,6 +141,7 @@ add_button_clicked_cb (GtkWidget  *widget,
 		return;
 
 	gth_catalog_load_from_file (data->selected_catalog->file,
+				    NULL,
 				    catalog_ready_cb,
 				    data);
 }
diff --git a/extensions/catalogs/gth-catalog.c b/extensions/catalogs/gth-catalog.c
index 1d78b1a..3b475a1 100644
--- a/extensions/catalogs/gth-catalog.c
+++ b/extensions/catalogs/gth-catalog.c
@@ -703,6 +703,7 @@ load__catalog_buffer_ready_cb (void     *buffer,
 
 void
 gth_catalog_load_from_file (GFile         *file,
+		            GCancellable  *cancellable,
 			    ReadyCallback  ready_func,
 			    gpointer       user_data)
 {
@@ -716,7 +717,7 @@ gth_catalog_load_from_file (GFile         *file,
 	gio_file = gth_catalog_file_to_gio_file (file);
 	g_load_file_async (gio_file,
 			   G_PRIORITY_DEFAULT,
-			   NULL,
+			   cancellable,
 			   load__catalog_buffer_ready_cb,
 			   load_data);
 
diff --git a/extensions/catalogs/gth-catalog.h b/extensions/catalogs/gth-catalog.h
index 8120579..f0ad571 100644
--- a/extensions/catalogs/gth-catalog.h
+++ b/extensions/catalogs/gth-catalog.h
@@ -108,6 +108,7 @@ char *         gth_catalog_get_relative_path       (GFile         *file);
 GIcon *        gth_catalog_get_icon                (GFile         *file);
 char *         gth_catalog_get_display_name        (GFile         *file);
 void           gth_catalog_load_from_file          (GFile         *file,
+						    GCancellable  *cancellable,
 						    ReadyCallback  ready_func,
 						    gpointer       user_data);
 
diff --git a/extensions/catalogs/gth-file-source-catalogs.c b/extensions/catalogs/gth-file-source-catalogs.c
index 7e2c4a3..f94f561 100644
--- a/extensions/catalogs/gth-file-source-catalogs.c
+++ b/extensions/catalogs/gth-file-source-catalogs.c
@@ -304,11 +304,11 @@ gth_file_source_catalogs_list (GthFileSource *file_source,
 }
 
 
-/* -- gth_file_source_vfs_copy -- */
+/* -- gth_file_source_catalogs_copy -- */
 
 
 typedef struct {
-	GthFileSourceVfs *file_source;
+	GthFileSource    *file_source;
 	GthFileData      *destination;
 	GList            *file_list;
 	ProgressCallback  progress_callback;
@@ -409,7 +409,10 @@ copy__file_list_info_ready_cb (GList    *files,
 	}
 	cod->files = g_list_reverse (cod->files);
 
-	gth_catalog_load_from_file (cod->destination->file, catalog_ready_cb, cod);
+	gth_catalog_load_from_file (cod->destination->file,
+				   gth_file_source_get_cancellable (cod->file_source),
+				   catalog_ready_cb,
+				   cod);
 }
 
 
@@ -451,6 +454,140 @@ gth_file_source_catalogs_copy (GthFileSource    *file_source,
 }
 
 
+static gboolean
+gth_file_source_catalogs_is_reorderable (GthFileSource *file_source)
+{
+	return TRUE;
+
+}
+
+
+typedef struct {
+	GthFileSource *file_source;
+	GthFileData   *destination;
+	GList         *file_list; /* GFile * list */
+	int            dest_pos;
+	ReadyCallback  callback;
+	gpointer       data;
+} ReorderData;
+
+
+static void
+reorder_data_free (ReorderData *reorder_data)
+{
+	_g_object_list_unref (reorder_data->file_list);
+	_g_object_unref (reorder_data->destination);
+	_g_object_unref (reorder_data->file_source);
+	g_free (reorder_data);
+}
+
+
+static void
+reorder_buffer_ready_cb (void     *buffer,
+		         gsize     count,
+		         GError   *error,
+		         gpointer  user_data)
+{
+	ReorderData *reorder_data = user_data;
+	GFile       *parent;
+	GList       *files;
+
+	g_free (buffer);
+
+	reorder_data->callback (G_OBJECT (reorder_data->file_source), error, reorder_data->data);
+
+	parent = g_file_get_parent (reorder_data->destination->file);
+	files = g_list_append (NULL, reorder_data->destination->file);
+	gth_monitor_folder_changed (gth_main_get_default_monitor (),
+				    parent,
+				    files,
+				    GTH_MONITOR_EVENT_CHANGED);
+
+	g_list_free (files);
+	g_object_unref (parent);
+	reorder_data_free (reorder_data);
+}
+
+
+static void
+reorder_catalog_ready_cb (GObject  *object,
+			  GError   *error,
+			  gpointer  user_data)
+{
+	ReorderData *reorder_data = user_data;
+	GthCatalog  *catalog;
+	char        *buffer;
+	gsize        buffer_size;
+	GFile       *gio_file;
+
+	if (error != NULL) {
+		reorder_data->callback (G_OBJECT (reorder_data->file_source), error, reorder_data->data);
+		reorder_data_free (reorder_data);
+		return;
+	}
+
+	catalog = (GthCatalog *) object;
+
+	/* FIXME: reorder the file list here */
+
+	{
+		GList *scan;
+
+		for (scan = gth_catalog_get_file_list (catalog); scan; scan = scan->next) {
+			GFile *file = scan->data;
+
+			g_print ("==> %s\n", g_file_get_uri (file));
+		}
+	}
+
+	buffer = gth_catalog_to_data (catalog, &buffer_size);
+	gio_file = gth_file_source_to_gio_file (reorder_data->file_source, reorder_data->destination->file);
+	g_write_file_async (gio_file,
+			    buffer,
+			    buffer_size,
+			    G_PRIORITY_DEFAULT,
+			    gth_file_source_get_cancellable (reorder_data->file_source),
+			    reorder_buffer_ready_cb,
+			    reorder_data);
+
+	g_object_unref (gio_file);
+}
+
+
+static void
+gth_file_source_catalogs_reorder (GthFileSource *file_source,
+				  GthFileData   *destination,
+				  GList         *file_list, /* GFile * list */
+				  int            dest_pos,
+				  ReadyCallback  callback,
+				  gpointer       data)
+{
+	GthFileSourceCatalogs *catalogs = (GthFileSourceCatalogs *) file_source;
+	ReorderData           *reorder_data;
+	GFile                 *gio_file;
+
+	gth_file_source_set_active (GTH_FILE_SOURCE (catalogs), TRUE);
+	g_cancellable_reset (gth_file_source_get_cancellable (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->dest_pos = dest_pos;
+	reorder_data->callback = callback;
+	reorder_data->data = data;
+
+	gio_file = gth_file_source_to_gio_file (file_source, destination->file);
+	gth_catalog_load_from_file (gio_file,
+				    gth_file_source_get_cancellable (file_source),
+				    reorder_catalog_ready_cb,
+				    reorder_data);
+
+	g_object_unref (gio_file);
+}
+
+
+
 static void
 gth_file_source_catalogs_finalize (GObject *object)
 {
@@ -486,6 +623,9 @@ gth_file_source_catalogs_class_init (GthFileSourceCatalogsClass *class)
 	file_source_class->get_file_data = gth_file_source_catalogs_get_file_data;
 	file_source_class->list = gth_file_source_catalogs_list;
 	file_source_class->copy = gth_file_source_catalogs_copy;
+	file_source_class->is_reorderable  = gth_file_source_catalogs_is_reorderable;
+	file_source_class->reorder = gth_file_source_catalogs_reorder;
+
 }
 
 
diff --git a/extensions/file_manager/Makefile.am b/extensions/file_manager/Makefile.am
index 3d01974..3dafa84 100644
--- a/extensions/file_manager/Makefile.am
+++ b/extensions/file_manager/Makefile.am
@@ -12,6 +12,8 @@ libfile_manager_la_SOURCES = 		\
 	gth-delete-task.h		\
 	gth-duplicate-task.c		\
 	gth-duplicate-task.h		\
+	gth-reorder-task.c		\
+	gth-reorder-task.h		\
 	main.c
 
 libfile_manager_la_CFLAGS = $(GTHUMB_CFLAGS) $(DISABLE_DEPRECATED) $(WARNINGS) -I$(top_srcdir) -I$(top_builddir)/gthumb 
diff --git a/extensions/file_manager/callbacks.c b/extensions/file_manager/callbacks.c
index 8b7cd25..30dcef6 100644
--- a/extensions/file_manager/callbacks.c
+++ b/extensions/file_manager/callbacks.c
@@ -28,9 +28,11 @@
 #include <gthumb.h>
 #include "actions.h"
 #include "gth-copy-task.h"
+#include "gth-reorder-task.h"
 
 
 #define BROWSER_DATA_KEY "file-manager-browser-data"
+#define URI_LIST_TARGET (gdk_atom_intern_static_string ("text/uri-list"))
 
 
 static const char *vfs_ui_info =
@@ -196,6 +198,7 @@ typedef struct {
 	guint           browser_vfs_merge_id;
 	guint           folder_popup_merge_id;
 	gboolean        can_paste;
+	int             drop_pos;
 } BrowserData;
 
 
@@ -223,22 +226,20 @@ gth_file_list_drag_data_received (GtkWidget        *widget,
 				  GdkDragContext   *context,
 				  int               x,
 				  int               y,
-				  GtkSelectionData *data,
+				  GtkSelectionData *selection_data,
 				  guint             info,
 				  guint             time,
-				  gpointer          extra_data)
+				  gpointer          user_data)
 {
-	GthBrowser  *browser = extra_data;
+	GthBrowser  *browser = user_data;
+
 	gboolean     success = FALSE;
 	char       **uris;
 	GList       *file_list;
 
-	g_signal_stop_emission_by_name (widget, "drag-data-received");
+	g_print ("DRAG_DATA_RECEIVED\n");
 
-	if (gtk_drag_get_source_widget (context) == gth_file_list_get_view (GTH_FILE_LIST (gth_browser_get_file_list (browser)))) {
-		gtk_drag_finish (context, FALSE, FALSE, time);
-		return;
-	}
+	g_signal_stop_emission_by_name (widget, "drag-data-received");
 
 	if ((context->suggested_action == GDK_ACTION_COPY)
 	    || (context->suggested_action == GDK_ACTION_MOVE))
@@ -248,46 +249,61 @@ gth_file_list_drag_data_received (GtkWidget        *widget,
 
 	gtk_drag_finish (context, success, FALSE, time);
 
-	uris = gtk_selection_data_get_uris (data);
+	uris = gtk_selection_data_get_uris (selection_data);
 	file_list = _g_file_list_new_from_uriv (uris);
 	if (file_list != NULL) {
-		GthFileSource *file_source;
-		gboolean       cancel = FALSE;
-		gboolean       move;
-
-		file_source = gth_browser_get_location_source (browser);
-		move = context->suggested_action == GDK_ACTION_MOVE;
-		if (move && ! gth_file_source_can_cut (file_source)) {
-			GtkWidget *dialog;
-			int        response;
-
-			dialog = _gtk_message_dialog_new (GTK_WINDOW (browser),
-							  GTK_DIALOG_MODAL,
-							  GTK_STOCK_DIALOG_QUESTION,
-							  _("Could not move the files"),
-							  _("Files cannot be moved to the current location, as alternative you can choose to copy them."),
-							  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-							  GTK_STOCK_COPY, GTK_RESPONSE_OK,
-							  NULL);
-			response = gtk_dialog_run (GTK_DIALOG (dialog));
-			gtk_widget_destroy (dialog);
-
-			if (response == GTK_RESPONSE_CANCEL)
-				cancel = TRUE;
-
-			move = FALSE;
+		if (gtk_drag_get_source_widget (context) == gth_file_list_get_view (GTH_FILE_LIST (gth_browser_get_file_list (browser)))) {
+			BrowserData *data;
+			GthTask     *task;
+
+			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,
+						     data->drop_pos);
+			gth_browser_exec_task (browser, task, FALSE);
+
+			g_object_unref (task);
 		}
+		else {
+			GthFileSource *file_source;
+			gboolean       cancel = FALSE;
+			gboolean       move;
+
+			file_source = gth_browser_get_location_source (browser);
+			move = context->suggested_action == GDK_ACTION_MOVE;
+			if (move && ! gth_file_source_can_cut (file_source)) {
+				GtkWidget *dialog;
+				int        response;
+
+				dialog = _gtk_message_dialog_new (GTK_WINDOW (browser),
+								  GTK_DIALOG_MODAL,
+								  GTK_STOCK_DIALOG_QUESTION,
+								  _("Could not move the files"),
+								  _("Files cannot be moved to the current location, as alternative you can choose to copy them."),
+								  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+								  GTK_STOCK_COPY, GTK_RESPONSE_OK,
+								  NULL);
+				response = gtk_dialog_run (GTK_DIALOG (dialog));
+				gtk_widget_destroy (dialog);
+
+				if (response == GTK_RESPONSE_CANCEL)
+					cancel = TRUE;
+
+				move = FALSE;
+			}
 
-		if (! cancel) {
-			GthTask *task;
+			if (! cancel) {
+				GthTask *task;
 
-			task = gth_copy_task_new (file_source,
-						  gth_browser_get_location_data (browser),
-						  move,
-						  file_list);
-			gth_browser_exec_task (browser, task, FALSE);
+				task = gth_copy_task_new (file_source,
+							  gth_browser_get_location_data (browser),
+							  move,
+							  file_list);
+				gth_browser_exec_task (browser, task, FALSE);
 
-			g_object_unref (task);
+				g_object_unref (task);
+			}
 		}
 	}
 
@@ -296,6 +312,75 @@ gth_file_list_drag_data_received (GtkWidget        *widget,
 }
 
 
+static gboolean
+gth_file_list_drag_drop (GtkWidget      *widget,
+			 GdkDragContext *context,
+			 gint            x,
+			 gint            y,
+			 guint           time,
+			 gpointer        user_data)
+{
+	g_print ("DRAG_DROP\n");
+
+	g_signal_stop_emission_by_name (widget, "drag-drop");
+	gtk_drag_get_data (widget,
+	                   context,
+	                   URI_LIST_TARGET,
+	                   time);
+
+	return TRUE;
+}
+
+
+static gboolean
+gth_file_list_drag_motion (GtkWidget          *widget,
+			   GdkDragContext     *context,
+			   gint                x,
+			   gint                y,
+			   guint               time,
+			   gpointer            extra_data)
+{
+	GthBrowser  *browser = extra_data;
+	BrowserData *data;
+	GtkWidget   *file_view;
+
+	g_print ("DRAG_MOTION\n");
+
+	data = g_object_get_data (G_OBJECT (browser), BROWSER_DATA_KEY);
+
+	file_view = gth_file_list_get_view (GTH_FILE_LIST (gth_browser_get_file_list (browser)));
+	if ((gtk_drag_get_source_widget (context) == file_view) && ! gth_file_source_is_reorderable (gth_browser_get_location_source (browser))) {
+		data->drop_pos = -1;
+		gdk_drag_status (context, 0, time);
+		return FALSE;
+	}
+
+	gdk_drag_status (context, GDK_ACTION_MOVE, time);
+	gth_file_view_set_drag_dest_pos (GTH_FILE_VIEW (file_view), context, x, y, time, &data->drop_pos);
+
+	return TRUE;
+}
+
+
+static gboolean
+gth_file_list_drag_leave (GtkWidget          *widget,
+			  GdkDragContext     *context,
+			  guint               time,
+			  gpointer            extra_data)
+{
+	GthBrowser *browser = extra_data;
+	GtkWidget  *file_view;
+
+	g_print ("DRAG_LEAVE\n");
+
+	file_view = gth_file_list_get_view (GTH_FILE_LIST (gth_browser_get_file_list (browser)));
+	if (gtk_drag_get_source_widget (context) == file_view)
+		gth_file_view_set_drag_dest_pos (GTH_FILE_VIEW (file_view), context, -1, -1, time, NULL);
+
+	return TRUE;
+}
+
+
 void
 fm__gth_browser_construct_cb (GthBrowser *browser)
 {
@@ -316,15 +401,26 @@ fm__gth_browser_construct_cb (GthBrowser *browser)
 	set_action_sensitive (data, "Edit_PasteInFolder", FALSE);
 
 	file_view = gth_file_list_get_view (GTH_FILE_LIST (gth_browser_get_file_list (browser)));
-	gtk_drag_dest_set (file_view,
-                           GTK_DEST_DEFAULT_ALL,
-                           drag_dest_targets,
-                           G_N_ELEMENTS (drag_dest_targets),
-                           GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK);
-	g_signal_connect (G_OBJECT (file_view),
+	gth_file_view_enable_drag_dest (GTH_FILE_VIEW (file_view),
+					drag_dest_targets,
+					G_N_ELEMENTS (drag_dest_targets),
+					GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK);
+	g_signal_connect (file_view,
                           "drag_data_received",
                           G_CALLBACK (gth_file_list_drag_data_received),
                           browser);
+	g_signal_connect (file_view,
+	                  "drag_drop",
+	                  G_CALLBACK (gth_file_list_drag_drop),
+	                  browser);
+	g_signal_connect (file_view,
+			  "drag_motion",
+			  G_CALLBACK (gth_file_list_drag_motion),
+			  browser);
+	g_signal_connect (file_view,
+	                  "drag_leave",
+	                  G_CALLBACK (gth_file_list_drag_leave),
+	                  browser);
 
 	g_object_set_data_full (G_OBJECT (browser), BROWSER_DATA_KEY, data, (GDestroyNotify) browser_data_free);
 }
diff --git a/extensions/file_manager/gth-reorder-task.c b/extensions/file_manager/gth-reorder-task.c
new file mode 100644
index 0000000..2b5630f
--- /dev/null
+++ b/extensions/file_manager/gth-reorder-task.c
@@ -0,0 +1,156 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Reorderright (C) 2009 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a reorder of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "gth-reorder-task.h"
+
+
+struct _GthReorderTaskPrivate {
+	GthFileSource *file_source;
+	GthFileData   *destination;
+	GList         *files;
+	int            new_pos;
+};
+
+
+static gpointer parent_class = NULL;
+
+
+static void
+gth_reorder_task_finalize (GObject *object)
+{
+	GthReorderTask *self;
+
+	self = GTH_REORDER_TASK (object);
+
+	_g_object_list_unref (self->priv->files);
+	_g_object_unref (self->priv->destination);
+	_g_object_unref (self->priv->file_source);
+
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+reorder_done_cb (GObject  *object,
+	         GError   *error,
+	         gpointer  user_data)
+{
+	gth_task_completed (GTH_TASK (user_data), error);
+}
+
+
+static void
+gth_reorder_task_exec (GthTask *task)
+{
+	GthReorderTask *self;
+
+	g_return_if_fail (GTH_IS_REORDER_TASK (task));
+
+	self = GTH_REORDER_TASK (task);
+
+	gth_file_source_reorder (self->priv->file_source,
+				 self->priv->destination,
+			         self->priv->files,
+			         self->priv->new_pos,
+			         reorder_done_cb,
+			         self);
+}
+
+
+static void
+gth_reorder_task_cancel (GthTask *task)
+{
+	gth_file_source_cancel (GTH_REORDER_TASK (task)->priv->file_source);
+}
+
+
+static void
+gth_reorder_task_class_init (GthReorderTaskClass *klass)
+{
+	GObjectClass *object_class;
+	GthTaskClass *task_class;
+
+	parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (GthReorderTaskPrivate));
+
+	object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = gth_reorder_task_finalize;
+
+	task_class = GTH_TASK_CLASS (klass);
+	task_class->exec = gth_reorder_task_exec;
+	task_class->cancel = gth_reorder_task_cancel;
+}
+
+
+static void
+gth_reorder_task_init (GthReorderTask *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_REORDER_TASK, GthReorderTaskPrivate);
+}
+
+
+GType
+gth_reorder_task_get_type (void)
+{
+	static GType type = 0;
+
+	if (! type) {
+		GTypeInfo type_info = {
+			sizeof (GthReorderTaskClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) gth_reorder_task_class_init,
+			NULL,
+			NULL,
+			sizeof (GthReorderTask),
+			0,
+			(GInstanceInitFunc) gth_reorder_task_init
+		};
+
+		type = g_type_register_static (GTH_TYPE_TASK,
+					       "GthReorderTask",
+					       &type_info,
+					       0);
+	}
+
+	return type;
+}
+
+
+GthTask *
+gth_reorder_task_new (GthFileSource *file_source,
+		      GthFileData   *destination,
+		      GList         *file_list,
+		      int            new_pos)
+{
+	GthReorderTask *self;
+
+	self = GTH_REORDER_TASK (g_object_new (GTH_TYPE_REORDER_TASK, NULL));
+
+	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);
+
+	return (GthTask *) self;
+}
diff --git a/extensions/file_manager/gth-reorder-task.h b/extensions/file_manager/gth-reorder-task.h
new file mode 100644
index 0000000..23b6419
--- /dev/null
+++ b/extensions/file_manager/gth-reorder-task.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Reorderright (C) 2009 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a reorder of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GTH_REORDER_TASK_H
+#define GTH_REORDER_TASK_H
+
+#include <glib.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_REORDER_TASK            (gth_reorder_task_get_type ())
+#define GTH_REORDER_TASK(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_REORDER_TASK, GthReorderTask))
+#define GTH_REORDER_TASK_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_REORDER_TASK, GthReorderTaskClass))
+#define GTH_IS_REORDER_TASK(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_REORDER_TASK))
+#define GTH_IS_REORDER_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_REORDER_TASK))
+#define GTH_REORDER_TASK_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_REORDER_TASK, GthReorderTaskClass))
+
+typedef struct _GthReorderTask        GthReorderTask;
+typedef struct _GthReorderTaskClass   GthReorderTaskClass;
+typedef struct _GthReorderTaskPrivate GthReorderTaskPrivate;
+
+struct _GthReorderTask {
+	GthTask __parent;
+	GthReorderTaskPrivate *priv;
+};
+
+struct _GthReorderTaskClass {
+	GthTaskClass __parent;
+};
+
+GType         gth_reorder_task_get_type  (void);
+GthTask *     gth_reorder_task_new       (GthFileSource *file_source,
+					  GthFileData   *destination,
+					  GList         *file_list,
+					  int            new_pos);
+
+G_END_DECLS
+
+#endif /* GTH_REORDER_TASK_H */
diff --git a/gthumb/gth-file-source.c b/gthumb/gth-file-source.c
index 4452d1c..6c34e86 100644
--- a/gthumb/gth-file-source.c
+++ b/gthumb/gth-file-source.c
@@ -50,7 +50,8 @@ typedef enum {
 	FILE_SOURCE_OP_LIST,
 	FILE_SOURCE_OP_READ_ATTRIBUTES,
 	FILE_SOURCE_OP_RENAME,
-	FILE_SOURCE_OP_COPY
+	FILE_SOURCE_OP_COPY,
+	FILE_SOURCE_OP_REORDER
 } FileSourceOp;
 
 
@@ -89,6 +90,15 @@ typedef struct {
 
 
 typedef struct {
+	GthFileData   *destination;
+	GList         *file_list;
+	int            dest_pos;
+	ReadyCallback  ready_callback;
+	gpointer       data;
+} ReorderData;
+
+
+typedef struct {
 	GthFileSource *file_source;
 	FileSourceOp   op;
 	union {
@@ -96,6 +106,7 @@ typedef struct {
 		ReadAttributesData read_attributes;
 		RenameData         rename;
 		CopyData           copy;
+		ReorderData        reorder;
 	} data;
 } FileSourceAsyncOp;
 
@@ -118,6 +129,10 @@ file_source_async_op_free (FileSourceAsyncOp *async_op)
 		g_object_unref (async_op->data.copy.destination);
 		_g_object_list_unref (async_op->data.copy.file_list);
 		break;
+	case FILE_SOURCE_OP_REORDER:
+		g_object_unref (async_op->data.copy.destination);
+		_g_object_list_unref (async_op->data.copy.file_list);
+		break;
 	}
 
 	g_free (async_op);
@@ -213,6 +228,29 @@ gth_file_source_queue_copy (GthFileSource    *file_source,
 
 
 static void
+gth_file_source_queue_reorder (GthFileSource    *file_source,
+			       GthFileData      *destination,
+			       GList            *file_list,
+			       int               dest_pos,
+			       ReadyCallback     ready_callback,
+			       gpointer          data)
+{
+	FileSourceAsyncOp *async_op;
+
+	async_op = g_new0 (FileSourceAsyncOp, 1);
+	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.dest_pos = dest_pos;
+	async_op->data.reorder.ready_callback = ready_callback;
+	async_op->data.reorder.data = data;
+
+	file_source->priv->queue = g_list_append (file_source->priv->queue, async_op);
+}
+
+
+static void
 gth_file_source_exec_next_in_queue (GthFileSource *file_source)
 {
 	GList             *head;
@@ -256,6 +294,14 @@ gth_file_source_exec_next_in_queue (GthFileSource *file_source)
 				      async_op->data.copy.ready_callback,
 				      async_op->data.copy.data);
 		break;
+	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.dest_pos,
+				         async_op->data.reorder.ready_callback,
+					 async_op->data.reorder.data);
+		break;
 	}
 
 	file_source_async_op_free (async_op);
@@ -393,6 +439,26 @@ base_monitor_directory (GthFileSource  *file_source,
 }
 
 
+static gboolean
+base_is_reorderable (GthFileSource *file_source)
+{
+	return FALSE;
+
+}
+
+
+static void
+base_reorder (GthFileSource *file_source,
+	      GthFileData   *destination,
+	      GList         *file_list, /* GFile * list */
+	      int            dest_pos,
+	      ReadyCallback  callback,
+	      gpointer       data)
+{
+	/* void */
+}
+
+
 static void
 gth_file_source_finalize (GObject *object)
 {
@@ -430,6 +496,8 @@ gth_file_source_class_init (GthFileSourceClass *class)
 	class->can_cut = base_can_cut;
 	class->monitor_entry_points = base_monitor_entry_points;
 	class->monitor_directory = base_monitor_directory;
+	class->is_reorderable = base_is_reorderable;
+	class->reorder = base_reorder;
 }
 
 
@@ -726,9 +794,33 @@ gth_file_source_monitor_entry_points (GthFileSource *file_source)
 
 
 void
-gth_file_source_monitor_directory (GthFileSource  *file_source,
-				   GFile          *file,
-				   gboolean        activate)
+gth_file_source_monitor_directory (GthFileSource *file_source,
+				   GFile         *file,
+				   gboolean       activate)
 {
 	GTH_FILE_SOURCE_GET_CLASS (G_OBJECT (file_source))->monitor_directory (file_source, file, activate);
 }
+
+
+gboolean
+gth_file_source_is_reorderable (GthFileSource *file_source)
+{
+	return GTH_FILE_SOURCE_GET_CLASS (G_OBJECT (file_source))->is_reorderable (file_source);
+}
+
+
+void
+gth_file_source_reorder (GthFileSource *file_source,
+			 GthFileData   *destination,
+		         GList         *file_list, /* 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);
+		return;
+	}
+	GTH_FILE_SOURCE_GET_CLASS (G_OBJECT (file_source))->reorder (file_source, destination, file_list, dest_pos, callback, data);
+}
+
diff --git a/gthumb/gth-file-source.h b/gthumb/gth-file-source.h
index 17014a2..efd373b 100644
--- a/gthumb/gth-file-source.h
+++ b/gthumb/gth-file-source.h
@@ -98,6 +98,13 @@ struct _GthFileSourceClass
 	void         (*monitor_directory)     (GthFileSource    *file_source,
 					       GFile            *file,
 					       gboolean          activate);
+	gboolean     (*is_reorderable)        (GthFileSource    *file_source);
+	void         (*reorder)               (GthFileSource    *file_source,
+					       GthFileData      *destination,
+					       GList            *file_list, /* GFile * list */
+					       int               dest_pos,
+					       ReadyCallback     callback,
+					       gpointer          data);
 };
 
 GType          gth_file_source_get_type              (void) G_GNUC_CONST;
@@ -146,6 +153,13 @@ void           gth_file_source_monitor_entry_points  (GthFileSource    *file_sou
 void           gth_file_source_monitor_directory     (GthFileSource    *file_source,
 						      GFile            *file,
 						      gboolean          activate);
+gboolean       gth_file_source_is_reorderable        (GthFileSource    *file_source);
+void           gth_file_source_reorder               (GthFileSource    *file_source,
+						      GthFileData      *destination,
+						      GList            *file_list, /* GFile * list */
+						      int               dest_pos,
+						      ReadyCallback     callback,
+						      gpointer          data);
 
 /*< protected >*/
 
diff --git a/gthumb/gth-file-view.c b/gthumb/gth-file-view.c
index c64936b..0f0625b 100644
--- a/gthumb/gth-file-view.c
+++ b/gthumb/gth-file-view.c
@@ -166,6 +166,18 @@ gth_file_view_unset_drag_dest (GthFileView *self)
 }
 
 
+void
+gth_file_view_set_drag_dest_pos (GthFileView    *self,
+				 GdkDragContext *context,
+			         int             x,
+			         int             y,
+			         guint           time,
+		                 int            *pos)
+{
+	GTH_FILE_VIEW_GET_INTERFACE (self)->set_drag_dest_pos (self, context, x, y, time, pos);
+}
+
+
 GType
 gth_file_view_get_type (void)
 {
diff --git a/gthumb/gth-file-view.h b/gthumb/gth-file-view.h
index 49a43d0..e1470a5 100644
--- a/gthumb/gth-file-view.h
+++ b/gthumb/gth-file-view.h
@@ -93,6 +93,12 @@ struct _GthFileViewIface {
 					      gint                  n_targets,
 					      GdkDragAction         actions);
 	void           (*unset_drag_dest)    (GthFileView          *self);
+	void           (*set_drag_dest_pos)  (GthFileView          *self,
+					      GdkDragContext       *context,
+			                      int                   x,
+			                      int                   y,
+			                      guint                 time,
+			                      int                  *pos);
 };
 
 GType          gth_file_view_get_type           (void);
@@ -131,6 +137,12 @@ void           gth_file_view_enable_drag_dest   (GthFileView          *self,
 				      		 int                   n_targets,
 				      		 GdkDragAction         actions);
 void           gth_file_view_unset_drag_dest    (GthFileView          *self);
+void           gth_file_view_set_drag_dest_pos  (GthFileView          *self,
+					         GdkDragContext       *context,
+			                         int                   x,
+			                         int                   y,
+			                         guint                 time,
+				                 int                  *pos);
 
 G_END_DECLS
 
diff --git a/gthumb/gth-icon-view.c b/gthumb/gth-icon-view.c
index 38e2570..e9c967b 100644
--- a/gthumb/gth-icon-view.c
+++ b/gthumb/gth-icon-view.c
@@ -249,6 +249,39 @@ gth_icon_view_unset_drag_dest (GthFileView *self)
 
 
 static void
+gth_icon_view_set_drag_dest_pos (GthFileView    *self,
+				 GdkDragContext *context,
+				 int             x,
+				 int             y,
+				 guint           time,
+				 int            *pos)
+{
+	GtkTreePath             *path = NULL;
+	GtkIconViewDropPosition  drop_pos;
+
+	if ((x >= 0) && (y >= 0) && gtk_icon_view_get_dest_item_at_pos (GTK_ICON_VIEW (self), x, y, &path, &drop_pos)) {
+		if (pos != NULL) {
+			int *indices;
+
+			indices = gtk_tree_path_get_indices (path);
+			*pos = indices[0];
+			if (drop_pos == GTK_ICON_VIEW_DROP_RIGHT)
+				*pos = *pos + 1;
+		}
+		gtk_icon_view_set_drag_dest_item (GTK_ICON_VIEW (self), path, drop_pos);
+	}
+	else {
+		if (pos != NULL)
+			*pos = -1;
+		gtk_icon_view_set_drag_dest_item (GTK_ICON_VIEW (self), NULL, GTK_ICON_VIEW_NO_DROP);
+	}
+
+	if (path != NULL)
+		gtk_tree_path_free (path);
+}
+
+
+static void
 gth_icon_view_real_set_selection_mode (GthFileSelection *base,
 				       GtkSelectionMode  mode)
 {
@@ -444,6 +477,7 @@ gth_icon_view_gth_file_view_interface_init (GthFileViewIface *iface)
 	iface->unset_drag_source = gth_icon_view_unset_drag_source;
 	iface->enable_drag_dest = gth_icon_view_enable_drag_dest;
 	iface->unset_drag_dest = gth_icon_view_unset_drag_dest;
+	iface->set_drag_dest_pos = gth_icon_view_set_drag_dest_pos;
 }
 
 
diff --git a/gthumb/gth-main.c b/gthumb/gth-main.c
index 52dd13b..65e597a 100644
--- a/gthumb/gth-main.c
+++ b/gthumb/gth-main.c
@@ -1061,7 +1061,7 @@ gth_main_get_default_tag_file (void)
 }
 
 
-const char **
+char **
 gth_main_get_all_tags (void)
 {
 	return gth_tags_file_get_tags (gth_main_get_default_tag_file ());
diff --git a/gthumb/gth-main.h b/gthumb/gth-main.h
index 3c77467..bf39fe4 100644
--- a/gthumb/gth-main.h
+++ b/gthumb/gth-main.h
@@ -110,7 +110,7 @@ GthFilterFile *        gth_main_get_default_filter_file       (void);
 GList *                gth_main_get_all_filters               (void);
 void                   gth_main_filters_changed               (void);
 GthTagsFile *          gth_main_get_default_tag_file          (void);
-const char **          gth_main_get_all_tags                  (void);
+char **                gth_main_get_all_tags                  (void);
 void                   gth_main_tags_changed                  (void);
 GthMonitor *           gth_main_get_default_monitor           (void);
 GthExtensionManager *  gth_main_get_default_extension_manager (void);
diff --git a/gthumb/gth-tags-entry.c b/gthumb/gth-tags-entry.c
index 090b1f9..8887974 100644
--- a/gthumb/gth-tags-entry.c
+++ b/gthumb/gth-tags-entry.c
@@ -331,7 +331,7 @@ update_tag_list (GthTagsEntry *self)
 	tags = gth_main_get_default_tag_file ();
 
 	g_strfreev (self->priv->tags);
-	self->priv->tags = g_strdupv ((char **)gth_tags_file_get_tags (tags));
+	self->priv->tags = g_strdupv (gth_tags_file_get_tags (tags));
 
 	for (i = 0; self->priv->tags[i] != NULL; i++) {
 		GtkTreeIter iter;
diff --git a/gthumb/gth-tags-file.c b/gthumb/gth-tags-file.c
index 7016299..83e3189 100644
--- a/gthumb/gth-tags-file.c
+++ b/gthumb/gth-tags-file.c
@@ -201,7 +201,7 @@ gth_tags_file_to_file (GthTagsFile  *tags,
 }
 
 
-const char **
+char **
 gth_tags_file_get_tags (GthTagsFile *tags)
 {
 	GList *scan;
diff --git a/gthumb/gth-tags-file.h b/gthumb/gth-tags-file.h
index aa3d15a..1045ac1 100644
--- a/gthumb/gth-tags-file.h
+++ b/gthumb/gth-tags-file.h
@@ -45,7 +45,7 @@ char *         gth_tags_file_to_data          (GthTagsFile  *tags,
 gboolean       gth_tags_file_to_file          (GthTagsFile  *tags,
                                                const char   *filename,
                                                GError      **error);
-const char **  gth_tags_file_get_tags         (GthTagsFile  *tags);
+char **        gth_tags_file_get_tags         (GthTagsFile  *tags);
 gboolean       gth_tags_file_has_tag          (GthTagsFile  *tags,
 					       const char   *tag);
 void           gth_tags_file_add              (GthTagsFile  *tags,



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