[gthumb/ext] load and save the catalog order



commit 2755d5601d70c1a2fb7c6527280f1069b809b500
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Mon Aug 24 18:38:54 2009 +0200

    load and save the catalog order

 extensions/catalogs/gth-catalog.c              |   44 +++-
 extensions/catalogs/gth-catalog.h              |    5 +
 extensions/catalogs/gth-file-source-catalogs.c |  255 ++++++++++++++++-
 extensions/rename_series/dlg-rename-series.c   |    3 +-
 gthumb/dlg-sort-order.c                        |    9 +-
 gthumb/gth-browser.c                           |  387 +++++++++++++----------
 gthumb/gth-file-source.c                       |  198 ++++++++++++
 gthumb/gth-file-source.h                       |   20 ++
 gthumb/gth-file-store.c                        |    5 +-
 gthumb/gth-filter.c                            |    2 +-
 gthumb/gth-main-default-sort-types.c           |   15 +-
 11 files changed, 752 insertions(+), 191 deletions(-)
---
diff --git a/extensions/catalogs/gth-catalog.c b/extensions/catalogs/gth-catalog.c
index aedb730..7996745 100644
--- a/extensions/catalogs/gth-catalog.c
+++ b/extensions/catalogs/gth-catalog.c
@@ -36,6 +36,8 @@ struct _GthCatalogPrivate {
 	GFile          *file;
 	GList          *file_list;
 	gboolean        active;
+	char           *order;
+	gboolean        order_inverse;
 	GCancellable   *cancellable;
 };
 
@@ -52,6 +54,7 @@ gth_catalog_finalize (GObject *object)
 		if (catalog->priv->file != NULL)
 			g_object_unref (catalog->priv->file);
 		_g_object_list_unref (catalog->priv->file_list);
+		g_free (catalog->priv->order);
 		g_free (catalog->priv);
 		catalog->priv = NULL;
 	}
@@ -88,6 +91,10 @@ read_catalog_data_from_xml (GthCatalog  *catalog,
 						catalog->priv->file_list = g_list_prepend (catalog->priv->file_list, g_file_new_for_uri (uri));
 				}
 			}
+			if (g_strcmp0 (child->tag_name, "order") == 0)
+				gth_catalog_set_order (catalog,
+						       dom_element_get_attribute (child, "type"),
+						       g_strcmp0 (dom_element_get_attribute (child, "inverse"), "1") == 0);
 		}
 		catalog->priv->file_list = g_list_reverse (catalog->priv->file_list);
 	}
@@ -178,18 +185,24 @@ base_to_data (GthCatalog *catalog,
 					    NULL);
 	dom_element_append_child (DOM_ELEMENT (doc), root);
 	if (catalog->priv->file_list != NULL) {
-		DomElement *uri_list;
+		DomElement *node;
 		GList      *scan;
 
-		uri_list = dom_document_create_element (doc, "files", NULL);
-		dom_element_append_child (root, uri_list);
+		if (catalog->priv->order != NULL)
+			dom_element_append_child (root, dom_document_create_element (doc, "order",
+										     "type", catalog->priv->order,
+										     "inverse", (catalog->priv->order_inverse ? "1" : "0"),
+										     NULL));
+
+		node = dom_document_create_element (doc, "files", NULL);
+		dom_element_append_child (root, node);
 
 		for (scan = catalog->priv->file_list; scan; scan = scan->next) {
 			GFile *file = scan->data;
 			char  *uri;
 
 			uri = g_file_get_uri (file);
-			dom_element_append_child (DOM_ELEMENT (uri_list), dom_document_create_element (doc, "file", "uri", uri, NULL));
+			dom_element_append_child (DOM_ELEMENT (node), dom_document_create_element (doc, "file", "uri", uri, NULL));
 
 			g_free (uri);
 		}
@@ -283,6 +296,29 @@ gth_catalog_get_file (GthCatalog *catalog)
 
 
 void
+gth_catalog_set_order (GthCatalog *catalog,
+		       const char *order,
+		       gboolean    inverse)
+{
+	g_free (catalog->priv->order);
+	catalog->priv->order = NULL;
+
+	if (order != NULL)
+		catalog->priv->order = g_strdup (order);
+	catalog->priv->order_inverse = inverse;
+}
+
+
+const char *
+gth_catalog_get_order (GthCatalog *catalog,
+		       gboolean   *inverse)
+{
+	*inverse = catalog->priv->order_inverse;
+	return catalog->priv->order;
+}
+
+
+void
 gth_catalog_load_from_data (GthCatalog  *catalog,
 			    const void  *buffer,
 			    gsize        count,
diff --git a/extensions/catalogs/gth-catalog.h b/extensions/catalogs/gth-catalog.h
index 4774ff9..b8520a9 100644
--- a/extensions/catalogs/gth-catalog.h
+++ b/extensions/catalogs/gth-catalog.h
@@ -75,6 +75,11 @@ GthCatalog *  gth_catalog_new            (void);
 void          gth_catalog_set_file       (GthCatalog           *catalog,
 					  GFile                *file);
 GFile *       gth_catalog_get_file       (GthCatalog           *catalog);
+void          gth_catalog_set_order      (GthCatalog           *catalog,
+					  const char           *order,
+					  gboolean              inverse);
+const char *  gth_catalog_get_order      (GthCatalog           *catalog,
+					  gboolean             *inverse);
 void          gth_catalog_load_from_data (GthCatalog           *catalog,
 					  const void           *buffer,
 					  gsize                 count,
diff --git a/extensions/catalogs/gth-file-source-catalogs.c b/extensions/catalogs/gth-file-source-catalogs.c
index 7dc179b..8ac4be5 100644
--- a/extensions/catalogs/gth-file-source-catalogs.c
+++ b/extensions/catalogs/gth-file-source-catalogs.c
@@ -182,6 +182,256 @@ gth_file_source_catalogs_get_file_data (GthFileSource *file_source,
 }
 
 
+/* -- gth_file_source_catalogs_write_metadata -- */
+
+
+typedef struct {
+	GthFileSourceCatalogs *catalogs;
+	GthFileData           *file_data;
+	char                  *attributes;
+	ReadyCallback          ready_callback;
+	gpointer               user_data;
+	GthCatalog            *catalog;
+} MetadataOpData;
+
+
+static void
+metadata_op_free (MetadataOpData *metadata_op)
+{
+	gth_file_source_set_active (GTH_FILE_SOURCE (metadata_op->catalogs), FALSE);
+	g_object_unref (metadata_op->file_data);
+	g_free (metadata_op->attributes);
+	g_object_unref (metadata_op->catalog);
+	g_free (metadata_op);
+}
+
+
+static void
+write_metadata_write_buffer_ready_cb (void     *buffer,
+				      gsize     count,
+				      GError   *error,
+				      gpointer  user_data)
+{
+	MetadataOpData        *metadata_op = user_data;
+	GthFileSourceCatalogs *catalogs = metadata_op->catalogs;
+
+	g_free (buffer);
+
+	metadata_op->ready_callback (G_OBJECT (catalogs), error, metadata_op->user_data);
+	metadata_op_free (metadata_op);
+}
+
+
+static void
+write_metadata_load_buffer_ready_cb (void     *buffer,
+				     gsize     count,
+				     GError   *error,
+				     gpointer  user_data)
+{
+	MetadataOpData        *metadata_op = user_data;
+	GthFileSourceCatalogs *catalogs = metadata_op->catalogs;
+	GFile                 *gio_file;
+
+	if (error != NULL) {
+		metadata_op->ready_callback (G_OBJECT (catalogs), error, metadata_op->user_data);
+		metadata_op_free (metadata_op);
+		return;
+	}
+
+	gth_catalog_load_from_data (metadata_op->catalog, buffer, count, &error);
+
+	if (error != NULL) {
+		metadata_op->ready_callback (G_OBJECT (catalogs), error, metadata_op->user_data);
+		metadata_op_free (metadata_op);
+		return;
+	}
+
+	if (_g_file_attributes_matches (metadata_op->attributes, "sort::*"))
+		gth_catalog_set_order (metadata_op->catalog,
+				       g_file_info_get_attribute_string (metadata_op->file_data->info, "sort::type"),
+				       g_file_info_get_attribute_boolean (metadata_op->file_data->info, "sort::inverse"));
+
+	buffer = gth_catalog_to_data (metadata_op->catalog, &count);
+	gio_file = gth_catalog_file_to_gio_file (metadata_op->file_data->file);
+	g_write_file_async (gio_file,
+			    buffer,
+			    count,
+			    G_PRIORITY_DEFAULT,
+			    gth_file_source_get_cancellable (GTH_FILE_SOURCE (metadata_op->catalogs)),
+			    write_metadata_write_buffer_ready_cb,
+			    metadata_op);
+
+	g_object_unref (gio_file);
+}
+
+
+static void
+gth_file_source_catalogs_write_metadata (GthFileSource *file_source,
+					 GthFileData   *file_data,
+					 const char    *attributes,
+					 ReadyCallback  callback,
+					 gpointer       user_data)
+{
+	GthFileSourceCatalogs *catalogs = (GthFileSourceCatalogs *) file_source;
+	char                  *uri;
+	MetadataOpData        *metadata_op;
+	GFile                 *gio_file;
+
+	uri = g_file_get_uri (file_data->file);
+	if (! g_str_has_suffix (uri, ".gqv")
+	    && ! g_str_has_suffix (uri, ".catalog")
+	    && ! g_str_has_suffix (uri, ".search"))
+	{
+		g_free (uri);
+		object_ready_with_error (file_source, callback, user_data, NULL);
+		return;
+	}
+
+	metadata_op = g_new0 (MetadataOpData, 1);
+	metadata_op->catalogs = catalogs;
+	metadata_op->file_data = g_object_ref (file_data);
+	metadata_op->attributes = g_strdup (attributes);
+	metadata_op->ready_callback = callback;
+	metadata_op->user_data = user_data;
+
+	gth_file_source_set_active (GTH_FILE_SOURCE (catalogs), TRUE);
+	g_cancellable_reset (gth_file_source_get_cancellable (file_source));
+
+	metadata_op->catalog = gth_catalog_new ();
+	gio_file = gth_file_source_to_gio_file (file_source, file_data->file);
+	gth_catalog_set_file (metadata_op->catalog, gio_file);
+	g_load_file_async (gio_file,
+			   G_PRIORITY_DEFAULT,
+			   gth_file_source_get_cancellable (file_source),
+			   write_metadata_load_buffer_ready_cb,
+			   metadata_op);
+
+	g_object_unref (gio_file);
+	g_free (uri);
+}
+
+
+/* -- gth_file_source_catalogs_read_metadata -- */
+
+
+typedef struct {
+	GthFileSource *file_source;
+	GthFileData   *file_data;
+	char          *attributes;
+	ReadyCallback  callback;
+	gpointer       data;
+} ReadMetadataOpData;
+
+
+static void
+read_metadata_free (ReadMetadataOpData *read_metadata)
+{
+	g_object_unref (read_metadata->file_source);
+	g_object_unref (read_metadata->file_data);
+	g_free (read_metadata->attributes);
+	g_free (read_metadata);
+}
+
+
+static void
+read_metadata_catalog_ready_cb (GObject  *object,
+				GError   *error,
+				gpointer  user_data)
+{
+	ReadMetadataOpData *read_metadata = user_data;
+	GthCatalog         *catalog;
+	const char         *sort_type;
+	gboolean            sort_inverse;
+
+	if (object == NULL) {
+		read_metadata->callback (G_OBJECT (read_metadata->file_source), error, read_metadata->data);
+		read_metadata_free (read_metadata);
+		return;
+	}
+
+	catalog = GTH_CATALOG (object);
+	sort_type = gth_catalog_get_order (catalog, &sort_inverse);
+	if (sort_type != NULL) {
+		g_file_info_set_attribute_string (read_metadata->file_data->info, "sort::type", sort_type);
+		g_file_info_set_attribute_boolean (read_metadata->file_data->info, "sort::inverse", sort_inverse);
+	}
+
+	read_metadata->callback (G_OBJECT (read_metadata->file_source), error, read_metadata->data);
+
+	g_object_unref (catalog);
+	read_metadata_free (read_metadata);
+}
+
+
+static void
+read_metadata_info_ready_cb (GList    *files,
+			     GError   *error,
+			     gpointer  user_data)
+{
+	ReadMetadataOpData *read_metadata = user_data;
+	GthFileData        *result;
+
+	if (error != NULL) {
+		read_metadata->callback (G_OBJECT (read_metadata->file_source), error, read_metadata->data);
+		read_metadata_free (read_metadata);
+		return;
+	}
+
+	result = files->data;
+	g_file_info_copy_into (result->info, read_metadata->file_data->info);
+
+	if (_g_file_attributes_matches (read_metadata->attributes, "sort::*")) {
+		GFile *gio_file;
+
+		gio_file = gth_catalog_file_to_gio_file (read_metadata->file_data->file);
+		gth_catalog_load_from_file (gio_file,
+					    gth_file_source_get_cancellable (read_metadata->file_source),
+					    read_metadata_catalog_ready_cb,
+					    read_metadata);
+
+		g_object_unref (gio_file);
+	}
+	else {
+		read_metadata->callback (G_OBJECT (read_metadata->file_source), NULL, read_metadata->data);
+		read_metadata_free (read_metadata);
+	}
+}
+
+
+static void
+gth_file_source_catalogs_read_metadata (GthFileSource *file_source,
+					GthFileData   *file_data,
+					const char    *attributes,
+					ReadyCallback  callback,
+					gpointer       data)
+{
+	ReadMetadataOpData *read_metadata;
+	GFile              *gio_file;
+	GList              *files;
+
+	read_metadata = g_new0 (ReadMetadataOpData, 1);
+	read_metadata->file_source = g_object_ref (file_source);
+	read_metadata->file_data = g_object_ref (file_data);
+	read_metadata->attributes = g_strdup (attributes);
+	read_metadata->callback = callback;
+	read_metadata->data = data;
+
+	gio_file = gth_catalog_file_to_gio_file (file_data->file);
+	files = g_list_prepend (NULL, gio_file);
+	_g_query_all_metadata_async (files,
+				     FALSE,
+				     TRUE,
+				     attributes,
+				     gth_file_source_get_cancellable (file_source),
+				     read_metadata_info_ready_cb,
+				     read_metadata);
+
+	_g_object_list_unref (files);
+}
+
+
+/* -- list -- */
+
 
 static void
 list__done_func (GError   *error,
@@ -248,7 +498,6 @@ catalog_list_ready_cb (GthCatalog *catalog,
 
 	gth_catalog_set_file_list (catalogs->priv->catalog, NULL);
 	g_object_unref (catalogs);
-
 	if (G_IS_OBJECT (catalogs))
 		gth_file_source_set_active (GTH_FILE_SOURCE (catalogs), FALSE);
 }
@@ -475,6 +724,7 @@ typedef struct {
 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_unref (reorder_data->destination);
 	_g_object_unref (reorder_data->file_source);
@@ -547,6 +797,7 @@ reorder_catalog_ready_cb (GObject  *object,
 
 	catalog = (GthCatalog *) object;
 	reorder_catalog_list (catalog, reorder_data->file_list, reorder_data->dest_pos);
+	gth_catalog_set_order (catalog, "general::unsorted", FALSE);
 
 	buffer = gth_catalog_to_data (catalog, &buffer_size);
 	gio_file = gth_file_source_to_gio_file (reorder_data->file_source, reorder_data->destination->file);
@@ -629,6 +880,8 @@ gth_file_source_catalogs_class_init (GthFileSourceCatalogsClass *class)
 	file_source_class->to_gio_file = gth_file_source_catalogs_to_gio_file;
 	file_source_class->get_file_info = gth_file_source_catalogs_get_file_info;
 	file_source_class->get_file_data = gth_file_source_catalogs_get_file_data;
+	file_source_class->write_metadata = gth_file_source_catalogs_write_metadata;
+	file_source_class->read_metadata = gth_file_source_catalogs_read_metadata;
 	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;
diff --git a/extensions/rename_series/dlg-rename-series.c b/extensions/rename_series/dlg-rename-series.c
index 5b82d03..94a632f 100644
--- a/extensions/rename_series/dlg-rename-series.c
+++ b/extensions/rename_series/dlg-rename-series.c
@@ -261,7 +261,8 @@ dlg_rename_series_update_preview (DialogData *data)
 				    SORT_DATA_COLUMN, &sort_type,
 				    -1);
 
-		data->new_file_list = g_list_sort (data->new_file_list, (GCompareFunc) sort_type->cmp_func);
+		if (sort_type->cmp_func != NULL)
+			data->new_file_list = g_list_sort (data->new_file_list, (GCompareFunc) sort_type->cmp_func);
 	}
 	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("reverse_order_checkbutton"))))
 		data->new_file_list = g_list_reverse (data->new_file_list);
diff --git a/gthumb/dlg-sort-order.c b/gthumb/dlg-sort-order.c
index 92a46d8..a08636e 100644
--- a/gthumb/dlg-sort-order.c
+++ b/gthumb/dlg-sort-order.c
@@ -81,6 +81,7 @@ dlg_sort_order (GthBrowser *browser)
 	DialogData      *data;
 	GtkListStore    *selection_model;
 	GtkCellRenderer *renderer;
+	GthFileData     *file_data;
 	GList           *scan;
 	GthFileDataSort *current_sort_type;
 	gboolean         sort_inverse;
@@ -116,7 +117,13 @@ dlg_sort_order (GthBrowser *browser)
 					"text", SELECTION_COLUMN_NAME,
 					NULL);
   	
-  	gth_browser_get_sort_order (data->browser, &current_sort_type, &sort_inverse);  	
+	file_data = gth_browser_get_location_data (data->browser);
+	if (file_data != NULL) {
+		current_sort_type = gth_main_get_sort_type (g_file_info_get_attribute_string (file_data->info, "sort::type"));
+		sort_inverse = g_file_info_get_attribute_boolean (file_data->info, "sort::inverse");
+	}
+	else
+		gth_browser_get_sort_order (data->browser, &current_sort_type, &sort_inverse);
 
 	for (i = 0, i_active = 0, scan = gth_main_get_all_sort_types (); scan; scan = scan->next, i++) {
 		GthFileDataSort *sort_type = scan->data;
diff --git a/gthumb/gth-browser.c b/gthumb/gth-browser.c
index 820fba7..35340db 100644
--- a/gthumb/gth-browser.c
+++ b/gthumb/gth-browser.c
@@ -866,7 +866,7 @@ _gth_browser_update_statusbar_list_info (GthBrowser *browser)
 
 typedef struct {
 	GthBrowser    *browser;
-	GFile         *requested_folder;
+	GthFileData   *requested_folder;
 	GFile         *requested_folder_parent;
 	GthAction      action;
 	gboolean       automatic;
@@ -890,8 +890,8 @@ load_data_new (GthBrowser *browser,
 
 	load_data = g_new0 (LoadData, 1);
 	load_data->browser = browser;
-	load_data->requested_folder = g_object_ref (location);
-	load_data->requested_folder_parent = g_file_get_parent (load_data->requested_folder);
+	load_data->requested_folder = gth_file_data_new (location, NULL);
+	load_data->requested_folder_parent = g_file_get_parent (load_data->requested_folder->file);
 	load_data->action = action;
 	load_data->automatic = automatic;
 	load_data->cancellable = g_cancellable_new ();
@@ -900,9 +900,9 @@ load_data_new (GthBrowser *browser,
 		return load_data;
 
 	load_data->entry_point = g_object_ref (entry_point);
-	load_data->file_source = gth_main_get_file_source (load_data->requested_folder);
+	load_data->file_source = gth_main_get_file_source (load_data->requested_folder->file);
 
-	file = g_object_ref (load_data->requested_folder);
+	file = g_object_ref (load_data->requested_folder->file);
 	load_data->list = g_list_prepend (NULL, g_object_ref (file));
 	while (! g_file_equal (load_data->entry_point, file)) {
 		GFile *parent;
@@ -958,7 +958,7 @@ load_data_done (LoadData *load_data,
 	{
 		char *uri;
 
-		uri = g_file_get_uri (load_data->requested_folder);
+		uri = g_file_get_uri (load_data->requested_folder->file);
 		debug (DEBUG_INFO, "LOAD READY: %s [%s]\n", uri, (error == NULL ? "Ok" : "Error"));
 		performance (DEBUG_INFO, "load done for %s", uri);
 
@@ -969,7 +969,7 @@ load_data_done (LoadData *load_data,
 	g_signal_emit (G_OBJECT (browser),
 		       gth_browser_signals[LOCATION_READY],
 		       0,
-		       load_data->requested_folder,
+		       load_data->requested_folder->file,
 		       (error != NULL));
 
 	if (error == NULL) {
@@ -977,7 +977,7 @@ load_data_done (LoadData *load_data,
 		browser->priv->location_source = g_object_ref (load_data->file_source);
 	}
 
-	gth_hook_invoke ("gth-browser-load-location-after", browser, load_data->requested_folder, error);
+	gth_hook_invoke ("gth-browser-load-location-after", browser, load_data->requested_folder->file, error);
 
 	if (error == NULL)
 		return;
@@ -990,7 +990,7 @@ load_data_done (LoadData *load_data,
 	if (load_data->automatic) {
 		GFile *parent;
 
-		parent = g_file_get_parent (load_data->requested_folder);
+		parent = g_file_get_parent (load_data->requested_folder->file);
 		if (parent != NULL) {
 			_gth_browser_load (load_data->browser,
 					   parent,
@@ -1010,13 +1010,11 @@ static void _gth_browser_load_ready_cb (GthFileSource *file_source, GList *files
 
 
 static void
-requested_folder_attributes_ready_cb (GthFileSource *file_source,
-				      GList         *files,
-				      GError        *error,
-				      gpointer       user_data)
+requested_folder_attributes_ready_cb (GObject  *file_source,
+				      GError   *error,
+				      gpointer  user_data)
 {
-	LoadData    *load_data = user_data;
-	GthFileData *requested_folder_data;
+	LoadData *load_data = user_data;
 
 	if (error != NULL) {
 		load_data_done (load_data, error);
@@ -1024,11 +1022,10 @@ requested_folder_attributes_ready_cb (GthFileSource *file_source,
 		return;
 	}
 
-	requested_folder_data = (GthFileData *) files->data;
-	gth_file_data_set_info (load_data->browser->priv->location, requested_folder_data->info);
+	gth_file_data_set_info (load_data->browser->priv->location, load_data->requested_folder->info);
 
 	gth_file_source_list (load_data->file_source,
-			      load_data->requested_folder,
+			      load_data->requested_folder->file,
 			      eel_gconf_get_boolean (PREF_FAST_FILE_TYPE, TRUE) ? GFILE_STANDARD_ATTRIBUTES_WITH_FAST_CONTENT_TYPE : GFILE_STANDARD_ATTRIBUTES_WITH_CONTENT_TYPE,
 			      _gth_browser_load_ready_cb,
 			      load_data);
@@ -1051,7 +1048,7 @@ load_data_load_next_folder (LoadData *load_data)
 			load_data->current = load_data->current->next;
 		folder_to_load = (GFile *) load_data->current->data;
 
-		if (g_file_equal (folder_to_load, load_data->requested_folder))
+		if (g_file_equal (folder_to_load, load_data->requested_folder->file))
 			break;
 
 		if ((load_data->requested_folder_parent != NULL) && g_file_equal (folder_to_load, load_data->requested_folder_parent))
@@ -1066,25 +1063,19 @@ load_data_load_next_folder (LoadData *load_data)
 			break;
 		}
 
-		if (! g_file_equal (folder_to_load, load_data->requested_folder))
+		if (! g_file_equal (folder_to_load, load_data->requested_folder->file))
 			gth_folder_tree_expand_row (folder_tree, path, FALSE);
 
 		gtk_tree_path_free (path);
 	}
 	while (TRUE);
 
-	if (g_file_equal (folder_to_load, load_data->requested_folder)) {
-		GList *files;
-
-		files = g_list_prepend (NULL, folder_to_load);
-		gth_file_source_read_attributes (load_data->file_source,
-						 files,
-						 GFILE_BASIC_ATTRIBUTES ",access::*",
-						 requested_folder_attributes_ready_cb,
-						 load_data);
-
-		g_list_free (files);
-	}
+	if (g_file_equal (folder_to_load, load_data->requested_folder->file))
+		gth_file_source_read_metadata (load_data->file_source,
+					       load_data->requested_folder,
+					       GFILE_BASIC_ATTRIBUTES ",access::*,sort::*",
+					       requested_folder_attributes_ready_cb,
+     					       load_data);
 	else
 		gth_file_source_list (load_data->file_source,
 				      folder_to_load,
@@ -1123,117 +1114,7 @@ _gth_browser_get_visible_folders (GthBrowser *browser,
 }
 
 
-static void
-load_data_continue (LoadData *load_data,
-		    GList    *loaded_files)
-{
-	GthBrowser  *browser = load_data->browser;
-	GList       *files;
-	GFile       *loaded_folder;
-	GtkTreePath *path;
-	GthTest     *filter;
-
-	if ((load_data->action != GTH_ACTION_LIST_CHILDREN)
-	    && ! g_file_equal (load_data->requested_folder, load_data->browser->priv->location->file))
-	{
-		load_data_done (load_data, g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED, ""));
-		load_data_free (load_data);
-		return;
-	}
-
-	files = _gth_browser_get_visible_folders (browser, loaded_files);
-
-	loaded_folder = (GFile *) load_data->current->data;
-	gth_folder_tree_set_children (GTH_FOLDER_TREE (browser->priv->folder_tree), loaded_folder, files);
-	path = gth_folder_tree_get_path (GTH_FOLDER_TREE (browser->priv->folder_tree), loaded_folder);
-	if ((path != NULL) && ! g_file_equal (loaded_folder, load_data->requested_folder))
-		gth_folder_tree_expand_row (GTH_FOLDER_TREE (browser->priv->folder_tree), path, FALSE);
-
-	if (! g_file_equal (loaded_folder, load_data->requested_folder)) {
-		gtk_tree_path_free (path);
-		_g_object_list_unref (files);
-
-		load_data_load_next_folder (load_data);
-		return;
-	}
-
-	load_data_done (load_data, NULL);
-
-	switch (load_data->action) {
-	case GTH_ACTION_VIEW:
-	case GTH_ACTION_GO_BACK:
-	case GTH_ACTION_GO_FORWARD:
-	case GTH_ACTION_GO_TO:
-		if (path != NULL) {
-			GList *entry_points;
-			GList *scan;
-
-			gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (browser->priv->folder_tree), path, NULL, FALSE, .0, .0);
-			gth_folder_tree_select_path (GTH_FOLDER_TREE (browser->priv->folder_tree), path);
-
-			/* expand the path if it's an entry point */
-
-			entry_points = gth_main_get_all_entry_points ();
-			for (scan = entry_points; scan; scan = scan->next) {
-				GthFileData *file_data = scan->data;
-
-				if (g_file_equal (file_data->file, load_data->requested_folder)) {
-					gtk_tree_view_expand_row (GTK_TREE_VIEW (browser->priv->folder_tree), path, FALSE);
-					break;
-				}
-			}
-
-			_g_object_list_unref (entry_points);
-		}
-		break;
-	default:
-		break;
-	}
-
-	switch (load_data->action) {
-	case GTH_ACTION_VIEW:
-	case GTH_ACTION_GO_BACK:
-	case GTH_ACTION_GO_FORWARD:
-	case GTH_ACTION_GO_INTO:
-	case GTH_ACTION_GO_TO:
-		filter = _gth_browser_get_file_filter (browser);
-		gth_file_list_set_filter (GTH_FILE_LIST (browser->priv->file_list), filter);
-		gth_file_list_set_files (GTH_FILE_LIST (browser->priv->file_list), files);
-		g_object_unref (filter);
-		break;
-	default:
-		break;
-	}
-
-	gth_browser_update_sensitivity (browser);
-	_gth_browser_update_statusbar_list_info (browser);
-
-	gth_file_source_monitor_directory (browser->priv->location_source,
-					   browser->priv->location->file,
-					   TRUE);
-
-	if (path != NULL)
-		gtk_tree_path_free (path);
-	load_data_free (load_data);
-	_g_object_list_unref (files);
-}
-
-
-static void
-metadata_ready_cb (GList    *files,
-		   GError   *error,
-		   gpointer  user_data)
-{
-	LoadData *load_data = user_data;
-
-	if (error != NULL) {
-		load_data_done (load_data, error);
-		load_data_free (load_data);
-		return;
-	}
-
-	load_data_continue (load_data, files);
-}
+/* -- _gth_browser_set_sort_order -- */
 
 
 static const char *
@@ -1272,7 +1153,7 @@ _gth_browser_get_list_attributes (GthBrowser *browser)
 
 	/* attributes required for sorting */
 
-	if (browser->priv->sort_type->required_attributes[0] != '\0') {
+	if ((browser->priv->sort_type != NULL) && (browser->priv->sort_type->required_attributes[0] != '\0')) {
 		g_string_append (attributes, ",");
 		g_string_append (attributes, browser->priv->sort_type->required_attributes);
 	}
@@ -1366,6 +1247,184 @@ _gth_browser_reload_required (GthBrowser *browser)
 
 
 static void
+write_sort_order_ready_cb (GObject  *source,
+		           GError   *error,
+		           gpointer  user_data)
+{
+	GthBrowser *browser = user_data;
+
+	if (browser->priv->constructed && _gth_browser_reload_required (browser))
+		gth_browser_reload (browser);
+}
+
+
+static void
+_gth_browser_set_sort_order (GthBrowser      *browser,
+			     GthFileDataSort *sort_type,
+			     gboolean         inverse,
+			     gboolean         save)
+{
+	if (save) {
+		browser->priv->sort_type = sort_type;
+		browser->priv->sort_inverse = inverse;
+	}
+
+	if (sort_type != NULL)
+		gth_file_list_set_sort_func (GTH_FILE_LIST (browser->priv->file_list),
+					     sort_type->cmp_func,
+					     inverse);
+	else
+		gth_file_list_set_sort_func (GTH_FILE_LIST (browser->priv->file_list),
+					     NULL,
+					     FALSE);
+	gth_browser_update_title (browser);
+
+	if (! browser->priv->constructed)
+		return;
+
+	if (! save) {
+		write_sort_order_ready_cb (G_OBJECT (browser->priv->location_source), NULL, browser);
+		return;
+	}
+
+	g_file_info_set_attribute_string (browser->priv->location->info, "sort::type", sort_type != NULL ? sort_type->name : "manual");
+	g_file_info_set_attribute_boolean (browser->priv->location->info, "sort::inverse", sort_type != NULL ? inverse : FALSE);
+	gth_file_source_write_metadata (browser->priv->location_source,
+					browser->priv->location,
+					"sort::type,sort::inverse",
+					write_sort_order_ready_cb,
+					browser);
+}
+
+
+static void
+load_data_continue (LoadData *load_data,
+		    GList    *loaded_files)
+{
+	GthBrowser  *browser = load_data->browser;
+	GList       *files;
+	GFile       *loaded_folder;
+	GtkTreePath *path;
+	GthTest     *filter;
+
+	if ((load_data->action != GTH_ACTION_LIST_CHILDREN)
+	    && ! g_file_equal (load_data->requested_folder->file, load_data->browser->priv->location->file))
+	{
+		load_data_done (load_data, g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED, ""));
+		load_data_free (load_data);
+		return;
+	}
+
+	files = _gth_browser_get_visible_folders (browser, loaded_files);
+
+	loaded_folder = (GFile *) load_data->current->data;
+	gth_folder_tree_set_children (GTH_FOLDER_TREE (browser->priv->folder_tree), loaded_folder, files);
+	path = gth_folder_tree_get_path (GTH_FOLDER_TREE (browser->priv->folder_tree), loaded_folder);
+	if ((path != NULL) && ! g_file_equal (loaded_folder, load_data->requested_folder->file))
+		gth_folder_tree_expand_row (GTH_FOLDER_TREE (browser->priv->folder_tree), path, FALSE);
+
+	if (! g_file_equal (loaded_folder, load_data->requested_folder->file)) {
+		gtk_tree_path_free (path);
+		_g_object_list_unref (files);
+
+		load_data_load_next_folder (load_data);
+		return;
+	}
+
+	load_data_done (load_data, NULL);
+
+	switch (load_data->action) {
+	case GTH_ACTION_VIEW:
+	case GTH_ACTION_GO_BACK:
+	case GTH_ACTION_GO_FORWARD:
+	case GTH_ACTION_GO_TO:
+		if (path != NULL) {
+			GList *entry_points;
+			GList *scan;
+
+			gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (browser->priv->folder_tree), path, NULL, FALSE, .0, .0);
+			gth_folder_tree_select_path (GTH_FOLDER_TREE (browser->priv->folder_tree), path);
+
+			/* expand the path if it's an entry point */
+
+			entry_points = gth_main_get_all_entry_points ();
+			for (scan = entry_points; scan; scan = scan->next) {
+				GthFileData *file_data = scan->data;
+
+				if (g_file_equal (file_data->file, load_data->requested_folder->file)) {
+					gtk_tree_view_expand_row (GTK_TREE_VIEW (browser->priv->folder_tree), path, FALSE);
+					break;
+				}
+			}
+
+			_g_object_list_unref (entry_points);
+		}
+		break;
+	default:
+		break;
+	}
+
+	{
+		GthFileDataSort *sort_type;
+		gboolean         sort_inverse;
+
+		sort_type = gth_main_get_sort_type (g_file_info_get_attribute_string (browser->priv->location->info, "sort::type"));
+		sort_inverse = g_file_info_get_attribute_boolean (browser->priv->location->info, "sort::inverse");
+		if (sort_type == NULL) {
+			g_file_info_set_attribute_string (browser->priv->location->info, "sort::type", browser->priv->sort_type->name);
+			g_file_info_set_attribute_boolean (browser->priv->location->info, "sort::inverse", browser->priv->sort_inverse);
+		}
+
+		_gth_browser_set_sort_order (browser, sort_type, sort_inverse, FALSE);
+	}
+
+	switch (load_data->action) {
+	case GTH_ACTION_VIEW:
+	case GTH_ACTION_GO_BACK:
+	case GTH_ACTION_GO_FORWARD:
+	case GTH_ACTION_GO_INTO:
+	case GTH_ACTION_GO_TO:
+		filter = _gth_browser_get_file_filter (browser);
+		gth_file_list_set_filter (GTH_FILE_LIST (browser->priv->file_list), filter);
+		gth_file_list_set_files (GTH_FILE_LIST (browser->priv->file_list), files);
+		g_object_unref (filter);
+		break;
+	default:
+		break;
+	}
+
+	gth_browser_update_sensitivity (browser);
+	_gth_browser_update_statusbar_list_info (browser);
+
+	gth_file_source_monitor_directory (browser->priv->location_source,
+					   browser->priv->location->file,
+					   TRUE);
+
+	if (path != NULL)
+		gtk_tree_path_free (path);
+	load_data_free (load_data);
+	_g_object_list_unref (files);
+}
+
+
+static void
+metadata_ready_cb (GList    *files,
+		   GError   *error,
+		   gpointer  user_data)
+{
+	LoadData *load_data = user_data;
+
+	if (error != NULL) {
+		load_data_done (load_data, error);
+		load_data_free (load_data);
+		return;
+	}
+
+	load_data_continue (load_data, files);
+}
+
+
+static void
 load_data_ready (LoadData *data,
 		 GList    *files,
 		 GError   *error)
@@ -1374,7 +1433,7 @@ load_data_ready (LoadData *data,
 		load_data_done (data, error);
 		load_data_free (data);
 	}
-	else if (g_file_equal ((GFile *) data->current->data, data->requested_folder))
+	else if (g_file_equal ((GFile *) data->current->data, data->requested_folder->file))
 		_g_query_metadata_async (files,
 					 _gth_browser_get_list_attributes (data->browser),
 					 data->cancellable,
@@ -1499,7 +1558,7 @@ _gth_browser_load (GthBrowser *browser,
 	entry_point = get_nearest_entry_point (location);
 	load_data = load_data_new (browser, location, action, automatic, entry_point);
 
-	gth_hook_invoke ("gth-browser-load-location-before", browser, load_data->requested_folder);
+	gth_hook_invoke ("gth-browser-load-location-before", browser, load_data->requested_folder->file);
 	browser->priv->activity_ref++;
 
 	if (entry_point == NULL) {
@@ -1533,7 +1592,7 @@ _gth_browser_load (GthBrowser *browser,
 		GError *error;
 		char   *uri;
 
-		uri = g_file_get_uri (load_data->requested_folder);
+		uri = g_file_get_uri (load_data->requested_folder->file);
 		error = g_error_new (GTHUMB_ERROR, 0, _("No suitable module found for %s"), uri);
 		load_data_ready (load_data, NULL, error);
 
@@ -1546,13 +1605,13 @@ _gth_browser_load (GthBrowser *browser,
 	case GTH_ACTION_GO_INTO:
 	case GTH_ACTION_GO_TO:
 	case GTH_ACTION_VIEW:
-		_gth_browser_set_location_from_file (browser, load_data->requested_folder);
+		_gth_browser_set_location_from_file (browser, load_data->requested_folder->file);
 		_gth_browser_add_to_history (browser, browser->priv->location->file);
 		_gth_browser_update_history_list (browser);
 		break;
 	case GTH_ACTION_GO_BACK:
 	case GTH_ACTION_GO_FORWARD:
-		_gth_browser_set_location_from_file (browser, load_data->requested_folder);
+		_gth_browser_set_location_from_file (browser, load_data->requested_folder->file);
 		_gth_browser_update_history_list (browser);
 		break;
 	default:
@@ -1562,7 +1621,7 @@ _gth_browser_load (GthBrowser *browser,
 	{
 		char *uri;
 
-		uri = g_file_get_uri (load_data->requested_folder);
+		uri = g_file_get_uri (load_data->requested_folder->file);
 
 		debug (DEBUG_INFO, "LOAD: %s\n", uri);
 		performance (DEBUG_INFO, "loading %s", uri);
@@ -1728,8 +1787,10 @@ _gth_browser_close_final_step (gpointer user_data)
 			g_free (uri);
 		}
 
-		eel_gconf_set_string (PREF_SORT_TYPE, browser->priv->sort_type->name);
-		eel_gconf_set_boolean (PREF_SORT_INVERSE, browser->priv->sort_inverse);
+		if (browser->priv->sort_type != NULL) {
+			eel_gconf_set_string (PREF_SORT_TYPE, browser->priv->sort_type->name);
+			eel_gconf_set_boolean (PREF_SORT_INVERSE, browser->priv->sort_inverse);
+		}
 
 		gth_hook_invoke ("gth-browser-close-last-window", browser);
 	}
@@ -2300,6 +2361,11 @@ folder_changed_cb (GthMonitor      *monitor,
 		return;
 	}
 
+	if ((event == GTH_MONITOR_EVENT_CHANGED) && (_g_file_list_find_file_or_ancestor (list, browser->priv->location->file) != NULL)) {
+		_gth_browser_load (browser, browser->priv->location->file, GTH_ACTION_GO_TO, TRUE);
+		return;
+	}
+
 #if 0
 {
 	GList *scan;
@@ -3565,22 +3631,7 @@ gth_browser_set_sort_order (GthBrowser      *browser,
 			    GthFileDataSort *sort_type,
 			    gboolean         inverse)
 {
-	if (sort_type == NULL) {
-		gth_browser_set_sort_order (browser,
-					    gth_main_get_sort_type ("gth::file::mtime"),
-					    inverse);
-		return;
-	}
-
-	browser->priv->sort_type = sort_type;
-	browser->priv->sort_inverse = inverse;
-	gth_file_list_set_sort_func (GTH_FILE_LIST (browser->priv->file_list),
-				     browser->priv->sort_type->cmp_func,
-				     browser->priv->sort_inverse);
-	gth_browser_update_title (browser);
-
-	if (browser->priv->constructed && _gth_browser_reload_required (browser))
-		gth_browser_reload (browser);
+	_gth_browser_set_sort_order (browser, sort_type, inverse, TRUE);
 }
 
 
diff --git a/gthumb/gth-file-source.c b/gthumb/gth-file-source.c
index 6c34e86..75ea724 100644
--- a/gthumb/gth-file-source.c
+++ b/gthumb/gth-file-source.c
@@ -47,6 +47,8 @@ static GObjectClass *parent_class = NULL;
 
 
 typedef enum {
+	FILE_SOURCE_OP_WRITE_METADATA,
+	FILE_SOURCE_OP_READ_METADATA,
 	FILE_SOURCE_OP_LIST,
 	FILE_SOURCE_OP_READ_ATTRIBUTES,
 	FILE_SOURCE_OP_RENAME,
@@ -99,6 +101,22 @@ typedef struct {
 
 
 typedef struct {
+	GthFileData   *file_data;
+	char          *attributes;
+	ReadyCallback  ready_callback;
+	gpointer       data;
+} WriteMetadataData;
+
+
+typedef struct {
+	GthFileData   *file_data;
+	char          *attributes;
+	ReadyCallback  ready_callback;
+	gpointer       data;
+} ReadMetadataData;
+
+
+typedef struct {
 	GthFileSource *file_source;
 	FileSourceOp   op;
 	union {
@@ -107,6 +125,8 @@ typedef struct {
 		RenameData         rename;
 		CopyData           copy;
 		ReorderData        reorder;
+		WriteMetadataData  write_metadata;
+		ReadMetadataData   read_metadata;
 	} data;
 } FileSourceAsyncOp;
 
@@ -115,6 +135,14 @@ static void
 file_source_async_op_free (FileSourceAsyncOp *async_op)
 {
 	switch (async_op->op) {
+	case FILE_SOURCE_OP_WRITE_METADATA:
+		g_free (async_op->data.write_metadata.attributes);
+		g_object_unref (async_op->data.write_metadata.file_data);
+		break;
+	case FILE_SOURCE_OP_READ_METADATA:
+		g_free (async_op->data.write_metadata.attributes);
+		g_object_unref (async_op->data.read_metadata.file_data);
+		break;
 	case FILE_SOURCE_OP_LIST:
 		g_object_unref (async_op->data.list.folder);
 		break;
@@ -140,6 +168,48 @@ file_source_async_op_free (FileSourceAsyncOp *async_op)
 
 
 static void
+gth_file_source_queue_write_metadata (GthFileSource *file_source,
+			              GthFileData   *file_data,
+			              const char    *attributes,
+			              ReadyCallback  callback,
+			              gpointer       data)
+{
+	FileSourceAsyncOp *async_op;
+
+	async_op = g_new0 (FileSourceAsyncOp, 1);
+	async_op->file_source = file_source;
+	async_op->op = FILE_SOURCE_OP_WRITE_METADATA;
+	async_op->data.write_metadata.file_data = g_object_ref (file_data);
+	async_op->data.write_metadata.attributes = g_strdup (attributes);
+	async_op->data.write_metadata.ready_callback = callback;
+	async_op->data.write_metadata.data = data;
+
+	file_source->priv->queue = g_list_append (file_source->priv->queue, async_op);
+}
+
+
+static void
+gth_file_source_queue_read_metadata (GthFileSource *file_source,
+			             GthFileData   *file_data,
+			             const char    *attributes,
+			             ReadyCallback  callback,
+			             gpointer       data)
+{
+	FileSourceAsyncOp *async_op;
+
+	async_op = g_new0 (FileSourceAsyncOp, 1);
+	async_op->file_source = file_source;
+	async_op->op = FILE_SOURCE_OP_READ_METADATA;
+	async_op->data.read_metadata.file_data = g_object_ref (file_data);
+	async_op->data.write_metadata.attributes = g_strdup (attributes);
+	async_op->data.read_metadata.ready_callback = callback;
+	async_op->data.read_metadata.data = data;
+
+	file_source->priv->queue = g_list_append (file_source->priv->queue, async_op);
+}
+
+
+static void
 gth_file_source_queue_list (GthFileSource *file_source,
 			    GFile         *folder,
 			    const char    *attributes,
@@ -264,6 +334,20 @@ gth_file_source_exec_next_in_queue (GthFileSource *file_source)
 
 	async_op = head->data;
 	switch (async_op->op) {
+	case FILE_SOURCE_OP_WRITE_METADATA:
+		gth_file_source_write_metadata (file_source,
+					        async_op->data.write_metadata.file_data,
+					        async_op->data.write_metadata.attributes,
+					        async_op->data.write_metadata.ready_callback,
+					        async_op->data.write_metadata.data);
+		break;
+	case FILE_SOURCE_OP_READ_METADATA:
+		gth_file_source_read_metadata (file_source,
+					       async_op->data.read_metadata.file_data,
+					       async_op->data.write_metadata.attributes,
+					       async_op->data.read_metadata.ready_callback,
+					       async_op->data.read_metadata.data);
+		break;
 	case FILE_SOURCE_OP_LIST:
 		gth_file_source_list (file_source,
 				      async_op->data.list.folder,
@@ -379,6 +463,88 @@ base_get_file_data (GthFileSource  *file_source,
 
 
 static void
+base_write_metadata (GthFileSource *file_source,
+		     GthFileData   *file_data,
+		     const char    *attributes,
+		     ReadyCallback  callback,
+		     gpointer       data)
+{
+	object_ready_with_error (file_source, callback, data, NULL);
+}
+
+
+/* -- base_read_metadata -- */
+
+
+typedef struct {
+	GthFileSource *file_source;
+	GthFileData   *file_data;
+	ReadyCallback  callback;
+	gpointer       data;
+} ReadMetadataOpData;
+
+
+static void
+read_metadata_free (ReadMetadataOpData *read_metadata)
+{
+	g_object_unref (read_metadata->file_source);
+	g_object_unref (read_metadata->file_data);
+	g_free (read_metadata);
+}
+
+
+static void
+read_metadata_info_ready_cb (GList    *files,
+			     GError   *error,
+			     gpointer  user_data)
+{
+	ReadMetadataOpData *read_metadata = user_data;
+	GthFileData        *result;
+
+	if (error != NULL) {
+		read_metadata->callback (G_OBJECT (read_metadata->file_source), error, read_metadata->data);
+		read_metadata_free (read_metadata);
+		return;
+	}
+
+	result = files->data;
+	g_file_info_copy_into (result->info, read_metadata->file_data->info);
+	read_metadata->callback (G_OBJECT (read_metadata->file_source), NULL, read_metadata->data);
+
+	read_metadata_free (read_metadata);
+}
+
+
+static void
+base_read_metadata (GthFileSource *file_source,
+		    GthFileData   *file_data,
+		    const char    *attributes,
+		    ReadyCallback  callback,
+		    gpointer       data)
+{
+	ReadMetadataOpData *read_metadata;
+	GList              *files;
+
+	read_metadata = g_new0 (ReadMetadataOpData, 1);
+	read_metadata->file_source = g_object_ref (file_source);
+	read_metadata->file_data = g_object_ref (file_data);
+	read_metadata->callback = callback;
+	read_metadata->data = data;
+
+	files = g_list_prepend (NULL, file_data->file);
+	_g_query_all_metadata_async (files,
+				     FALSE,
+				     TRUE,
+				     attributes,
+				     file_source->priv->cancellable,
+				     read_metadata_info_ready_cb,
+				     read_metadata);
+
+	g_list_free (files);
+}
+
+
+static void
 base_list (GthFileSource *file_source,
 	   GFile         *folder,
 	   const char    *attributes,
@@ -491,6 +657,8 @@ gth_file_source_class_init (GthFileSourceClass *class)
 	class->to_gio_file = base_to_gio_file;
 	class->get_file_info = base_get_file_info;
 	class->get_file_data = base_get_file_data;
+	class->write_metadata = base_write_metadata;
+	class->read_metadata = base_read_metadata;
 	class->list = base_list;
 	class->rename = base_rename;
 	class->can_cut = base_can_cut;
@@ -653,6 +821,36 @@ gth_file_source_cancel (GthFileSource *file_source)
 
 
 void
+gth_file_source_write_metadata (GthFileSource *file_source,
+				GthFileData   *file_data,
+				const char    *attributes,
+				ReadyCallback  callback,
+				gpointer       data)
+{
+	if (gth_file_source_is_active (file_source)) {
+		gth_file_source_queue_write_metadata (file_source, file_data, attributes, callback, data);
+		return;
+	}
+	GTH_FILE_SOURCE_GET_CLASS (G_OBJECT (file_source))->write_metadata (file_source, file_data, attributes, callback, data);
+}
+
+
+void
+gth_file_source_read_metadata (GthFileSource *file_source,
+			       GthFileData   *file_data,
+			       const char    *attributes,
+			       ReadyCallback  callback,
+			       gpointer       data)
+{
+	if (gth_file_source_is_active (file_source)) {
+		gth_file_source_queue_read_metadata (file_source, file_data, attributes, callback, data);
+		return;
+	}
+	GTH_FILE_SOURCE_GET_CLASS (G_OBJECT (file_source))->read_metadata (file_source, file_data, attributes, callback, data);
+}
+
+
+void
 gth_file_source_list (GthFileSource *file_source,
 		      GFile         *folder,
 		      const char    *attributes,
diff --git a/gthumb/gth-file-source.h b/gthumb/gth-file-source.h
index efd373b..439ea4b 100644
--- a/gthumb/gth-file-source.h
+++ b/gthumb/gth-file-source.h
@@ -76,6 +76,16 @@ struct _GthFileSourceClass
 	GthFileData *(*get_file_data)         (GthFileSource    *file_source,
 					       GFile            *file,
 					       GFileInfo        *info);
+	void         (*write_metadata)        (GthFileSource    *file_source,
+					       GthFileData      *file_data,
+					       const char       *attributes,
+					       ReadyCallback     callback,
+       					       gpointer          data);
+	void         (*read_metadata)         (GthFileSource    *file_source,
+					       GthFileData      *file_data,
+					       const char       *attributes,
+					       ReadyCallback     callback,
+					       gpointer          data);
 	void         (*list)                  (GthFileSource    *file_source,
 					       GFile            *folder,
 					       const char       *attributes,
@@ -126,6 +136,16 @@ GthFileData *  gth_file_source_get_file_data         (GthFileSource    *file_sou
 					              GFileInfo        *info);
 gboolean       gth_file_source_is_active             (GthFileSource    *file_source);
 void           gth_file_source_cancel                (GthFileSource    *file_source);
+void           gth_file_source_write_metadata        (GthFileSource    *file_source,
+						      GthFileData      *file_data,
+						      const char       *attributes,
+						      ReadyCallback     callback,
+						      gpointer          data);
+void           gth_file_source_read_metadata         (GthFileSource    *file_source,
+						      GthFileData      *file_data,
+						      const char       *attributes,
+						      ReadyCallback     callback,
+						      gpointer          data);
 void           gth_file_source_list                  (GthFileSource    *file_source,
 						      GFile            *folder,
 						      const char       *attributes,
diff --git a/gthumb/gth-file-store.c b/gthumb/gth-file-store.c
index e8c932d..62922d6 100644
--- a/gthumb/gth-file-store.c
+++ b/gthumb/gth-file-store.c
@@ -708,7 +708,7 @@ campare_row_func (gconstpointer a,
 	int           result;
 
 	if (file_store->priv->cmp_func == NULL)
-		result = 1 /*strcmp (gth_file_data_get_filename_sort_key (row_a->file),
+		result = -1 /*strcmp (gth_file_data_get_filename_sort_key (row_a->file),
 			       gth_file_data_get_filename_sort_key (row_b->file))*/;
 	else
 		result = file_store->priv->cmp_func (row_a->file_data, row_b->file_data);
@@ -725,6 +725,9 @@ _gth_file_store_sort (GthFileStore *file_store,
 		      gconstpointer pbase,
 		      gint          total_elems)
 {
+	if (file_store->priv->cmp_func == NULL)
+		return;
+
 	g_qsort_with_data (pbase,
 			   total_elems,
 			   (gsize) sizeof (GthFileRow *),
diff --git a/gthumb/gth-filter.c b/gthumb/gth-filter.c
index 46d56c7..40a560e 100644
--- a/gthumb/gth-filter.c
+++ b/gthumb/gth-filter.c
@@ -180,7 +180,7 @@ gth_filter_set_file_list (GthTest *test,
 		GthFileDataSort *sort_type;
 
 		sort_type = gth_main_get_sort_type (filter->priv->sort_name);
-		if (sort_type != NULL) {
+		if ((sort_type != NULL) && (sort_type->cmp_func != NULL)) {
 			g_qsort_with_data (test->files, test->n_files, (gsize) sizeof (GthFileData *), qsort_campare_func, sort_type);
 			if (filter->priv->sort_direction == GTK_SORT_DESCENDING) {
 				int i;
diff --git a/gthumb/gth-main-default-sort-types.c b/gthumb/gth-main-default-sort-types.c
index 9304d84..690160b 100644
--- a/gthumb/gth-main-default-sort-types.c
+++ b/gthumb/gth-main-default-sort-types.c
@@ -72,24 +72,11 @@ gth_file_data_cmp_modified_time (GthFileData *a,
 }
 
 
-static int
-gth_file_data_cmp_unsorted (GthFileData *a,
-		            GthFileData *b)
-{
-	if (a == b)
-		return 0;
-	else if (a < b)
-		return -1;
-	else
-		return 1;
-}
-
-
 GthFileDataSort default_sort_types[] = {
 	{ "file::name", N_("name"), "standard::display-name", gth_file_data_cmp_filename },
 	{ "file::size", N_("size"), "standard::size", gth_file_data_cmp_filesize },
 	{ "file::mtime", N_("last modified"), "time::modified,time::modified-usec", gth_file_data_cmp_modified_time },
-	{ "general::unsorted", N_("unsorted"), "", gth_file_data_cmp_unsorted },
+	{ "general::unsorted", N_("unsorted"), "", NULL },
 };
 
 



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