[gthumb/ext: 72/79] load the metadata required by the browser



commit 49df8207d9f11d6e6b6349b869b67870aada3ef6
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sun Jul 26 16:22:14 2009 +0200

    load the metadata required by the browser
    
    only load the metadata required by the filter, the sort function and
    the thumbnail caption.

 .../comments/gth-metadata-provider-comment.c       |   59 +++-----
 extensions/comments/gth-test-category.c            |   31 ++--
 extensions/comments/main.c                         |    2 +
 extensions/exiv2/gth-metadata-provider-exiv2.c     |   54 ++++----
 extensions/exiv2/main.c                            |    2 +-
 extensions/image_viewer/gth-image-viewer-page.c    |    8 +-
 .../image_viewer/gth-metadata-provider-image.c     |   32 ++---
 extensions/image_viewer/main.c                     |    2 +-
 gthumb/glib-utils.c                                |   36 ++++--
 gthumb/gth-browser.c                               |  144 +++++++++++++++++---
 gthumb/gth-cell-renderer-thumbnail.c               |   21 ++--
 gthumb/gth-file-data.h                             |    1 +
 gthumb/gth-file-list.c                             |    2 +-
 gthumb/gth-filter.c                                |   20 +++-
 gthumb/gth-filterbar.c                             |    4 +-
 gthumb/gth-main-default-metadata.c                 |    9 +-
 gthumb/gth-main-default-sort-types.c               |   14 +-
 gthumb/gth-main-default-tests.c                    |    2 +
 gthumb/gth-metadata-provider-file.c                |   53 ++------
 gthumb/gth-metadata-provider.c                     |   29 ++++-
 gthumb/gth-test-chain.c                            |  112 +++++++++++----
 gthumb/gth-test-simple.c                           |    7 +-
 gthumb/gth-test.c                                  |   34 +++++
 gthumb/gth-test.h                                  |    8 +-
 24 files changed, 452 insertions(+), 234 deletions(-)
---
diff --git a/extensions/comments/gth-metadata-provider-comment.c b/extensions/comments/gth-metadata-provider-comment.c
index dbdc117..d8c7eba 100644
--- a/extensions/comments/gth-metadata-provider-comment.c
+++ b/extensions/comments/gth-metadata-provider-comment.c
@@ -63,6 +63,9 @@ gth_metadata_provider_comment_read (GthMetadataProvider *self,
 {
 	GthComment            *comment;
 	GFileAttributeMatcher *matcher;
+	const char            *value;
+	GPtrArray             *categories;
+	char                  *comment_time;
 
 	comment = gth_comment_new_for_file (file_data->file, NULL);
 	if (comment == NULL)
@@ -70,49 +73,33 @@ gth_metadata_provider_comment_read (GthMetadataProvider *self,
 
 	matcher = g_file_attribute_matcher_new (attributes);
 
-	if (g_file_attribute_matcher_matches (matcher, "comment::note")) {
-		const char *value;
-
-		value = gth_comment_get_note (comment);
-		if (value != NULL) {
-			g_file_info_set_attribute_string (file_data->info, "comment::note", value);
-			set_attribute_from_string (file_data->info, "Embedded::Image::Comment", value);
-		}
+	value = gth_comment_get_note (comment);
+	if (value != NULL) {
+		g_file_info_set_attribute_string (file_data->info, "comment::note", value);
+		set_attribute_from_string (file_data->info, "Embedded::Image::Comment", value);
 	}
 
-	if (g_file_attribute_matcher_matches (matcher, "comment::place")) {
-		const char *value;
-
-		value = gth_comment_get_place (comment);
-		if (value != NULL) {
-			g_file_info_set_attribute_string (file_data->info, "comment::place", value);
-			set_attribute_from_string (file_data->info, "Embedded::Image::Location", value);
-		}
+	value = gth_comment_get_place (comment);
+	if (value != NULL) {
+		g_file_info_set_attribute_string (file_data->info, "comment::place", value);
+		set_attribute_from_string (file_data->info, "Embedded::Image::Location", value);
 	}
 
-	if (g_file_attribute_matcher_matches (matcher, "comment::categories")) {
-		GPtrArray *categories;
+	categories = gth_comment_get_categories (comment);
+	if (categories->len > 0) {
+		GObject *value;
 
-		categories = gth_comment_get_categories (comment);
-		if (categories->len > 0) {
-			GObject *value;
-
-			value = (GObject *) gth_string_list_new_from_ptr_array (categories);
-			g_file_info_set_attribute_object (file_data->info, "comment::categories", value);
-			g_file_info_set_attribute_object (file_data->info, "Embedded::Image::Keywords", value);
-			g_object_unref (value);
-		}
+		value = (GObject *) gth_string_list_new_from_ptr_array (categories);
+		g_file_info_set_attribute_object (file_data->info, "comment::categories", value);
+		g_file_info_set_attribute_object (file_data->info, "Embedded::Image::Keywords", value);
+		g_object_unref (value);
 	}
 
-	if (g_file_attribute_matcher_matches (matcher, "comment::time")) {
-		char *comment_time;
-
-		comment_time = gth_comment_get_time_as_exif_format (comment);
-		if (comment_time != NULL) {
-			g_file_info_set_attribute_string (file_data->info, "comment::time", comment_time);
-			set_attribute_from_string (file_data->info, "Embedded::Image::DateTime", comment_time);
-			g_free (comment_time);
-		}
+	comment_time = gth_comment_get_time_as_exif_format (comment);
+	if (comment_time != NULL) {
+		g_file_info_set_attribute_string (file_data->info, "comment::time", comment_time);
+		set_attribute_from_string (file_data->info, "Embedded::Image::DateTime", comment_time);
+		g_free (comment_time);
 	}
 
 	g_file_attribute_matcher_unref (matcher);
diff --git a/extensions/comments/gth-test-category.c b/extensions/comments/gth-test-category.c
index ac3f2e2..97ee956 100644
--- a/extensions/comments/gth-test-category.c
+++ b/extensions/comments/gth-test-category.c
@@ -147,7 +147,7 @@ gth_test_category_real_create_control (GthTest *base)
 	test->priv->text_entry = gtk_entry_new ();
 	/*gtk_entry_set_width_chars (GTK_ENTRY (test->priv->text_entry), 6);*/
 	if (test->priv->category != NULL)
-		gtk_entry_set_text (GTK_ENTRY (test->priv->text_entry), test->priv->category);	
+		gtk_entry_set_text (GTK_ENTRY (test->priv->text_entry), test->priv->category);
 	gtk_widget_show (test->priv->text_entry);
 
 	g_signal_connect (G_OBJECT (test->priv->text_entry),
@@ -178,29 +178,29 @@ gth_test_category_real_match (GthTest     *test,
 {
 	GthTestCategory *test_category;
 	gboolean         result = FALSE;
-		
+
         test_category = GTH_TEST_CATEGORY (test);
 
 	if (test_category->priv->category != NULL) {
 		GthStringList *string_list;
 		GList         *list, *scan;
-	
-		string_list = (GthStringList *) g_file_info_get_attribute_object (file->info, "comment::categories");	
+
+		string_list = (GthStringList *) g_file_info_get_attribute_object (file->info, "comment::categories");
 		if (string_list != NULL)
 			list = gth_string_list_get_list (string_list);
 		else
 			list = NULL;
-		
-		for (scan = list; scan; scan = scan->next) {	
+
+		for (scan = list; scan; scan = scan->next) {
 			char *category = scan->data;
-			
+
 			if (g_utf8_collate (category, test_category->priv->category) == 0) {
 				result = TRUE;
 				break;
 			}
 		}
 	}
-	
+
         if (test_category->priv->negative)
 		result = ! result;
 
@@ -242,7 +242,7 @@ gth_test_category_set_category (GthTestCategory *self,
 {
 	g_free (self->priv->category);
 	self->priv->category = NULL;
-	if (category != NULL) 
+	if (category != NULL)
 		self->priv->category = g_strdup (category);
 }
 
@@ -268,7 +268,7 @@ gth_test_category_real_load_from_element (DomDomizable *base,
 
 	gth_test_category_set_category (self, NULL);
 	value = dom_element_get_attribute (element, "value");
-	if (value != NULL) 
+	if (value != NULL)
 		gth_test_category_set_category (self, value);
 }
 
@@ -279,14 +279,14 @@ gth_test_category_real_update_from_control (GthTest  *base,
 {
 	GthTestCategory *self;
 	GthOpData        op_data;
-	
+
 	self = GTH_TEST_CATEGORY (base);
 
 	op_data = category_op_data[gtk_combo_box_get_active (GTK_COMBO_BOX (self->priv->op_combo_box))];
 	self->priv->op = op_data.op;
 	self->priv->negative = op_data.negative;
-	
-	gth_test_category_set_category (self, gtk_entry_get_text (GTK_ENTRY (self->priv->text_entry)));	
+
+	gth_test_category_set_category (self, gtk_entry_get_text (GTK_ENTRY (self->priv->text_entry)));
 	if (g_strcmp0 (self->priv->category, "") == 0) {
 		if (error != NULL)
 			*error = g_error_new (GTH_TEST_ERROR, 0, _("The test definition is incomplete"));
@@ -311,7 +311,7 @@ gth_test_category_real_duplicate (GthDuplicable *duplicable)
 	new_test->priv->op = test->priv->op;
 	new_test->priv->negative = test->priv->negative;
 	gth_test_category_set_category (new_test, test->priv->category);
-	
+
 	return (GObject *) new_test;
 }
 
@@ -354,6 +354,7 @@ static void
 gth_test_category_init (GthTestCategory *test)
 {
 	test->priv = g_new0 (GthTestCategoryPrivate, 1);
+	g_object_set (test, "attributes", "comment::categories", NULL);
 }
 
 
@@ -384,7 +385,7 @@ gth_test_category_get_type (void)
 			(GInterfaceFinalizeFunc) NULL,
 			NULL
 		};
-		
+
 		type = g_type_register_static (GTH_TYPE_TEST,
 					       "GthTestCategory",
 					       &type_info,
diff --git a/extensions/comments/main.c b/extensions/comments/main.c
index 1ac92da..3ee1885 100644
--- a/extensions/comments/main.c
+++ b/extensions/comments/main.c
@@ -83,12 +83,14 @@ gthumb_extension_activate (void)
 	gth_main_register_type ("edit-metadata-dialog-page", GTH_TYPE_EDIT_COMMENT_PAGE);
 	gth_main_register_test ("comment::note",
 				GTH_TYPE_TEST_SIMPLE,
+				"attributes", "comment::note",
 				"display-name", _("Comment"),
 				"data-type", GTH_TEST_DATA_TYPE_STRING,
 				"get-data-func", get_comment_for_test,
 				NULL);
 	gth_main_register_test ("comment::place",
 				GTH_TYPE_TEST_SIMPLE,
+				"attributes", "comment::place",
 				"display-name", _("Place"),
 				"data-type", GTH_TEST_DATA_TYPE_STRING,
 				"get-data-func", get_place_for_test,
diff --git a/extensions/exiv2/gth-metadata-provider-exiv2.c b/extensions/exiv2/gth-metadata-provider-exiv2.c
index 2d3cb40..d55b56e 100644
--- a/extensions/exiv2/gth-metadata-provider-exiv2.c
+++ b/extensions/exiv2/gth-metadata-provider-exiv2.c
@@ -45,35 +45,33 @@ gth_metadata_provider_exiv2_read (GthMetadataProvider *self,
 				  GthFileData         *file_data,
 				  const char          *attributes)
 {
-	if (_g_file_attributes_matches (attributes, "Exif::*,Iptc::*,Xmp::*")) {
-		char        *uri;
-		char        *uri_wo_ext;
-		char        *sidecar_uri;
-		GthFileData *sidecar_file_data;
-
-		/* this function is executed in a secondary thread, so calling
-		 * slow sync functions, such as obtain_local_file, is not a
-		 * problem. */
-
-		exiv2_read_metadata (file_data->file, file_data->info);
-
-		/* sidecar data */
-
-		uri = g_file_get_uri (file_data->file);
-		uri_wo_ext = _g_uri_remove_extension (uri);
-		sidecar_uri = g_strconcat (uri_wo_ext, ".xmp", NULL);
-		sidecar_file_data = gth_file_data_new_for_uri (sidecar_uri, NULL);
-		if (g_file_query_exists (sidecar_file_data->file, NULL)) {
-			gth_file_data_update_info (sidecar_file_data, "time::*");
-			if (g_file_query_exists (sidecar_file_data->file, NULL))
-				exiv2_read_sidecar (sidecar_file_data->file, file_data->info);
-		}
-
-		g_object_unref (sidecar_file_data);
-		g_free (sidecar_uri);
-		g_free (uri_wo_ext);
-		g_free (uri);
+	char        *uri;
+	char        *uri_wo_ext;
+	char        *sidecar_uri;
+	GthFileData *sidecar_file_data;
+
+	/* this function is executed in a secondary thread, so calling
+	 * slow sync functions, such as obtain_local_file, is not a
+	 * problem. */
+
+	exiv2_read_metadata (file_data->file, file_data->info);
+
+	/* sidecar data */
+
+	uri = g_file_get_uri (file_data->file);
+	uri_wo_ext = _g_uri_remove_extension (uri);
+	sidecar_uri = g_strconcat (uri_wo_ext, ".xmp", NULL);
+	sidecar_file_data = gth_file_data_new_for_uri (sidecar_uri, NULL);
+	if (g_file_query_exists (sidecar_file_data->file, NULL)) {
+		gth_file_data_update_info (sidecar_file_data, "time::*");
+		if (g_file_query_exists (sidecar_file_data->file, NULL))
+			exiv2_read_sidecar (sidecar_file_data->file, file_data->info);
 	}
+
+	g_object_unref (sidecar_file_data);
+	g_free (sidecar_uri);
+	g_free (uri_wo_ext);
+	g_free (uri);
 }
 
 
diff --git a/extensions/exiv2/main.c b/extensions/exiv2/main.c
index 8198798..c5281be 100644
--- a/extensions/exiv2/main.c
+++ b/extensions/exiv2/main.c
@@ -50,7 +50,7 @@ GthMetadataInfo exiv2_metadata_info[] = {
 	{ "Exif::Image::Software", NULL, "Exif::General", 3, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
 	{ "Exif::Image::DateTime", NULL, "Exif::General", 4, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
 	{ "Exif::Photo::SubSecTime", NULL, "Exif::General", 5, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
-	{ "Exif::Photo::DateTimeOriginal", NULL, "Exif::General", 6, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
+	{ "Exif::Photo::DateTimeOriginal", NULL, "Exif::General", 6, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW},
 	{ "Exif::Photo::SubSecTimeOriginal", NULL, "Exif::General", 7, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
 	{ "Exif::Photo::DateTimeDigitized", NULL, "Exif::General", 8, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
 	{ "Exif::Photo::SubSecTimeDigitized", NULL, "Exif::General", 9, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
diff --git a/extensions/image_viewer/gth-image-viewer-page.c b/extensions/image_viewer/gth-image-viewer-page.c
index 1dd01c6..b385b6e 100644
--- a/extensions/image_viewer/gth-image-viewer-page.c
+++ b/extensions/image_viewer/gth-image-viewer-page.c
@@ -186,7 +186,7 @@ image_ready_cb (GtkWidget          *widget,
 {
 	gth_image_history_clear (self->priv->history);
 
-	g_file_info_set_attribute_boolean (self->priv->file_data->info, "file::is-modified", FALSE);
+	g_file_info_set_attribute_boolean (self->priv->file_data->info, "gth::file::is-modified", FALSE);
 	gth_monitor_metadata_changed (gth_main_get_default_monitor (), self->priv->file_data);
 
 }
@@ -676,7 +676,7 @@ image_saved_cb (GthFileData *file_data,
 		current_file = gth_browser_get_current_file (self->priv->browser);
 		if (current_file != NULL) {
 			gth_file_data_set_file (current_file, data->original_file->file);
-			g_file_info_set_attribute_boolean (current_file->info, "file::is-modified", FALSE);
+			g_file_info_set_attribute_boolean (current_file->info, "gth::file::is-modified", FALSE);
 		}
 	}
 
@@ -732,7 +732,7 @@ _gth_image_viewer_page_real_save (GthViewerPage *base,
 	data->original_file = gth_file_data_dup (current_file);
 	if (file != NULL)
 		gth_file_data_set_file (current_file, file);
-	g_file_info_set_attribute_boolean (current_file->info, "file::is-modified", FALSE);
+	g_file_info_set_attribute_boolean (current_file->info, "gth::file::is-modified", FALSE);
 
 	_gdk_pixbuf_save_async (gth_image_viewer_get_current_pixbuf (GTH_IMAGE_VIEWER (self->priv->viewer)),
 			        current_file,
@@ -1078,7 +1078,7 @@ _gth_image_viewer_page_set_pixbuf (GthImageViewerPage *self,
 
 	file_data = gth_browser_get_current_file (GTH_BROWSER (self->priv->browser));
 
-	g_file_info_set_attribute_boolean (file_data->info, "file::is-modified", modified);
+	g_file_info_set_attribute_boolean (file_data->info, "gth::file::is-modified", modified);
 
 	width = gdk_pixbuf_get_width (pixbuf);
 	height = gdk_pixbuf_get_height (pixbuf);
diff --git a/extensions/image_viewer/gth-metadata-provider-image.c b/extensions/image_viewer/gth-metadata-provider-image.c
index 64c2181..53eef88 100644
--- a/extensions/image_viewer/gth-metadata-provider-image.c
+++ b/extensions/image_viewer/gth-metadata-provider-image.c
@@ -45,29 +45,27 @@ gth_metadata_provider_image_read (GthMetadataProvider *self,
 				  GthFileData         *file_data,
 				  const char          *attributes)
 {
-	if (_g_file_attributes_matches (attributes, "image::*")) {
-		GdkPixbufFormat *format;
-		char            *filename;
-		int              width, height;
+	GdkPixbufFormat *format;
+	char            *filename;
+	int              width, height;
 
-		filename = g_file_get_path (file_data->file);
-		format = gdk_pixbuf_get_file_info (filename, &width, &height);
-		if (format != NULL) {
-			char *size;
+	filename = g_file_get_path (file_data->file);
+	format = gdk_pixbuf_get_file_info (filename, &width, &height);
+	if (format != NULL) {
+		char *size;
 
-			g_file_info_set_attribute_string (file_data->info, "image::format", gdk_pixbuf_format_get_description (format));
+		g_file_info_set_attribute_string (file_data->info, "image::format", gdk_pixbuf_format_get_description (format));
 
-			g_file_info_set_attribute_int32 (file_data->info, "image::width", width);
-			g_file_info_set_attribute_int32 (file_data->info, "image::height", height);
+		g_file_info_set_attribute_int32 (file_data->info, "image::width", width);
+		g_file_info_set_attribute_int32 (file_data->info, "image::height", height);
 
-			size = g_strdup_printf ("%d x %d", width, height);
-			g_file_info_set_attribute_string (file_data->info, "image::size", size);
+		size = g_strdup_printf ("%d x %d", width, height);
+		g_file_info_set_attribute_string (file_data->info, "image::size", size);
 
-			g_free (size);
-		}
-
-		g_free (filename);
+		g_free (size);
 	}
+
+	g_free (filename);
 }
 
 
diff --git a/extensions/image_viewer/main.c b/extensions/image_viewer/main.c
index e95d482..f3e3d75 100644
--- a/extensions/image_viewer/main.c
+++ b/extensions/image_viewer/main.c
@@ -36,7 +36,7 @@ GthMetadataCategory image_metadata_category[] = {
 
 
 GthMetadataInfo image_metadata_info[] = {
-	{ "image::size", N_("Size"), "image", 1, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
+	{ "image::size", N_("Image Size"), "image", 1, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW | GTH_METADATA_ALLOW_IN_FILE_LIST },
 	{ "image::format", N_("Format"), "image", 2, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
 	{ NULL, NULL, NULL, 0, 0 }
 };
diff --git a/gthumb/glib-utils.c b/gthumb/glib-utils.c
index 24f9918..00078b0 100644
--- a/gthumb/glib-utils.c
+++ b/gthumb/glib-utils.c
@@ -1891,29 +1891,43 @@ _g_file_append_path (GFile      *file,
 }
 
 
-gboolean
-_g_file_attributes_matches (const char *attributes,
-			    const char *mask)
+static gboolean
+_g_file_attributes_matches_mask (const char *attributes,
+			         const char *mask)
 {
-	GFileAttributeMatcher *matcher;
-	gboolean               matches;
+	gboolean   matches = FALSE;
+	char     **attributes_v;
+	char     **mask_v;
+	int        i;
+
+	attributes_v = g_strsplit (attributes, ",", -1);
+	mask_v = g_strsplit (mask, ",", -1);
+	for (i = 0; ! matches && (mask_v[i] != NULL); i++) {
+		GFileAttributeMatcher *matcher;
+		int                    j;
 
-	matcher = g_file_attribute_matcher_new (mask);
+		matcher = g_file_attribute_matcher_new (mask_v[i]);
+		for (j = 0; ! matches && (attributes_v[j] != NULL); j++)
+			matches = g_file_attribute_matcher_matches (matcher, attributes_v[j]);
 
-	matches = g_file_attribute_matcher_matches (matcher, attributes);
-	if (! matches) {
 		g_file_attribute_matcher_unref (matcher);
-		matcher = g_file_attribute_matcher_new (attributes);
-		matches = g_file_attribute_matcher_matches (matcher, mask);
 	}
 
-	g_file_attribute_matcher_unref (matcher);
+	g_strfreev (mask_v);
 
 	return matches;
 }
 
 
 gboolean
+_g_file_attributes_matches (const char *attributes,
+			    const char *mask)
+{
+	return _g_file_attributes_matches_mask (attributes, mask) || _g_file_attributes_matches_mask (mask, attributes);
+}
+
+
+gboolean
 _g_mime_type_is_image (const char *mime_type)
 {
 	g_return_val_if_fail (mime_type != NULL, FALSE);
diff --git a/gthumb/gth-browser.c b/gthumb/gth-browser.c
index b62454a..12b10f8 100644
--- a/gthumb/gth-browser.c
+++ b/gthumb/gth-browser.c
@@ -148,6 +148,7 @@ struct _GthBrowserPrivateData {
 	GList             *load_data_queue;
 	guint              load_file_timeout;
 	char              *list_attributes;
+	gboolean           constructed;
 
 	/* fulscreen */
 
@@ -785,6 +786,9 @@ _gth_browser_get_file_filter (GthBrowser *browser)
 	GthTest *filterbar_test;
 	GthTest *test;
 
+	if (browser->priv->filterbar == NULL)
+		return NULL;
+
 	filterbar_test = gth_filterbar_get_test (GTH_FILTERBAR (browser->priv->filterbar));
 	test = gth_main_add_general_filter (filterbar_test);
 
@@ -1234,40 +1238,132 @@ metadata_ready_cb (GList    *files,
 static const char *
 _gth_browser_get_list_attributes (GthBrowser *browser)
 {
-	GString  *attributes;
-	char    **attributes_v;
-	int       i;
+	GString *attributes;
+	GthTest *filter;
+	char    *thumbnail_caption;
 
 	if (browser->priv->list_attributes != NULL)
 		return browser->priv->list_attributes;
 
 	attributes = g_string_new ("");
+
+	/* standard attributes */
+
 	if (eel_gconf_get_boolean (PREF_FAST_FILE_TYPE, TRUE))
 		g_string_append (attributes, GFILE_STANDARD_ATTRIBUTES_WITH_FAST_CONTENT_TYPE);
 	else
 		g_string_append (attributes, GFILE_STANDARD_ATTRIBUTES_WITH_CONTENT_TYPE);
 
-	attributes_v = gth_main_get_metadata_attributes ("*");
-	for (i = 0; attributes_v[i] != NULL; i++) {
-		GthMetadataInfo *info;
+	/* attributes required by the filter */
 
-		info = gth_main_get_metadata_info (attributes_v[i]);
-		if ((info == NULL) || ((info->flags & GTH_METADATA_ALLOW_IN_FILE_LIST) == 0))
-			continue;
+	filter = _gth_browser_get_file_filter (browser);
+	if (filter != NULL) {
+		const char *filter_attributes;
 
+		filter_attributes = gth_test_get_attributes (GTH_TEST (filter));
+		if (filter_attributes[0] != '\0') {
+			g_string_append (attributes, ",");
+			g_string_append (attributes, filter_attributes);
+		}
+
+		g_object_unref (filter);
+	}
+
+	/* attributes required for sorting */
+
+	if (browser->priv->sort_type->required_attributes[0] != '\0') {
 		g_string_append (attributes, ",");
-		g_string_append (attributes, attributes_v[i]);
+		g_string_append (attributes, browser->priv->sort_type->required_attributes);
 	}
 
-	browser->priv->list_attributes = attributes->str;
+	/* attributes required for the thumbnail caption */
 
-	g_strfreev (attributes_v);
-	g_string_free (attributes, FALSE);
+	thumbnail_caption = eel_gconf_get_string (PREF_THUMBNAIL_CAPTION, "standard::display-name");
+	if ((thumbnail_caption[0] != '\0') && (strcmp (thumbnail_caption, "none") != 0)) {
+		g_string_append (attributes, ",");
+		g_string_append (attributes, thumbnail_caption);
+		g_free (thumbnail_caption);
+	}
+
+	browser->priv->list_attributes = g_string_free (attributes, FALSE);
 
 	return browser->priv->list_attributes;
 }
 
 
+static gboolean
+_gth_browser_reload_required (GthBrowser *browser)
+{
+	char        *old_list_attributes;
+	char       **old_list_attributes_v;
+	const char  *new_list_attributes;
+	char       **new_list_attributes_v;
+	int          new_list_attributes_len;
+	int          i;
+	gboolean     reload_required;
+
+	old_list_attributes = g_strdup (_gth_browser_get_list_attributes (browser));
+	old_list_attributes_v = g_strsplit (old_list_attributes, ",", -1);
+
+	g_free (browser->priv->list_attributes);
+	browser->priv->list_attributes = NULL;
+	new_list_attributes = _gth_browser_get_list_attributes (browser);
+	new_list_attributes_v = g_strsplit (new_list_attributes, ",", -1);
+	new_list_attributes_len = g_strv_length (new_list_attributes_v);
+
+	for (i = 0; i < new_list_attributes_len; i++) {
+		if (_g_file_attributes_matches (new_list_attributes_v[i], "standard::*,etag::*,id::*,access::*,mountable::*,time::*,unix::*,dos::*,owner::*,thumbnail::*,filesystem::*,gvfs::*,xattr::*,xattr-sys::*,selinux::*")) {
+			g_free (new_list_attributes_v[i]);
+			new_list_attributes_v[i] = NULL;
+		}
+	}
+
+	for (i = 0; (old_list_attributes_v[i] != NULL); i++) {
+		GthMetadataProvider *provider;
+		int                  j;
+
+		provider = gth_main_get_metadata_reader (old_list_attributes_v[i]);
+		if (provider == NULL)
+			continue;
+
+		for (j = 0; j < new_list_attributes_len; j++)
+			if ((new_list_attributes_v[j] != NULL)
+			    && (new_list_attributes_v[j][0] != '\0')
+			    && (strcmp (new_list_attributes_v[j], "none") != 0))
+			{
+				char *attr_v[2];
+
+				attr_v[0] = new_list_attributes_v[j];
+				attr_v[1] = NULL;
+				if (gth_metadata_provider_can_read (provider, attr_v)) {
+					g_free (new_list_attributes_v[j]);
+					new_list_attributes_v[j] = NULL;
+				}
+			}
+
+		g_object_ref (provider);
+	}
+
+	/*g_print ("attributes to load: %s\n", new_list_attributes);
+	g_print ("attributes not available: \n");*/
+	reload_required = FALSE;
+	for (i = 0; ! reload_required && (i < new_list_attributes_len); i++)
+		if ((new_list_attributes_v[i] != NULL)
+		    && (new_list_attributes_v[i][0] != '\0')
+		    && (strcmp (new_list_attributes_v[i], "none") != 0))
+		{
+			reload_required = TRUE;
+			/*g_print ("\t%s\n", new_list_attributes_v[i]);*/
+		}
+
+	g_strfreev (new_list_attributes_v);
+	g_strfreev (old_list_attributes_v);
+	g_free (old_list_attributes);
+
+	return reload_required;
+}
+
+
 static void
 load_data_ready (LoadData *data,
 		 GList    *files,
@@ -1496,7 +1592,7 @@ ask_whether_to_save__done (AskSaveData *data,
 			   gboolean     cancelled)
 {
 	if (cancelled)
-		g_file_info_set_attribute_boolean (data->browser->priv->current_file->info, "file::is-modified", TRUE);
+		g_file_info_set_attribute_boolean (data->browser->priv->current_file->info, "gth::file::is-modified", TRUE);
 	if (data->callback != NULL)
 		(*data->callback) (data->browser, cancelled, data->user_data);
 	g_free (data);
@@ -2085,6 +2181,9 @@ filterbar_changed_cb (GthFilterbar *filterbar,
 
 	_gth_browser_update_statusbar_list_info (browser);
 	gth_browser_update_sensitivity (browser);
+
+	if (_gth_browser_reload_required (browser))
+		gth_browser_reload (browser);
 }
 
 
@@ -2397,8 +2496,8 @@ _gth_browser_update_statusbar_file_info (GthBrowser *browser)
 	if (metadata != NULL)
 		file_date = gth_metadata_get_formatted (metadata);
 	else
-		file_date = g_file_info_get_attribute_string (browser->priv->current_file->info, "file::display-mtime");
-	file_size = g_file_info_get_attribute_string (browser->priv->current_file->info, "file::display-size");
+		file_date = g_file_info_get_attribute_string (browser->priv->current_file->info, "gth::file::display-mtime");
+	file_size = g_file_info_get_attribute_string (browser->priv->current_file->info, "gth::file::display-size");
 
 	if (gth_browser_get_file_modified (browser))
 		text = g_strdup_printf ("%s - %s", image_size, _("Modified"));
@@ -2774,6 +2873,9 @@ pref_thumbnail_caption_changed (GConfClient *client,
 	caption = eel_gconf_get_string (PREF_THUMBNAIL_CAPTION, "standard::display-name");
 	gth_file_list_set_caption (GTH_FILE_LIST (browser->priv->file_list), caption);
 
+	if (_gth_browser_reload_required (browser))
+		gth_browser_reload (browser);
+
 	g_free (caption);
 }
 
@@ -3011,7 +3113,7 @@ _gth_browser_construct (GthBrowser *browser)
 
 	browser->priv->file_list = gth_file_list_new ();
 	gth_browser_set_sort_order (browser,
-				    gth_main_get_sort_type (eel_gconf_get_string (PREF_SORT_TYPE, "file::mtime")),
+				    gth_main_get_sort_type (eel_gconf_get_string (PREF_SORT_TYPE, "gth::file::mtime")),
 				    FALSE);
 	gth_browser_enable_thumbnails (browser, eel_gconf_get_boolean (PREF_SHOW_THUMBNAILS, TRUE));
 	gth_file_list_set_thumb_size (GTH_FILE_LIST (browser->priv->file_list), eel_gconf_get_integer (PREF_THUMBNAIL_SIZE, DEF_THUMBNAIL_SIZE));
@@ -3151,6 +3253,7 @@ _gth_browser_construct (GthBrowser *browser)
 					   browser);
 
 	gth_window_set_current_page (GTH_WINDOW (browser), GTH_BROWSER_PAGE_BROWSER);
+	browser->priv->constructed = TRUE;
 
 	call_when_idle (_gth_browser_construct_step2, browser);
 }
@@ -3204,7 +3307,7 @@ gth_browser_get_file_modified (GthBrowser *browser)
 	if (browser->priv->current_file == NULL)
 		return FALSE;
 	else
-		return g_file_info_get_attribute_boolean (browser->priv->current_file->info, "file::is-modified");
+		return g_file_info_get_attribute_boolean (browser->priv->current_file->info, "gth::file::is-modified");
 }
 
 
@@ -3402,7 +3505,7 @@ gth_browser_set_sort_order (GthBrowser      *browser,
 {
 	if (sort_type == NULL) {
 		gth_browser_set_sort_order (browser,
-					    gth_main_get_sort_type ("file::mtime"),
+					    gth_main_get_sort_type ("gth::file::mtime"),
 					    inverse);
 		return;
 	}
@@ -3413,6 +3516,9 @@ gth_browser_set_sort_order (GthBrowser      *browser,
 				     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);
 }
 
 
diff --git a/gthumb/gth-cell-renderer-thumbnail.c b/gthumb/gth-cell-renderer-thumbnail.c
index 25a8285..f09ad23 100644
--- a/gthumb/gth-cell-renderer-thumbnail.c
+++ b/gthumb/gth-cell-renderer-thumbnail.c
@@ -373,6 +373,7 @@ gth_cell_renderer_thumbnail_render (GtkCellRenderer      *cell,
 				    GtkCellRendererState  flags)
 {
 	GthCellRendererThumbnail *self;
+	GtkStyle                 *style;
 	GtkStateType              state;
 	GdkRectangle              thumb_rect;
 	GdkRectangle              draw_rect;
@@ -406,6 +407,8 @@ gth_cell_renderer_thumbnail_render (GtkCellRenderer      *cell,
 		return;
 	}
 
+	style = gtk_widget_get_style (widget);
+
   	if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
   		state = GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE;
   	else
@@ -460,40 +463,40 @@ gth_cell_renderer_thumbnail_render (GtkCellRenderer      *cell,
 			frame_rect = image_rect;
 		}
 
-	  	gdk_draw_rectangle (GDK_DRAWABLE (window), widget->style->dark_gc[state], FALSE,
+	  	gdk_draw_rectangle (GDK_DRAWABLE (window), style->dark_gc[state], FALSE,
   				    frame_rect.x - B,
   				    frame_rect.y - B,
   				    frame_rect.width + (B * 2) - 1,
 				    frame_rect.height + (B * 2) - 1);
 
-  		gdk_draw_line (GDK_DRAWABLE (window), widget->style->dark_gc[state],
+  		gdk_draw_line (GDK_DRAWABLE (window), style->dark_gc[state],
   			       frame_rect.x - (B / 2),
   			       frame_rect.y + frame_rect.height + B,
   			       frame_rect.x + frame_rect.width + B,
   			       frame_rect.y + frame_rect.height + B);
-  		gdk_draw_line (GDK_DRAWABLE (window), widget->style->dark_gc[state],
+  		gdk_draw_line (GDK_DRAWABLE (window), style->dark_gc[state],
   			       frame_rect.x + frame_rect.width + B,
   			       frame_rect.y + frame_rect.height + B,
   			       frame_rect.x + frame_rect.width + B,
   			       frame_rect.y - (B / 2));
 
-		gdk_draw_line (GDK_DRAWABLE (window), widget->style->mid_gc[state],
+		gdk_draw_line (GDK_DRAWABLE (window), style->mid_gc[state],
   			       frame_rect.x - (B / 2) + 1,
   			       frame_rect.y + frame_rect.height + B + 1,
   			       frame_rect.x + frame_rect.width + B + 1,
   			       frame_rect.y + frame_rect.height + B + 1);
-  		gdk_draw_line (GDK_DRAWABLE (window), widget->style->mid_gc[state],
+  		gdk_draw_line (GDK_DRAWABLE (window), style->mid_gc[state],
   			       frame_rect.x + frame_rect.width + B + 1,
   			       frame_rect.y + frame_rect.height + B + 1,
   			       frame_rect.x + frame_rect.width + B + 1,
   			       frame_rect.y - (B / 2) + 1);
 
-  		gdk_draw_rectangle (GDK_DRAWABLE (window), widget->style->light_gc[state], TRUE,
+  		/*gdk_draw_rectangle (GDK_DRAWABLE (window), style->light_gc[state], TRUE,
   				    frame_rect.x - (B - 1),
   				    frame_rect.y - (B - 1),
   				    frame_rect.width + ((B - 1) * 2),
-  				    frame_rect.height + ((B - 1) * 2));
-  		/*gdk_draw_rectangle (GDK_DRAWABLE (window), widget->style->mid_gc[state], FALSE,
+  				    frame_rect.height + ((B - 1) * 2));*/
+  		/*gdk_draw_rectangle (GDK_DRAWABLE (window), style->mid_gc[state], FALSE,
   				    image_rect.x - 1,
   				    image_rect.y - 1,
   				    image_rect.width + 1,
@@ -501,7 +504,7 @@ gth_cell_renderer_thumbnail_render (GtkCellRenderer      *cell,
 	}
 
   	if ((flags & (GTK_CELL_RENDERER_SELECTED | GTK_CELL_RENDERER_PRELIT)) != 0) {
-		colorized = create_colorized_pixbuf (pixbuf, &widget->style->base[state]);
+		colorized = create_colorized_pixbuf (pixbuf, &style->base[state]);
 		pixbuf = colorized;
 	}
 
diff --git a/gthumb/gth-file-data.h b/gthumb/gth-file-data.h
index d5949a1..52e170e 100644
--- a/gthumb/gth-file-data.h
+++ b/gthumb/gth-file-data.h
@@ -63,6 +63,7 @@ typedef void (*GthFileDataFunc)     (GthFileData *a, GError *error, gpointer dat
 typedef struct {
 	const char          *name;
 	const char          *display_name;
+	const char          *required_attributes;
 	GthFileDataCompFunc  cmp_func;
 } GthFileDataSort;
 
diff --git a/gthumb/gth-file-list.c b/gthumb/gth-file-list.c
index 4f1d5e2..6d20cf0 100644
--- a/gthumb/gth-file-list.c
+++ b/gthumb/gth-file-list.c
@@ -516,7 +516,7 @@ gth_file_list_construct (GthFileList *file_list)
 	file_list->priv->thumbnail_renderer = renderer = gth_cell_renderer_thumbnail_new ();
 	g_object_set (renderer,
 		      "size", file_list->priv->thumb_size,
-		      "yalign", 0.5,
+		      "yalign", 1.0,
 		      NULL);
 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (file_list->priv->view), renderer, FALSE);
 	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (file_list->priv->view),
diff --git a/gthumb/gth-filter.c b/gthumb/gth-filter.c
index 0dae6ce..46d56c7 100644
--- a/gthumb/gth-filter.c
+++ b/gthumb/gth-filter.c
@@ -140,6 +140,18 @@ gth_filter_real_load_from_element (DomDomizable *base,
 }
 
 
+static const char *
+gth_filter_get_attributes (GthTest *test)
+{
+	GthFilter *filter = GTH_FILTER (test);
+
+	if (filter->priv->test != NULL)
+		return gth_test_get_attributes (GTH_TEST (filter->priv->test));
+	else
+		return "";
+}
+
+
 static int
 qsort_campare_func (gconstpointer a,
 		    gconstpointer b,
@@ -397,6 +409,7 @@ gth_filter_real_duplicate (GthDuplicable *duplicable)
 	new_filter = gth_filter_new ();
 	g_object_set (new_filter,
 		      "id", gth_test_get_id (GTH_TEST (filter)),
+		      "attributes", gth_test_get_attributes (GTH_TEST (filter)),
 		      "display-name", gth_test_get_display_name (GTH_TEST (filter)),
 		      "visible", gth_test_is_visible (GTH_TEST (filter)),
 		      NULL);
@@ -437,6 +450,7 @@ gth_filter_class_init (GthFilterClass *klass)
 	object_class->finalize = gth_filter_finalize;
 
 	test_class = GTH_TEST_CLASS (klass);
+	test_class->get_attributes = gth_filter_get_attributes;
 	test_class->set_file_list = gth_filter_set_file_list;
 	test_class->match = gth_filter_match;
 	test_class->create_control = gth_filter_real_create_control;
@@ -564,8 +578,12 @@ gth_filter_set_test (GthFilter    *filter,
 		g_object_unref (filter->priv->test);
 		filter->priv->test = NULL;
 	}
-	if (test != NULL)
+	if (test != NULL) {
 		filter->priv->test = g_object_ref (test);
+		g_object_set (filter, "attributes", gth_test_get_attributes (GTH_TEST (test)), NULL);
+	}
+	else
+		g_object_set (filter, "attributes", "", NULL);
 }
 
 
diff --git a/gthumb/gth-filterbar.c b/gthumb/gth-filterbar.c
index 064decd..a46017c 100644
--- a/gthumb/gth-filterbar.c
+++ b/gthumb/gth-filterbar.c
@@ -281,8 +281,8 @@ update_filter_list (GthFilterbar *filterbar,
 		gtk_list_store_set (filterbar->priv->model, &iter,
 				    TYPE_COLUMN, ITEM_TYPE_FILTER,
 				    FILTER_COLUMN, test,
-				    NAME_COLUMN, gth_test_get_display_name (test),
-					-1);
+				    NAME_COLUMN, gth_test_get_display_name(test),
+				    -1);
 
 		if (g_strcmp0 (current_filter, gth_test_get_id (test)) == 0) {
 			gtk_combo_box_set_active_iter (GTK_COMBO_BOX (filterbar->priv->test_combo_box), &iter);
diff --git a/gthumb/gth-main-default-metadata.c b/gthumb/gth-main-default-metadata.c
index 4308e3e..106fbd2 100644
--- a/gthumb/gth-main-default-metadata.c
+++ b/gthumb/gth-main-default-metadata.c
@@ -37,11 +37,10 @@ GthMetadataCategory file_metadata_category[] = {
 
 GthMetadataInfo file_metadata_info[] = {
 	{ "standard::display-name", N_("Name"), "file", 1, GTH_METADATA_ALLOW_EVERYWHERE },
-	{ "file::display-size", N_("Size"), "file", 2, GTH_METADATA_ALLOW_EVERYWHERE },
-	{ "file::display-ctime", N_("Created"), "file", 3, GTH_METADATA_ALLOW_EVERYWHERE },
-	{ "file::display-mtime", N_("Modified"), "file", 4, GTH_METADATA_ALLOW_EVERYWHERE },
-	{ "standard::fast-content-type", N_("Type"), "file", 5, GTH_METADATA_ALLOW_EVERYWHERE },
-	{ "file::is-modified", NULL, "file", 6, GTH_METADATA_ALLOW_NOWHERE },
+	{ "gth::file::display-size", N_("Size"), "file", 2, GTH_METADATA_ALLOW_EVERYWHERE },
+	{ "gth::file::display-mtime", N_("Modified"), "file", 3, GTH_METADATA_ALLOW_EVERYWHERE },
+	{ "standard::fast-content-type", N_("Type"), "file", 4, GTH_METADATA_ALLOW_EVERYWHERE },
+	{ "gth::file::is-modified", NULL, "file", 5, GTH_METADATA_ALLOW_NOWHERE },
 
 	{ "Embedded::Image::DateTime", "", "", 0, GTH_METADATA_ALLOW_NOWHERE },
 	{ "Embedded::Image::Comment", "", "", 0, GTH_METADATA_ALLOW_NOWHERE },
diff --git a/gthumb/gth-main-default-sort-types.c b/gthumb/gth-main-default-sort-types.c
index c2083f7..9304d84 100644
--- a/gthumb/gth-main-default-sort-types.c
+++ b/gthumb/gth-main-default-sort-types.c
@@ -49,7 +49,7 @@ gth_file_data_cmp_filesize (GthFileData *a,
 
 	size_a = g_file_info_get_size (a->info);
 	size_b = g_file_info_get_size (b->info);
-	
+
 	if (size_a < size_b)
 		return -1;
 	else if (size_a > size_b)
@@ -86,18 +86,18 @@ gth_file_data_cmp_unsorted (GthFileData *a,
 
 
 GthFileDataSort default_sort_types[] = {
-	{ "file::name", N_("name"), gth_file_data_cmp_filename },
-	{ "file::size", N_("size"), gth_file_data_cmp_filesize },
-	{ "file::mtime", N_("last modified"), gth_file_data_cmp_modified_time },
-	{ "general::unsorted", N_("unsorted"), gth_file_data_cmp_unsorted },
+	{ "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 },
 };
 
 
-void 
+void
 gth_main_register_default_sort_types (void)
 {
 	int i;
-	
+
 	for (i = 0; i < G_N_ELEMENTS (default_sort_types); i++)
 		gth_main_register_sort_type (&default_sort_types[i]);
 }
diff --git a/gthumb/gth-main-default-tests.c b/gthumb/gth-main-default-tests.c
index 5afde5f..c479d06 100644
--- a/gthumb/gth-main-default-tests.c
+++ b/gthumb/gth-main-default-tests.c
@@ -133,12 +133,14 @@ gth_main_register_default_tests (void)
 				NULL);
 	gth_main_register_test ("file::name",
 				GTH_TYPE_TEST_SIMPLE,
+				"attributes", "gth::file::display-name",
 				"display-name", _("Filename"),
 				"data-type", GTH_TEST_DATA_TYPE_STRING,
 				"get-data-func", get_filename_for_test,
 				NULL);
 	gth_main_register_test ("file::size",
 				GTH_TYPE_TEST_SIMPLE,
+				"attributes", "gth::file::size",
 				"display-name", _("Size"),
 				"data-type", GTH_TEST_DATA_TYPE_SIZE,
 				"get-data-func", get_filesize_for_test,
diff --git a/gthumb/gth-metadata-provider-file.c b/gthumb/gth-metadata-provider-file.c
index 263f89d..d8dcaa7 100644
--- a/gthumb/gth-metadata-provider-file.c
+++ b/gthumb/gth-metadata-provider-file.c
@@ -45,49 +45,24 @@ gth_metadata_provider_file_read (GthMetadataProvider *self,
 				 const char          *attributes)
 {
 	GFileAttributeMatcher *matcher;
+	char                  *value;
+	GTimeVal              *timeval_p;
+	const char            *value_s;
 
 	matcher = g_file_attribute_matcher_new (attributes);
 
-	if (g_file_attribute_matcher_matches (matcher, "file::display-size")) {
-		char *value;
+	value = g_format_size_for_display (g_file_info_get_size (file_data->info));
+	g_file_info_set_attribute_string (file_data->info, "gth::file::display-size", value);
+	g_free (value);
 
-		value = g_format_size_for_display (g_file_info_get_size (file_data->info));
-		g_file_info_set_attribute_string (file_data->info, "file::display-size", value);
+	timeval_p = gth_file_data_get_modification_time (file_data);
+	value = _g_time_val_to_exif_date (timeval_p);
+	g_file_info_set_attribute_string (file_data->info, "gth::file::display-mtime", value);
+	g_free (value);
 
-		g_free (value);
-	}
-
-	if (g_file_attribute_matcher_matches (matcher, "file::display-ctime")) {
-		GTimeVal  timeval;
-		char     *value;
-
-		timeval.tv_sec = g_file_info_get_attribute_uint64 (file_data->info, "time::created");
-		timeval.tv_usec = g_file_info_get_attribute_uint32 (file_data->info, "time::created-usec");
-
-		value = _g_time_val_to_exif_date (&timeval);
-		g_file_info_set_attribute_string (file_data->info, "file::display-ctime", value);
-
-		g_free (value);
-	}
-
-	if (g_file_attribute_matcher_matches (matcher, "file::display-mtime")) {
-		GTimeVal *timeval;
-		char     *value;
-
-		timeval = gth_file_data_get_modification_time (file_data);
-		value = _g_time_val_to_exif_date (timeval);
-		g_file_info_set_attribute_string (file_data->info, "file::display-mtime", value);
-
-		g_free (value);
-	}
-
-	if (g_file_attribute_matcher_matches (matcher, "file::content-type")) {
-		const char *value;
-
-		value = get_static_string (g_file_info_get_content_type (file_data->info));
-		if (value != NULL)
-			g_file_info_set_attribute_string (file_data->info, "file::content-type", value);
-	}
+	value_s = get_static_string (g_file_info_get_content_type (file_data->info));
+	if (value_s != NULL)
+		g_file_info_set_attribute_string (file_data->info, "gth::file::content-type", value_s);
 
 	g_file_attribute_matcher_unref (matcher);
 }
@@ -117,7 +92,7 @@ gth_metadata_provider_constructor (GType                  type,
 	obj = parent_class->constructor (type, n_construct_properties, construct_properties);
 	self = GTH_METADATA_PROVIDER (obj);
 
-	g_object_set (self, "readable-attributes", "file::display-size,file::display-mtime,file::content-type,file::is-modified", NULL);
+	g_object_set (self, "readable-attributes", "gth::file::display-size,gth::file::display-mtime,gth::file::content-type,gth::file::is-modified", NULL);
 
 	return obj;
 }
diff --git a/gthumb/gth-metadata-provider.c b/gthumb/gth-metadata-provider.c
index 5dbc14a..2da41a5 100644
--- a/gthumb/gth-metadata-provider.c
+++ b/gthumb/gth-metadata-provider.c
@@ -115,6 +115,30 @@ gth_metadata_provider_set_property (GObject      *object,
 
 
 static void
+gth_metadata_provider_get_property (GObject    *object,
+				    guint       property_id,
+				    GValue     *value,
+				    GParamSpec *pspec)
+{
+	GthMetadataProvider *self;
+
+	self = GTH_METADATA_PROVIDER (object);
+
+	switch (property_id) {
+	case GTH_METADATA_PROVIDER_READABLE_ATTRIBUTES:
+		g_value_set_string (value, self->priv->_readable_attributes);
+		break;
+	case GTH_METADATA_PROVIDER_WRITABLE_ATTRIBUTES:
+		g_value_set_string (value, self->priv->_writable_attributes);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+		break;
+	}
+}
+
+
+static void
 gth_metadata_provider_finalize (GObject *obj)
 {
 	GthMetadataProvider *self;
@@ -135,6 +159,7 @@ gth_metadata_provider_class_init (GthMetadataProviderClass * klass)
 	g_type_class_add_private (klass, sizeof (GthMetadataProviderPrivate));
 
 	G_OBJECT_CLASS (klass)->set_property = gth_metadata_provider_set_property;
+	G_OBJECT_CLASS (klass)->get_property = gth_metadata_provider_get_property;
 	G_OBJECT_CLASS (klass)->finalize = gth_metadata_provider_finalize;
 
 	GTH_METADATA_PROVIDER_CLASS (klass)->read = gth_metadata_provider_real_read;
@@ -146,14 +171,14 @@ gth_metadata_provider_class_init (GthMetadataProviderClass * klass)
 					 		      "readable-attributes",
 					 		      "readable-attributes",
 					 		      NULL,
-					 		      G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+					 		      G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
 	g_object_class_install_property (G_OBJECT_CLASS (klass),
 					 GTH_METADATA_PROVIDER_WRITABLE_ATTRIBUTES,
 					 g_param_spec_string ("writable-attributes",
 					 		      "writable-attributes",
 					 		      "writable-attributes",
 					 		      NULL,
-					 		      G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+					 		      G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
 }
 
 
diff --git a/gthumb/gth-test-chain.c b/gthumb/gth-test-chain.c
index f68a65a..cb4b5da 100644
--- a/gthumb/gth-test-chain.c
+++ b/gthumb/gth-test-chain.c
@@ -33,6 +33,7 @@ struct _GthTestChainPrivate
 {
 	GthMatchType  match_type;
 	GList        *tests;
+	GString      *attributes;
 };
 
 
@@ -50,6 +51,8 @@ gth_test_chain_finalize (GObject *object)
 
 	if (test->priv != NULL) {
 		_g_object_list_unref (test->priv->tests);
+		if (test->priv->attributes != NULL)
+			g_string_free (test->priv->attributes, TRUE);
 		test->priv = NULL;
 	}
 
@@ -58,23 +61,23 @@ gth_test_chain_finalize (GObject *object)
 
 
 static GthMatch
-gth_test_chain_real_match (GthTest     *test,
-			   GthFileData *file)
+gth_test_chain_match (GthTest     *test,
+		      GthFileData *file)
 {
 	GthTestChain *chain;
 	GthMatch      match = GTH_MATCH_NO;
 	GList        *scan;
-	
+
         chain = GTH_TEST_CHAIN (test);
-	
+
 	if (chain->priv->match_type == GTH_MATCH_TYPE_NONE)
 		return GTH_MATCH_YES;
-	
+
 	match = (chain->priv->match_type == GTH_MATCH_TYPE_ALL) ? GTH_MATCH_YES : GTH_MATCH_NO;
 	for (scan = chain->priv->tests; scan; scan = scan->next) {
 		GthTest *test = scan->data;
-		
-		if (gth_test_match (test, file)) {				
+
+		if (gth_test_match (test, file)) {
 			if (chain->priv->match_type == GTH_MATCH_TYPE_ANY) {
 				match = GTH_MATCH_YES;
 				break;
@@ -85,11 +88,38 @@ gth_test_chain_real_match (GthTest     *test,
 			break;
 		}
 	}
-		
+
 	return match;
 }
 
 
+
+static const char *
+gth_test_chain_get_attributes (GthTest *test)
+{
+	GthTestChain *chain = GTH_TEST_CHAIN (test);
+	GList        *scan;
+
+	if (chain->priv->attributes != NULL)
+		g_string_free (chain->priv->attributes, TRUE);
+	chain->priv->attributes = g_string_new ("");
+
+	for (scan = chain->priv->tests; scan; scan = scan->next) {
+		GthTest    *test = scan->data;
+		const char *child_attributes;
+
+		child_attributes = gth_test_get_attributes (test);
+		if ((child_attributes != NULL) && (child_attributes[0] != '\0')) {
+			if (chain->priv->attributes->len > 0)
+				g_string_append (chain->priv->attributes, ",");
+			g_string_append (chain->priv->attributes, child_attributes);
+		}
+	}
+
+	return chain->priv->attributes->str;
+}
+
+
 static DomElement*
 gth_test_chain_real_create_element (DomDomizable *base,
 				    DomDocument  *doc)
@@ -97,15 +127,15 @@ gth_test_chain_real_create_element (DomDomizable *base,
 	GthTestChain *self;
 	DomElement   *element;
 	GList        *scan;
-	
+
 	self = GTH_TEST_CHAIN (base);
-	
-	element = dom_document_create_element (doc, "tests", 
+
+	element = dom_document_create_element (doc, "tests",
 					       "match", _g_enum_type_get_value (GTH_TYPE_MATCH_TYPE, self->priv->match_type)->value_nick,
-					       NULL);	
-	for (scan = self->priv->tests; scan; scan = scan->next) 
+					       NULL);
+	for (scan = self->priv->tests; scan; scan = scan->next)
 		dom_element_append_child (element, dom_domizable_create_element (DOM_DOMIZABLE (scan->data), doc));
-				       
+
 	return element;
 }
 
@@ -117,13 +147,13 @@ gth_test_chain_real_load_from_element (DomDomizable *base,
 	GthTestChain *chain;
 	GEnumValue   *enum_value;
 	DomElement   *node;
-	
+
 	chain = GTH_TEST_CHAIN (base);
-		      
+
 	enum_value = _g_enum_type_get_value_by_nick (GTH_TYPE_MATCH_TYPE, dom_element_get_attribute (element, "match"));
 	if (enum_value != NULL)
 		chain->priv->match_type = enum_value->value;
-	
+
 	gth_test_chain_clear_tests (chain);
 	for (node = element->first_child; node; node = node->next_sibling) {
 		if (g_strcmp0 (node->tag_name, "test") == 0) {
@@ -132,14 +162,14 @@ gth_test_chain_real_load_from_element (DomDomizable *base,
 			test = gth_main_get_test (dom_element_get_attribute (node, "id"));
 			if (test == NULL)
 				continue;
-			
+
 			dom_domizable_load_from_element (DOM_DOMIZABLE (test), node);
 			gth_test_chain_add_test (chain, test);
 			g_object_unref (test);
 		}
 		else if (g_strcmp0 (node->tag_name, "tests") == 0) {
 			GthTest *sub_chain;
-			
+
 			sub_chain = gth_test_chain_new (GTH_MATCH_TYPE_NONE, NULL);
 			dom_domizable_load_from_element (DOM_DOMIZABLE (sub_chain), node);
 			gth_test_chain_add_test (chain, sub_chain);
@@ -155,15 +185,15 @@ gth_test_chain_real_duplicate (GthDuplicable *duplicable)
 	GthTestChain *chain;
 	GthTest      *new_chain;
 	GList        *tests, *scan;
-	
+
 	chain = GTH_TEST_CHAIN (duplicable);
-	
+
 	new_chain = gth_test_chain_new (chain->priv->match_type, NULL);
 	tests = gth_test_chain_get_tests (chain);
 	for (scan = tests; scan; scan = scan->next)
 		gth_test_chain_add_test (GTH_TEST_CHAIN (new_chain), scan->data);
 	_g_object_list_unref (tests);
-	
+
 	return G_OBJECT (new_chain);
 }
 
@@ -179,7 +209,8 @@ gth_test_chain_class_init (GthTestChainClass *class)
 	test_class = (GthTestClass *) class;
 
 	object_class->finalize = gth_test_chain_finalize;
-	test_class->match = gth_test_chain_real_match;
+	test_class->match = gth_test_chain_match;
+	test_class->get_attributes = gth_test_chain_get_attributes;
 }
 
 
@@ -234,7 +265,7 @@ gth_test_chain_get_type (void)
 			(GInterfaceFinalizeFunc) NULL,
 			NULL
 		};
-		
+
 		type = g_type_register_static (GTH_TYPE_TEST,
 					       "GthTestChain",
 					       &type_info,
@@ -254,17 +285,17 @@ gth_test_chain_new (GthMatchType  match_type,
 {
 	GthTestChain *chain;
 	va_list       args;
-	
+
 	chain = g_object_new (GTH_TYPE_TEST_CHAIN, NULL);
 	chain->priv->match_type = match_type;
-	
+
 	va_start (args, test);
 	while (test != NULL) {
 		gth_test_chain_add_test (chain, g_object_ref (test));
 		test = va_arg (args, GthTest *);
 	}
 	va_end (args);
-	
+
 	return (GthTest *) chain;
 }
 
@@ -275,7 +306,7 @@ gth_test_chain_set_match_type (GthTestChain *chain,
 {
 	chain->priv->match_type = match_type;
 }
-					      
+
 
 GthMatchType
 gth_test_chain_get_match_type (GthTestChain *chain)
@@ -291,6 +322,7 @@ gth_test_chain_clear_tests (GthTestChain *chain)
 		return;
 	_g_object_list_unref (chain->priv->tests);
 	chain->priv->tests = NULL;
+	g_object_set (chain, "attributes", "", NULL);
 }
 
 
@@ -298,8 +330,28 @@ void
 gth_test_chain_add_test (GthTestChain *chain,
 			 GthTest      *test)
 {
+	const char *old_attributes;
+	const char *test_attributes;
+	gboolean    separator;
+	char       *attributes;
+
 	g_object_set (test, "visible", TRUE, NULL);
 	chain->priv->tests = g_list_append (chain->priv->tests, g_object_ref (test));
+
+	old_attributes = gth_test_get_attributes (GTH_TEST (chain));
+	test_attributes = gth_test_get_attributes (test);
+	if (old_attributes == NULL) {
+		old_attributes = test_attributes;
+		test_attributes = NULL;
+	}
+	separator = (old_attributes != NULL) && (test_attributes != NULL) && (old_attributes[0] != '\0') && (test_attributes[0] != '\0');
+	attributes = g_strconcat (old_attributes,
+			          (separator ? "," : ""),
+			          test_attributes,
+			          NULL);
+	g_object_set (chain, "attributes", attributes, NULL);
+
+	g_free (attributes);
 }
 
 
@@ -315,7 +367,7 @@ gth_test_chain_has_type_test (GthTestChain *chain)
 {
 	gboolean  result = FALSE;
 	GList    *scan;
-	
+
 	for (scan = chain->priv->tests; scan; scan = scan->next) {
 		GthTest *single_test = scan->data;
 
@@ -324,6 +376,6 @@ gth_test_chain_has_type_test (GthTestChain *chain)
 			break;
 		}
 	}
-	
+
 	return result;
 }
diff --git a/gthumb/gth-test-simple.c b/gthumb/gth-test-simple.c
index 7bca9fe..0c891f3 100644
--- a/gthumb/gth-test-simple.c
+++ b/gthumb/gth-test-simple.c
@@ -122,7 +122,7 @@ _gth_test_simple_free_data (GthTestSimple *test)
 	default:
 		break;
 	}
-	
+
 	if (test->priv->pattern != NULL) {
 		g_pattern_spec_free (test->priv->pattern);
 		test->priv->pattern = NULL;
@@ -283,7 +283,7 @@ create_control_for_size (GthTestSimple *test)
 
 	test->priv->size_combo_box = gtk_combo_box_new_text ();
 	gtk_widget_show (test->priv->size_combo_box);
-	
+
 	size_idx = 0;
 	for (i = 0; i < G_N_ELEMENTS (size_data); i++) {
 		gtk_combo_box_append_text (GTK_COMBO_BOX (test->priv->size_combo_box), _(size_data[i].name));
@@ -777,6 +777,7 @@ gth_test_simple_real_duplicate (GthDuplicable *duplicable)
 
 	new_test = g_object_new (GTH_TYPE_TEST_SIMPLE,
 				 "id", gth_test_get_id (GTH_TEST (test)),
+				 "attributes", gth_test_get_attributes (GTH_TEST (test)),
 				 "display-name", gth_test_get_display_name (GTH_TEST (test)),
 				 "visible", gth_test_is_visible (GTH_TEST (test)),
 				 NULL);
@@ -1008,7 +1009,7 @@ gth_test_simple_get_type (void)
 			(GInterfaceFinalizeFunc) NULL,
 			NULL
 		};
-		
+
 		type = g_type_register_static (GTH_TYPE_TEST,
 					       "GthTestSimple",
 					       &type_info,
diff --git a/gthumb/gth-test.c b/gthumb/gth-test.c
index 29598db..8a2d15d 100644
--- a/gthumb/gth-test.c
+++ b/gthumb/gth-test.c
@@ -34,6 +34,7 @@
 enum {
         PROP_0,
         PROP_ID,
+        PROP_ATTRIBUTES,
         PROP_DISPLAY_NAME,
         PROP_VISIBLE
 };
@@ -47,6 +48,7 @@ enum {
 struct _GthTestPrivate
 {
 	char      *id;
+	char      *attributes;
 	char      *display_name;
 	gboolean   visible;
 };
@@ -79,6 +81,13 @@ gth_test_finalize (GObject *object)
 }
 
 
+const char *
+base_get_attributes (GthTest *test)
+{
+	return test->priv->attributes;
+}
+
+
 static GtkWidget *
 base_create_control (GthTest *test)
 {
@@ -167,6 +176,7 @@ gth_test_real_duplicate (GthDuplicable *duplicable)
 
 	new_test = g_object_new (GTH_TYPE_TEST,
 				 "id", gth_test_get_id (test),
+				 "attributes", gth_test_get_attributes (test),
 				 "display-name", gth_test_get_display_name (test),
 				 "visible", gth_test_is_visible (test),
 				 NULL);
@@ -192,6 +202,12 @@ gth_test_set_property (GObject      *object,
 		if (test->priv->id == NULL)
 			test->priv->id = g_strdup ("");
 		break;
+	case PROP_ATTRIBUTES:
+		g_free (test->priv->attributes);
+		test->priv->attributes = g_value_dup_string (value);
+		if (test->priv->attributes == NULL)
+			test->priv->attributes = g_strdup ("");
+		break;
 	case PROP_DISPLAY_NAME:
 		g_free (test->priv->display_name);
 		test->priv->display_name = g_value_dup_string (value);
@@ -221,6 +237,9 @@ gth_test_get_property (GObject    *object,
 	case PROP_ID:
 		g_value_set_string (value, test->priv->id);
 		break;
+	case PROP_ATTRIBUTES:
+		g_value_set_string (value, test->priv->attributes);
+		break;
 	case PROP_DISPLAY_NAME:
 		g_value_set_string (value, test->priv->display_name);
 		break;
@@ -247,6 +266,7 @@ gth_test_class_init (GthTestClass *klass)
 	object_class->get_property = gth_test_get_property;
 	object_class->finalize = gth_test_finalize;
 
+	klass->get_attributes = base_get_attributes;
 	klass->create_control = base_create_control;
 	klass->update_from_control = base_update_from_control;
 	klass->reset = base_reset;
@@ -264,6 +284,13 @@ gth_test_class_init (GthTestClass *klass)
                                                               NULL,
                                                               G_PARAM_READWRITE));
 	g_object_class_install_property (object_class,
+					 PROP_ATTRIBUTES,
+					 g_param_spec_string ("attributes",
+                                                              "Attributes",
+                                                              "The attributes required to perform this test",
+                                                              NULL,
+                                                              G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
 					 PROP_DISPLAY_NAME,
 					 g_param_spec_string ("display-name",
                                                               "Display name",
@@ -372,6 +399,13 @@ gth_test_is_visible (GthTest *test)
 }
 
 
+const char *
+gth_test_get_attributes (GthTest *test)
+{
+	return GTH_TEST_GET_CLASS (test)->get_attributes (test);
+}
+
+
 GtkWidget *
 gth_test_create_control (GthTest *test)
 {
diff --git a/gthumb/gth-test.h b/gthumb/gth-test.h
index 6ff35ff..cf52d4f 100644
--- a/gthumb/gth-test.h
+++ b/gthumb/gth-test.h
@@ -48,7 +48,7 @@ typedef enum  {
 	GTH_MATCH_LIMIT_REACHED = 2
 } GthMatch;
 
-typedef enum { 
+typedef enum {
 	GTH_TEST_OP_NONE,
 	GTH_TEST_OP_EQUAL,
 	GTH_TEST_OP_LOWER,
@@ -66,9 +66,9 @@ struct _GthTest
 {
 	GObject __parent;
 	GthTestPrivate *priv;
-	
+
 	/*< protected >*/
-	
+
 	GthFileData **files;
 	int            n_files;
 	int            iterator;
@@ -84,6 +84,7 @@ struct _GthTestClass
 
 	/*< virtual functions >*/
 
+	const char *  (*get_attributes)       (GthTest     *test);
 	GtkWidget *   (*create_control)       (GthTest     *test);
 	gboolean      (*update_from_control)  (GthTest     *test,
 					       GError     **error);
@@ -102,6 +103,7 @@ GthTest *     gth_test_new                 (void);
 const char *  gth_test_get_id              (GthTest      *test);
 const char *  gth_test_get_display_name    (GthTest      *test);
 gboolean      gth_test_is_visible          (GthTest      *test);
+const char *  gth_test_get_attributes      (GthTest      *test);
 GtkWidget *   gth_test_create_control      (GthTest      *test);
 gboolean      gth_test_update_from_control (GthTest      *test,
 					    GError      **error);



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