nautilus-3.6.3/src/nautilus-image-properties-page.c

No issues found

  1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
  2 
  3 /* 
  4  * Copyright (C) 2004 Red Hat, Inc
  5  * Copyright (c) 2007 Novell, Inc.
  6  *
  7  * This program is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU General Public License as
  9  * published by the Free Software Foundation; either version 2 of the
 10  * License, or (at your option) any later version.
 11  *
 12  * This program is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15  * General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU General Public
 18  * License along with this program; if not, write to the
 19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 20  * Boston, MA 02111-1307, USA.
 21  *
 22  * Author: Alexander Larsson <alexl@redhat.com>
 23  * XMP support by Hubert Figuiere <hfiguiere@novell.com>
 24  */
 25 
 26 #include <config.h>
 27 #include "nautilus-image-properties-page.h"
 28 
 29 #include <gtk/gtk.h>
 30 #include <glib/gi18n.h>
 31 #include <gio/gio.h>
 32 #include <eel/eel-vfs-extensions.h>
 33 #include <libnautilus-extension/nautilus-property-page-provider.h>
 34 #include <libnautilus-private/nautilus-module.h>
 35 #include <string.h>
 36 
 37 #ifdef HAVE_EXIF
 38   #include <libexif/exif-data.h>
 39   #include <libexif/exif-ifd.h>
 40   #include <libexif/exif-loader.h>
 41 #endif
 42 #ifdef HAVE_EXEMPI
 43   #include <exempi/xmp.h>
 44   #include <exempi/xmpconsts.h>
 45 #endif
 46 
 47 #define LOAD_BUFFER_SIZE 8192
 48 
 49 struct NautilusImagePropertiesPageDetails {
 50 	GCancellable *cancellable;
 51 	GtkWidget *grid;
 52 	GdkPixbufLoader *loader;
 53 	gboolean got_size;
 54 	gboolean pixbuf_still_loading;
 55 	char buffer[LOAD_BUFFER_SIZE];
 56 	int width;
 57 	int height;
 58 #ifdef HAVE_EXIF
 59 	ExifLoader *exifldr;
 60 #endif /*HAVE_EXIF*/
 61 #ifdef HAVE_EXEMPI
 62 	XmpPtr     xmp;
 63 #endif
 64 };
 65 
 66 #ifdef HAVE_EXIF
 67 struct ExifAttribute {
 68 	ExifTag tag;
 69 	char *value;
 70 	gboolean found;
 71 };
 72 #endif /*HAVE_EXIF*/
 73 
 74 enum {
 75 	PROP_URI
 76 };
 77 
 78 typedef struct {
 79         GObject parent;
 80 } NautilusImagePropertiesPageProvider;
 81 
 82 typedef struct {
 83         GObjectClass parent;
 84 } NautilusImagePropertiesPageProviderClass;
 85 
 86 
 87 static GType nautilus_image_properties_page_provider_get_type (void);
 88 static void  property_page_provider_iface_init                (NautilusPropertyPageProviderIface *iface);
 89 
 90 
 91 G_DEFINE_TYPE (NautilusImagePropertiesPage, nautilus_image_properties_page, GTK_TYPE_BOX);
 92 
 93 G_DEFINE_TYPE_WITH_CODE (NautilusImagePropertiesPageProvider, nautilus_image_properties_page_provider, G_TYPE_OBJECT,
 94 			 G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_PROPERTY_PAGE_PROVIDER,
 95 						property_page_provider_iface_init));
 96 
 97 static void
 98 nautilus_image_properties_page_finalize (GObject *object)
 99 {
100 	NautilusImagePropertiesPage *page;
101 
102 	page = NAUTILUS_IMAGE_PROPERTIES_PAGE (object);
103 
104 	if (page->details->cancellable) {
105 		g_cancellable_cancel (page->details->cancellable);
106 		g_object_unref (page->details->cancellable);
107 		page->details->cancellable = NULL;
108 	}
109 
110 	G_OBJECT_CLASS (nautilus_image_properties_page_parent_class)->finalize (object);
111 }
112 
113 static void
114 file_close_callback (GObject      *object,
115 		     GAsyncResult *res,
116 		     gpointer      data)
117 {
118 	NautilusImagePropertiesPage *page;
119 	GInputStream *stream;
120 
121 	page = NAUTILUS_IMAGE_PROPERTIES_PAGE (data);
122 	stream = G_INPUT_STREAM (object);
123 
124 	g_input_stream_close_finish (stream, res, NULL);
125 
126 	g_object_unref (page->details->cancellable);
127 	page->details->cancellable = NULL;
128 }
129 
130 static void
131 append_item (NautilusImagePropertiesPage *page,
132 	     const char                  *name,
133 	     const char                  *value)
134 {
135 	GtkWidget *name_label;
136 	GtkWidget *label;
137 	PangoAttrList *attrs;
138 
139 	name_label = gtk_label_new (name);
140 	attrs = pango_attr_list_new ();
141 	pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
142 	gtk_label_set_attributes (GTK_LABEL (name_label), attrs);
143 	pango_attr_list_unref (attrs);
144 	gtk_misc_set_alignment (GTK_MISC (name_label), 0, 0);
145 	gtk_container_add (GTK_CONTAINER (page->details->grid), name_label);
146 	gtk_widget_show (name_label);
147 
148 	if (value != NULL) {
149 		label = gtk_label_new (value);
150 		gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
151 		gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
152 		gtk_grid_attach_next_to (GTK_GRID (page->details->grid), label,
153 					 name_label, GTK_POS_RIGHT,
154 					 1, 1);
155 		gtk_widget_show (label);
156 	}
157 }
158 
159 #ifdef HAVE_EXIF
160 static char *
161 exif_string_to_utf8 (const char *exif_str)
162 {
163 	char *utf8_str;
164 	
165 	if (g_utf8_validate (exif_str, -1, NULL)) {
166 		return g_strdup (exif_str);
167 	}
168 	
169 	utf8_str = g_locale_to_utf8 (exif_str, -1, NULL, NULL, NULL);
170 	if (utf8_str != NULL) {
171 		return utf8_str;
172 	}
173 	
174 	return eel_make_valid_utf8 (exif_str);
175 }
176 
177 static void
178 exif_content_callback (ExifContent *content, gpointer data)
179 {
180 	struct ExifAttribute *attribute;
181 	char b[1024];
182 
183 	attribute = (struct ExifAttribute *)data;
184 	if (attribute->found) {
185 		return;
186 	}
187 
188         attribute->value = g_strdup (exif_content_get_value (content, attribute->tag, b, sizeof(b)));
189 
190 	if (attribute->value != NULL) {
191 		attribute->found = TRUE;
192 	}
193 }
194 
195 static char *
196 exifdata_get_tag_name_utf8 (ExifTag tag) 
197 {
198 	return exif_string_to_utf8 (exif_tag_get_name (tag));
199 }
200 
201 static char *
202 exifdata_get_tag_value_utf8 (ExifData *data, ExifTag tag) 
203 {
204 	struct ExifAttribute attribute;
205 	char *utf8_value;
206 
207 	attribute.tag = tag;
208 	attribute.value = NULL;
209 	attribute.found = FALSE;
210 	
211 	exif_data_foreach_content (data, exif_content_callback, &attribute);
212 
213 	if (attribute.found) {
214 		utf8_value = exif_string_to_utf8 (attribute.value);
215 		g_free (attribute.value);
216 	} else {
217 		utf8_value = NULL;
218 	}
219 
220 	return utf8_value;
221 }
222 
223 static gboolean
224 append_tag_value_pair (NautilusImagePropertiesPage *page,
225 		       ExifData *data,
226 		       ExifTag   tag,
227 		       char     *description) 
228 {
229         char *utf_attribute;
230         char *utf_value;
231 
232 	utf_attribute = exifdata_get_tag_name_utf8 (tag);
233 	utf_value = exifdata_get_tag_value_utf8 (data, tag);
234 
235 	if ((utf_attribute == NULL) || (utf_value == NULL)) {
236 		g_free (utf_attribute);
237 		g_free (utf_value);
238    		return FALSE;
239 	}
240 
241 	append_item (page,
242 		     description ? description : utf_attribute,
243 		     utf_value);
244 
245         g_free (utf_attribute);
246         g_free (utf_value);
247 
248 	return TRUE;
249 }
250 
251 static void
252 append_exifdata_string (ExifData *exifdata, NautilusImagePropertiesPage *page)
253 {
254 	if (exifdata && exifdata->ifd[0] && exifdata->ifd[0]->count) {
255                 append_tag_value_pair (page, exifdata, EXIF_TAG_MAKE, _("Camera Brand"));
256                 append_tag_value_pair (page, exifdata, EXIF_TAG_MODEL, _("Camera Model"));
257 
258                 /* Choose which date to show in order of relevance */
259                 if (!append_tag_value_pair (page, exifdata, EXIF_TAG_DATE_TIME_ORIGINAL, _("Date Taken")))
260                 {
261                         if (!append_tag_value_pair (page, exifdata, EXIF_TAG_DATE_TIME_DIGITIZED, _("Date Digitized")))
262                         {
263                                 append_tag_value_pair (page, exifdata, EXIF_TAG_DATE_TIME, _("Date Modified"));
264                         }
265                 }
266 
267                 append_tag_value_pair (page, exifdata, EXIF_TAG_EXPOSURE_TIME, _("Exposure Time"));
268                 append_tag_value_pair (page, exifdata, EXIF_TAG_APERTURE_VALUE, _("Aperture Value"));
269                 append_tag_value_pair (page, exifdata, EXIF_TAG_ISO_SPEED_RATINGS, _("ISO Speed Rating"));
270                 append_tag_value_pair (page, exifdata, EXIF_TAG_FLASH,_("Flash Fired"));
271                 append_tag_value_pair (page, exifdata, EXIF_TAG_METERING_MODE, _("Metering Mode"));
272                 append_tag_value_pair (page, exifdata, EXIF_TAG_EXPOSURE_PROGRAM, _("Exposure Program"));
273                 append_tag_value_pair (page, exifdata, EXIF_TAG_FOCAL_LENGTH,_("Focal Length"));
274                 append_tag_value_pair (page, exifdata, EXIF_TAG_SOFTWARE, _("Software"));
275 	}
276 }
277 #endif /*HAVE_EXIF*/
278 
279 #ifdef HAVE_EXEMPI
280 static void
281 append_xmp_value_pair (NautilusImagePropertiesPage *page,
282 		       XmpPtr      xmp,
283 		       const char *ns,
284 		       const char *propname,
285 		       char       *descr)
286 {
287 	uint32_t options;
288 	XmpStringPtr value;
289 
290 	value = xmp_string_new();
291 	if (xmp_get_property (xmp, ns, propname, value, &options)) {
292 		if (XMP_IS_PROP_SIMPLE (options)) {
293 			append_item (page, descr, xmp_string_cstr (value));
294 		}
295 		else if (XMP_IS_PROP_ARRAY (options)) {
296 			XmpIteratorPtr iter;
297 
298 			iter = xmp_iterator_new (xmp, ns, propname, XMP_ITER_JUSTLEAFNODES);
299 			if (iter) {
300 				GString *str;
301 				gboolean first = TRUE;
302 
303 				str = g_string_new (NULL);
304 
305 				while (xmp_iterator_next (iter, NULL, NULL, value, &options) 
306 				       && !XMP_IS_PROP_QUALIFIER(options)) {
307 					if (!first) {
308 						g_string_append_printf (str, ", ");
309 					}
310 					else {
311 						first = FALSE;
312 					}
313 					g_string_append_printf (str,
314 								"%s",
315 								xmp_string_cstr(value));
316 				}
317 				xmp_iterator_free(iter);
318 				append_item (page, descr, g_string_free (str, FALSE));
319 			}
320 		}
321 	}
322 	xmp_string_free(value);
323 }
324 
325 static void
326 append_xmpdata_string (XmpPtr xmp, NautilusImagePropertiesPage *page)
327 {
328 	if (xmp != NULL) {
329 		append_xmp_value_pair (page, xmp, NS_IPTC4XMP, "Location", _("Location"));
330 		append_xmp_value_pair (page, xmp, NS_DC, "description", _("Description"));
331 		append_xmp_value_pair (page, xmp, NS_DC, "subject", _("Keywords"));
332 		append_xmp_value_pair (page, xmp, NS_DC, "creator", _("Creator"));
333 		append_xmp_value_pair (page, xmp, NS_DC, "rights", _("Copyright"));
334 		append_xmp_value_pair (page, xmp, NS_XAP,"Rating", _("Rating"));
335 		/* TODO add CC licenses */
336 	}
337 }
338 #endif
339 
340 static void
341 load_finished (NautilusImagePropertiesPage *page)
342 {
343 	GdkPixbufFormat *format;
344 	GtkWidget *label;
345 	char *name, *desc;
346 	char *value;
347 
348 	label = gtk_grid_get_child_at (GTK_GRID (page->details->grid), 0, 0);
349 	gtk_container_remove (GTK_CONTAINER (page->details->grid), label);
350 
351 	if (page->details->loader != NULL) {
352 		gdk_pixbuf_loader_close (page->details->loader, NULL);
353 	}
354 
355 	if (page->details->got_size) {
356 #ifdef HAVE_EXIF
357                 ExifData *exif_data;
358 #endif
359 
360 		format = gdk_pixbuf_loader_get_format (page->details->loader);
361 	
362 		name = gdk_pixbuf_format_get_name (format);
363 		desc = gdk_pixbuf_format_get_description (format);
364 		value = g_strdup_printf ("%s (%s)", name, desc);
365 		g_free (name);
366 		g_free (desc);
367 		append_item (page, _("Image Type"), value);
368 		g_free (value);
369 		value = g_strdup_printf (ngettext ("%d pixel",
370 						   "%d pixels",
371 						   page->details->width),
372 					 page->details->width);
373 		append_item (page, _("Width"), value);
374 		g_free (value);
375 		value = g_strdup_printf (ngettext ("%d pixel",
376 						   "%d pixels",
377 						   page->details->height),
378 					 page->details->height);
379 		append_item (page, _("Height"), value);
380 		g_free (value);
381 #ifdef HAVE_EXIF
382 		exif_data = exif_loader_get_data (page->details->exifldr);
383                 append_exifdata_string (exif_data, page);
384                 exif_data_unref (exif_data);
385 #endif /*HAVE_EXIF*/
386 #ifdef HAVE_EXEMPI
387 		append_xmpdata_string (page->details->xmp, page);
388 #endif /*HAVE EXEMPI*/		
389 	} else {
390 		append_item (page, _("Failed to load image information"), NULL);
391 	}
392 
393 	if (page->details->loader != NULL) {
394 		g_object_unref (page->details->loader);
395 		page->details->loader = NULL;
396 	}
397 #ifdef HAVE_EXIF
398 	if (page->details->exifldr != NULL) {
399 		exif_loader_unref (page->details->exifldr);
400 		page->details->exifldr = NULL;
401 	}
402 #endif /*HAVE_EXIF*/
403 #ifdef HAVE_EXEMPI
404 	if (page->details->xmp != NULL) {
405 		xmp_free (page->details->xmp);
406 		page->details->xmp = NULL;
407 	}
408 #endif
409 }
410 
411 static void
412 file_read_callback (GObject      *object,
413 		    GAsyncResult *res,
414 		    gpointer      data)
415 {
416 	NautilusImagePropertiesPage *page;
417 	GInputStream *stream;
418 	gssize count_read;
419 	GError *error;
420 	int exif_still_loading;
421 	gboolean done_reading;
422 
423 	page = NAUTILUS_IMAGE_PROPERTIES_PAGE (data);
424 	stream = G_INPUT_STREAM (object);
425 
426 	error = NULL;
427 	done_reading = FALSE;
428 	count_read = g_input_stream_read_finish (stream, res, &error);
429 
430 	if (count_read > 0) {
431 
432 		g_assert (count_read <= sizeof(page->details->buffer));
433 
434 #ifdef HAVE_EXIF
435 		exif_still_loading = exif_loader_write (page->details->exifldr,
436 				  		        (guchar *) page->details->buffer,
437 				  			count_read);
438 #else
439 		exif_still_loading = 0;
440 #endif
441 
442 		if (page->details->pixbuf_still_loading) {
443 			if (!gdk_pixbuf_loader_write (page->details->loader,
444 					      	      (const guchar *) page->details->buffer,
445 					      	      count_read,
446 					      	      NULL)) {
447 				page->details->pixbuf_still_loading = FALSE;
448 			}
449 		}
450 
451 		if (page->details->pixbuf_still_loading ||
452 		    (exif_still_loading == 1)) {
453 			g_input_stream_read_async (G_INPUT_STREAM (stream),
454 						   page->details->buffer,
455 						   sizeof (page->details->buffer),
456 						   0,
457 						   page->details->cancellable,
458 						   file_read_callback,
459 						   page);
460 		}
461 		else {
462 			done_reading = TRUE;
463 		}
464 	}
465 	else {
466 		/* either EOF, cancelled or an error occurred */
467 		done_reading = TRUE;
468 	}
469 
470 	if (error != NULL) {
471 		char *uri = g_file_get_uri (G_FILE (object));
472 		g_warning ("Error reading %s: %s", uri, error->message);
473 		g_free (uri);
474 		g_clear_error (&error);
475 	}
476 
477 	if (done_reading) {
478 		load_finished (page);
479 		g_input_stream_close_async (stream,
480 					    0,
481 					    page->details->cancellable,
482 					    file_close_callback,
483 					    page);
484 	}
485 }
486 
487 static void
488 size_prepared_callback (GdkPixbufLoader *loader, 
489 			int              width,
490 			int              height,
491 			gpointer         callback_data)
492 {
493 	NautilusImagePropertiesPage *page;
494 
495 	page = NAUTILUS_IMAGE_PROPERTIES_PAGE (callback_data);
496 
497 	page->details->height = height;
498 	page->details->width = width;
499 	page->details->got_size = TRUE;
500 	page->details->pixbuf_still_loading = FALSE;
501 }
502 
503 typedef struct {
504 	NautilusImagePropertiesPage *page;
505 	NautilusFileInfo            *info;
506 } FileOpenData;
507 
508 static void
509 file_open_callback (GObject      *object,
510 		    GAsyncResult *res,
511 		    gpointer      user_data)
512 {
513 	FileOpenData *data = user_data;
514 	NautilusImagePropertiesPage *page = data->page;
515 	GFile *file;
516 	GFileInputStream *stream;
517 	GError *error;
518 	char *uri;
519 
520 	file = G_FILE (object);
521 	uri = g_file_get_uri (file);
522 
523 	error = NULL;
524 	stream = g_file_read_finish (file, res, &error);
525 	if (stream) {
526 		char *mime_type;
527 
528 		mime_type = nautilus_file_info_get_mime_type (data->info);
529 		page->details->loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, &error);
530 		if (error != NULL) {
531 			g_warning ("Error creating loader for %s: %s", uri, error->message);
532 			g_clear_error (&error);
533 		}
534 		page->details->pixbuf_still_loading = TRUE;
535 		page->details->width = 0;
536 		page->details->height = 0;
537 #ifdef HAVE_EXIF
538 		page->details->exifldr = exif_loader_new ();
539 #endif /*HAVE_EXIF*/
540 		g_free (mime_type);
541 
542 		g_signal_connect (page->details->loader,
543 				  "size_prepared",
544 				  G_CALLBACK (size_prepared_callback),
545 				  page);
546 
547 		g_input_stream_read_async (G_INPUT_STREAM (stream),
548 					   page->details->buffer,
549 					   sizeof (page->details->buffer),
550 					   0,
551 					   page->details->cancellable,
552 					   file_read_callback,
553 					   page);
554 
555 		g_object_unref (stream);
556 	} else {
557 		g_warning ("Error reading %s: %s", uri, error->message);
558 		g_clear_error (&error);
559 		load_finished (page);
560 	}
561 
562 	g_free (uri);
563 	g_free (data);
564 }
565 
566 static void
567 load_location (NautilusImagePropertiesPage *page,
568 	       NautilusFileInfo            *info)
569 {
570 	GFile *file;
571 	char *uri;
572 	FileOpenData *data;
573 
574 	g_assert (NAUTILUS_IS_IMAGE_PROPERTIES_PAGE (page));
575 	g_assert (info != NULL);
576 
577 	page->details->cancellable = g_cancellable_new ();
578 
579 	uri = nautilus_file_info_get_uri (info);
580 	file = g_file_new_for_uri (uri);
581 
582 #ifdef HAVE_EXEMPI
583 	{
584 		/* Current Exempi does not support setting custom IO to be able to use Gnome-vfs */
585 		/* So it will only work with local files. Future version might remove this limitation */
586 		XmpFilePtr xf;
587 		char *localname;
588 
589 		localname = g_filename_from_uri (uri, NULL, NULL);
590 		if (localname) {
591 			xf = xmp_files_open_new (localname, 0);
592 			page->details->xmp = xmp_files_get_new_xmp (xf); /* only load when loading */
593 			xmp_files_close (xf, 0);
594 			g_free (localname);
595 		}
596 		else {
597 			page->details->xmp = NULL;
598 		}
599 	}
600 #endif /*HAVE_EXEMPI*/
601 
602 	data = g_new0 (FileOpenData, 1);
603 	data->page = page;
604 	data->info = info;
605 
606 	g_file_read_async (file,
607 			   0,
608 			   page->details->cancellable,
609 			   file_open_callback,
610 			   data);
611 
612 	g_object_unref (file);
613 	g_free (uri);
614 }
615 
616 static void
617 nautilus_image_properties_page_class_init (NautilusImagePropertiesPageClass *class)
618 {
619 	GObjectClass *object_class;
620 
621 	object_class = G_OBJECT_CLASS (class);
622 
623 	object_class->finalize = nautilus_image_properties_page_finalize;
624 
625 	g_type_class_add_private (object_class, sizeof(NautilusImagePropertiesPageDetails));
626 }
627 
628 static void
629 nautilus_image_properties_page_init (NautilusImagePropertiesPage *page)
630 {
631 	GtkWidget *sw;
632 
633 	page->details = G_TYPE_INSTANCE_GET_PRIVATE (page,
634 						     NAUTILUS_TYPE_IMAGE_PROPERTIES_PAGE,
635 						     NautilusImagePropertiesPageDetails);
636 
637 	gtk_orientable_set_orientation (GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL);
638 	gtk_box_set_homogeneous (GTK_BOX (page), FALSE);
639 	gtk_box_set_spacing (GTK_BOX (page), 0);
640 	gtk_container_set_border_width (GTK_CONTAINER (page), 0);
641 
642 	sw = gtk_scrolled_window_new (NULL, NULL);
643 	gtk_container_set_border_width (GTK_CONTAINER (sw), 0);
644 	gtk_widget_set_vexpand (GTK_WIDGET (sw), TRUE);
645 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
646 					GTK_POLICY_NEVER,
647 					GTK_POLICY_AUTOMATIC);
648 	gtk_box_pack_start (GTK_BOX (page), sw, FALSE, TRUE, 2);
649 
650 	page->details->grid = gtk_grid_new ();
651 	gtk_container_set_border_width (GTK_CONTAINER (page->details->grid), 6);
652 	gtk_orientable_set_orientation (GTK_ORIENTABLE (page->details->grid), GTK_ORIENTATION_VERTICAL);
653 	gtk_grid_set_row_spacing (GTK_GRID (page->details->grid), 6);
654 	gtk_grid_set_column_spacing (GTK_GRID (page->details->grid), 20);
655 	append_item (page, _("Loading..."), NULL);
656 	gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), page->details->grid);
657 
658 	gtk_widget_show_all (GTK_WIDGET (page));
659 }
660 
661 static gboolean
662 is_mime_type_supported (const char *mime_type)
663 {
664 	gboolean supported;
665 	GSList *formats;
666 	GSList *l;
667 
668 	supported = FALSE;
669 	formats = gdk_pixbuf_get_formats ();
670 
671 	for (l = formats; supported == FALSE && l != NULL; l = l->next) {
672 		GdkPixbufFormat *format = l->data;
673 		char **mime_types = gdk_pixbuf_format_get_mime_types (format);
674 		int i;
675 
676 		for (i = 0; mime_types[i] != NULL; i++) {
677 			if (strcmp (mime_types[i], mime_type) == 0) {
678 				supported = TRUE;
679 				break;
680 			}
681 		}
682 		g_strfreev (mime_types);
683 	}
684 	g_slist_free (formats);
685 
686 	return supported;
687 }
688 
689 static GList *
690 get_property_pages (NautilusPropertyPageProvider *provider,
691                     GList *files)
692 {
693 	GList *pages;
694 	NautilusFileInfo *file;
695 	char *mime_type;
696 
697 	/* Only show the property page if 1 file is selected */
698 	if (!files || files->next != NULL) {
699 		return NULL;
700 	}
701 
702 	pages = NULL;
703 	file = NAUTILUS_FILE_INFO (files->data);
704 
705 	mime_type = nautilus_file_info_get_mime_type (file);
706 	if (mime_type != NULL
707 	    && is_mime_type_supported (mime_type)) {
708 		NautilusImagePropertiesPage *page;
709 		NautilusPropertyPage *real_page;
710 
711 		page = g_object_new (nautilus_image_properties_page_get_type (), NULL);
712 		load_location (page, file);
713 
714 		real_page = nautilus_property_page_new
715 			("NautilusImagePropertiesPage::property_page", 
716 			 gtk_label_new (_("Image")),
717 			 GTK_WIDGET (page));
718 		pages = g_list_append (pages, real_page);
719 	}
720 
721 	g_free (mime_type);
722 
723 	return pages;
724 }
725 
726 static void 
727 property_page_provider_iface_init (NautilusPropertyPageProviderIface *iface)
728 {
729 	iface->get_pages = get_property_pages;
730 }
731 
732 
733 static void
734 nautilus_image_properties_page_provider_init (NautilusImagePropertiesPageProvider *sidebar)
735 {
736 }
737 
738 static void
739 nautilus_image_properties_page_provider_class_init (NautilusImagePropertiesPageProviderClass *class)
740 {
741 }
742 
743 void
744 nautilus_image_properties_page_register (void)
745 {
746         nautilus_module_add_type (nautilus_image_properties_page_provider_get_type ());
747 }