diff options
author | Lucas Rocha <lucasr@gnome.org> | 2007-07-18 23:24:59 +0000 |
---|---|---|
committer | Lucas Almeida Rocha <lucasr@src.gnome.org> | 2007-07-18 23:24:59 +0000 |
commit | e754da90e337345c5a17377bf8a646bcb05dca61 (patch) | |
tree | 11fdf158b0842722d501ed008d854b3a81cd842d | |
parent | a653d4daa7e596f707fdfdf0dc551d4d1fdf04a2 (diff) | |
download | eog-e754da90e337345c5a17377bf8a646bcb05dca61.tar.gz |
Optional XMP metadata support. Fixes bug #451101 (Hubert Figuiere).
2007-07-19 Lucas Rocha <lucasr@gnome.org>
* src/eog-exif-details.[c,h], src/main.c,
src/eog-properties-dialog.[c.h], src/eog-metadata-reader.[c,h],
src/eog-image.[c,h], src/eog-image-private.h, src/Makefile.am,
data/eog.glade, configure.ac: Optional XMP metadata support.
Fixes bug #451101 (Hubert Figuiere).
svn path=/trunk/; revision=3890
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | configure.ac | 20 | ||||
-rw-r--r-- | data/eog.glade | 1243 | ||||
-rw-r--r-- | src/Makefile.am | 12 | ||||
-rw-r--r-- | src/eog-exif-details.c | 122 | ||||
-rw-r--r-- | src/eog-exif-details.h | 11 | ||||
-rw-r--r-- | src/eog-image-private.h | 3 | ||||
-rw-r--r-- | src/eog-image.c | 62 | ||||
-rw-r--r-- | src/eog-image.h | 12 | ||||
-rw-r--r-- | src/eog-metadata-reader.c | 183 | ||||
-rw-r--r-- | src/eog-metadata-reader.h | 7 | ||||
-rw-r--r-- | src/eog-properties-dialog.c | 190 | ||||
-rw-r--r-- | src/eog-properties-dialog.h | 3 | ||||
-rw-r--r-- | src/main.c | 10 |
14 files changed, 1401 insertions, 485 deletions
@@ -1,3 +1,11 @@ +2007-07-19 Lucas Rocha <lucasr@gnome.org> + + * src/eog-exif-details.[c,h], src/main.c, + src/eog-properties-dialog.[c.h], src/eog-metadata-reader.[c,h], + src/eog-image.[c,h], src/eog-image-private.h, src/Makefile.am, + data/eog.glade, configure.ac: Optional XMP metadata support. + Fixes bug #451101 (Hubert Figuiere). + 2007-07-16 Claudio Saavedra <csaavedra@alumnos.utalca.cl> * configure.ac: Bumped gnome-icon-theme requirement to 2.19.1. diff --git a/configure.ac b/configure.ac index b3307a87..8f196763 100644 --- a/configure.ac +++ b/configure.ac @@ -74,6 +74,8 @@ LIBART_REQUIRED=2.3.16 GNOME_DESKTOP_REQUIRED=2.10.0 GTK_PRINT_REQUIRED=2.10.0 GNOME_ICON_THEME_REQUIRED=2.19.1 +EXEMPI_REQUIRED=1.99.2 + EOG_MODULES="gtk+-2.0 >= $GTK_REQUIRED \ glib-2.0 >= $GLIB_REQUIRED \ @@ -119,6 +121,23 @@ if test "x$have_lcms" = "xyes"; then EOG_MODULES="$EOG_MODULES lcms" fi + +# ********************* +# Exempi (optional) +# ********************* +AC_ARG_WITH(xmp, AC_HELP_STRING([--without-xmp], [disable special XMP support])) +have_exempi=no +if test x$with_xmp != xno; then + PKG_CHECK_MODULES(EXEMPI, exempi-2.0 >= $EXEMPI_REQUIRED, have_exempi=yes, have_exempi=no) +fi +if test "x$have_exempi" = "xyes"; then + AC_DEFINE(HAVE_EXEMPI,1, [XMP support.]) + EOG_MODULES="$EOG_MODULES exempi-2.0 >= $EXEMPI_REQUIRED" +fi + +AM_CONDITIONAL([HAVE_EXEMPI], [test "x$have_exempi" = "xyes"]) + + # ******************** # Jpeg (semi-optional) # ******************** @@ -368,6 +387,7 @@ Configure summary: Extra Compiler Warnings ....: ${WARN_CFLAGS} EXIF support ...............: ${have_exif} + XMP support ................: ${have_exempi} JPEG support ...............: ${have_jpeg} Colour management support ..: ${have_lcms} D-Bus activation............: ${have_dbus} diff --git a/data/eog.glade b/data/eog.glade index db6b8621..83ea0449 100644 --- a/data/eog.glade +++ b/data/eog.glade @@ -232,6 +232,8 @@ <property name="width_request">100</property> <property name="height_request">100</property> <property name="visible">True</property> + <property name="stock">gtk-missing-image</property> + <property name="icon_size">4</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">0</property> @@ -430,7 +432,7 @@ <child> <widget class="GtkLabel" id="name_label"> <property name="visible">True</property> - <property name="label">...</property> + <property name="label"></property> <property name="use_underline">False</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -455,7 +457,7 @@ <child> <widget class="GtkLabel" id="width_label"> <property name="visible">True</property> - <property name="label">...</property> + <property name="label"></property> <property name="use_underline">False</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -480,7 +482,7 @@ <child> <widget class="GtkLabel" id="height_label"> <property name="visible">True</property> - <property name="label">...</property> + <property name="label"></property> <property name="use_underline">False</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -505,7 +507,7 @@ <child> <widget class="GtkLabel" id="type_label"> <property name="visible">True</property> - <property name="label">...</property> + <property name="label"></property> <property name="use_underline">False</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -530,7 +532,7 @@ <child> <widget class="GtkLabel" id="bytes_label"> <property name="visible">True</property> - <property name="label">...</property> + <property name="label"></property> <property name="use_underline">False</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -555,7 +557,7 @@ <child> <widget class="GtkLabel" id="location_label"> <property name="visible">True</property> - <property name="label">...</property> + <property name="label"></property> <property name="use_underline">False</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -634,208 +636,359 @@ <property name="spacing">7</property> <child> - <widget class="GtkVBox" id="vbox31"> + <widget class="GtkVBox" id="vbox38"> <property name="visible">True</property> <property name="homogeneous">False</property> - <property name="spacing">5</property> + <property name="spacing">0</property> <child> - <widget class="GtkLabel" id="label88"> + <widget class="GtkVBox" id="vbox31"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Aperture Value:</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> + <property name="homogeneous">False</property> + <property name="spacing">5</property> - <child> - <widget class="GtkLabel" id="label83"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Exposure Time:</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> + <child> + <widget class="GtkLabel" id="label88"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Aperture Value:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> - <child> - <widget class="GtkLabel" id="label96"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Focal Length:</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> + <child> + <widget class="GtkLabel" id="label83"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Exposure Time:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> - <child> - <widget class="GtkLabel" id="label95"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Flash:</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> + <child> + <widget class="GtkLabel" id="label96"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Focal Length:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> - <child> - <widget class="GtkLabel" id="label94"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>ISO Speed Rating:</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> + <child> + <widget class="GtkLabel" id="label95"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Flash:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> - <child> - <widget class="GtkLabel" id="label93"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Metering Mode:</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> + <child> + <widget class="GtkLabel" id="label94"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>ISO Speed Rating:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> - <child> - <widget class="GtkLabel" id="label92"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Camera Model:</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_RIGHT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> + <child> + <widget class="GtkLabel" id="label93"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Metering Mode:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label92"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Camera Model:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label91"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Date/Time:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> </widget> <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> + <property name="padding">5</property> + <property name="expand">True</property> + <property name="fill">True</property> </packing> </child> <child> - <widget class="GtkLabel" id="label91"> + <widget class="GtkVBox" id="xmp_box"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Date/Time:</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> + <property name="homogeneous">False</property> + <property name="spacing">5</property> + + <child> + <widget class="GtkLabel" id="label111"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Description:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label110"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Location:</b> </property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label112"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Keywords:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label113"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Author:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label114"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Copyright:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> </widget> <packing> <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> + <property name="expand">True</property> + <property name="fill">True</property> </packing> </child> </widget> @@ -847,208 +1000,359 @@ </child> <child> - <widget class="GtkVBox" id="vbox32"> + <widget class="GtkVBox" id="vbox40"> <property name="visible">True</property> <property name="homogeneous">False</property> - <property name="spacing">5</property> + <property name="spacing">0</property> <child> - <widget class="GtkLabel" id="exif_aperture_label"> + <widget class="GtkVBox" id="vbox32"> <property name="visible">True</property> - <property name="label">...</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_RIGHT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> + <property name="homogeneous">False</property> + <property name="spacing">5</property> - <child> - <widget class="GtkLabel" id="exif_exposure_label"> - <property name="visible">True</property> - <property name="label">...</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> + <child> + <widget class="GtkLabel" id="exif_aperture_label"> + <property name="visible">True</property> + <property name="label"></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> - <child> - <widget class="GtkLabel" id="exif_focal_label"> - <property name="visible">True</property> - <property name="label">...</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> + <child> + <widget class="GtkLabel" id="exif_exposure_label"> + <property name="visible">True</property> + <property name="label"></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> - <child> - <widget class="GtkLabel" id="exif_flash_label"> - <property name="visible">True</property> - <property name="label">...</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_END</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> + <child> + <widget class="GtkLabel" id="exif_focal_label"> + <property name="visible">True</property> + <property name="label"></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> - <child> - <widget class="GtkLabel" id="exif_iso_label"> - <property name="visible">True</property> - <property name="label">...</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> + <child> + <widget class="GtkLabel" id="exif_flash_label"> + <property name="visible">True</property> + <property name="label"></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_END</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> - <child> - <widget class="GtkLabel" id="exif_metering_label"> - <property name="visible">True</property> - <property name="label">...</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> + <child> + <widget class="GtkLabel" id="exif_iso_label"> + <property name="visible">True</property> + <property name="label"></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> - <child> - <widget class="GtkLabel" id="exif_model_label"> - <property name="visible">True</property> - <property name="label">...</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> + <child> + <widget class="GtkLabel" id="exif_metering_label"> + <property name="visible">True</property> + <property name="label"></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="exif_model_label"> + <property name="visible">True</property> + <property name="label"></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="exif_date_label"> + <property name="visible">True</property> + <property name="label"></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> </widget> <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> + <property name="padding">5</property> + <property name="expand">True</property> + <property name="fill">True</property> </packing> </child> <child> - <widget class="GtkLabel" id="exif_date_label"> + <widget class="GtkVBox" id="xmp_box_label"> <property name="visible">True</property> - <property name="label">...</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> + <property name="homogeneous">False</property> + <property name="spacing">5</property> + + <child> + <widget class="GtkLabel" id="xmp_description_label"> + <property name="visible">True</property> + <property name="label"></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="xmp_location_label"> + <property name="visible">True</property> + <property name="label"></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="xmp_keywords_label"> + <property name="visible">True</property> + <property name="label"></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="xmp_creator_label"> + <property name="visible">True</property> + <property name="label"></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_END</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="xmp_rights_label"> + <property name="visible">True</property> + <property name="label"></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> </widget> <packing> <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> + <property name="expand">True</property> + <property name="fill">True</property> </packing> </child> </widget> @@ -1117,7 +1421,7 @@ <child> <widget class="GtkLabel" id="label44"> <property name="visible">True</property> - <property name="label">EXIF</property> + <property name="label">Metadata</property> <property name="use_underline">False</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -1663,10 +1967,10 @@ <property name="column_spacing">6</property> <child> - <widget class="GtkRadioButton" id="left_radio"> + <widget class="GtkRadioButton" id="bottom_radio"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="label" translatable="yes">Left</property> + <property name="label" translatable="yes">Bottom</property> <property name="use_underline">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> @@ -1675,80 +1979,77 @@ <property name="draw_indicator">True</property> </widget> <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options"></property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkRadioButton" id="right_radio"> + <widget class="GtkRadioButton" id="top_radio"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="label" translatable="yes">Right</property> + <property name="label" translatable="yes">Top</property> <property name="use_underline">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> <property name="active">False</property> <property name="inconsistent">False</property> <property name="draw_indicator">True</property> - <property name="group">left_radio</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options"></property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkRadioButton" id="top_radio"> + <widget class="GtkRadioButton" id="right_radio"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="label" translatable="yes">Top</property> + <property name="label" translatable="yes">Right</property> <property name="use_underline">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> <property name="active">False</property> <property name="inconsistent">False</property> <property name="draw_indicator">True</property> - <property name="group">left_radio</property> </widget> <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options"></property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkRadioButton" id="bottom_radio"> + <widget class="GtkRadioButton" id="left_radio"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="label" translatable="yes">Bottom</property> + <property name="label" translatable="yes">Left</property> <property name="use_underline">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> <property name="active">False</property> <property name="inconsistent">False</property> <property name="draw_indicator">True</property> - <property name="group">left_radio</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options"></property> <property name="y_options"></property> </packing> </child> @@ -2379,6 +2680,114 @@ <property name="column_spacing">6</property> <child> + <widget class="GtkLabel" id="label10"> + <property name="visible">True</property> + <property name="label" translatable="yes">Destination folder:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + </packing> + </child> + + <child> + <widget class="GtkFileChooserButton" id="dir_chooser"> + <property name="visible">True</property> + <property name="title" translatable="yes">Choose a folder</property> + <property name="action">GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER</property> + <property name="local_only">False</property> + <property name="show_hidden">False</property> + <property name="do_overwrite_confirmation">False</property> + <property name="width_chars">-1</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">3</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label11"> + <property name="visible">True</property> + <property name="label" translatable="yes">Filename format:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="token_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes">%f</property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> + <signal name="changed" handler="on_token_entry_changed"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + + <child> + <widget class="GtkComboBox" id="format_combobox"> + <property name="visible">True</property> + <property name="items" translatable="yes"> +</property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + + <child> <widget class="GtkVBox" id="vbox2"> <property name="visible">True</property> <property name="homogeneous">False</property> @@ -2651,7 +3060,7 @@ <property name="snap_to_ticks">False</property> <property name="wrap">False</property> <property name="adjustment">1 0 10000000 1 10 10</property> - <signal name="changed" handler="on_counter_spin_changed" last_modification_time="Wed, 30 Jun 2004 20:04:23 GMT"/> + <signal name="changed" handler="on_counter_spin_changed"/> </widget> <packing> <property name="padding">0</property> @@ -2793,17 +3202,17 @@ <property name="angle">0</property> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> </packing> </child> <child> - <widget class="GtkLabel" id="label35"> + <widget class="GtkLabel" id="preview_label_from"> <property name="visible">True</property> - <property name="label" translatable="yes">To:</property> + <property name="label" translatable="yes">label</property> <property name="use_underline">False</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -2819,17 +3228,17 @@ <property name="angle">0</property> </widget> <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> </packing> </child> <child> - <widget class="GtkLabel" id="label24"> + <widget class="GtkLabel" id="preview_label"> <property name="visible">True</property> - <property name="label" translatable="yes">Rename from:</property> + <property name="label" translatable="yes">label</property> <property name="use_underline">False</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -2845,10 +3254,10 @@ <property name="angle">0</property> </widget> <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> </packing> </child> </widget> diff --git a/src/Makefile.am b/src/Makefile.am index 5e148da6..cc02273a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -120,11 +120,17 @@ libeog_la_SOURCES += \ eog-python-plugin.h endif +if HAVE_EXEMPI +libeog_la_SOURCES += \ + eog-exif-details.h \ + eog-exif-details.c +endif + libeog_la_CFLAGS = \ $(EOG_CFLAGS) \ $(WARN_CFLAGS) \ -I$(top_srcdir)/jpegutils \ - -I$(top_srcdir)/cut-n-paste/toolbar-editor \ + -I$(top_srcdir)/cut-n-paste/toolbar-editor \ -DG_LOG_DOMAIN=\"EOG\" \ -DEOG_PREFIX=\""${prefix}"\" \ -DEOG_DATA_DIR=\""$(pkgdatadir)"\" \ @@ -157,7 +163,7 @@ eog_DEPENDENCIES = \ eog_CFLAGS = \ $(EOG_CFLAGS) \ - -I$(top_srcdir)/cut-n-paste/toolbar-editor \ + -I$(top_srcdir)/cut-n-paste/toolbar-editor \ -DEOG_DATADIR=\""$(pkgdatadir)"\" \ -DEOG_LOCALE_DIR=\""$(datadir)/locale"\" @@ -166,7 +172,7 @@ eog_LDADD = \ $(EOG_LIBS) \ $(X_LIBS) \ $(LIBJPEG) \ - $(toolbar_LIB) \ + $(toolbar_LIB) \ $(jpeg_LIB) eog_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*" diff --git a/src/eog-exif-details.c b/src/eog-exif-details.c index 9e5c083b..aa14f6cf 100644 --- a/src/eog-exif-details.c +++ b/src/eog-exif-details.c @@ -26,12 +26,20 @@ #include "eog-exif-details.h" #include "eog-util.h" +#if HAVE_EXIF #include <libexif/exif-entry.h> #include <libexif/exif-utils.h> +#endif +#if HAVE_EXEMPI +#include <exempi/xmp.h> +#include <exempi/xmpconsts.h> +#endif #include <glib/gi18n.h> #include <gtk/gtk.h> +#include <string.h> + #define EOG_EXIF_DETAILS_GET_PRIVATE(object) \ (G_TYPE_INSTANCE_GET_PRIVATE ((object), EOG_TYPE_EXIF_DETAILS, EogExifDetailsPrivate)) @@ -42,7 +50,13 @@ typedef enum { EXIF_CATEGORY_IMAGE_DATA, EXIF_CATEGORY_IMAGE_TAKING_CONDITIONS, EXIF_CATEGORY_MAKER_NOTE, - EXIF_CATEGORY_OTHER + EXIF_CATEGORY_OTHER, +#ifdef HAVE_EXEMPI + XMP_CATEGORY_EXIF, + XMP_CATEGORY_IPTC, + XMP_CATEGORY_RIGHTS, + XMP_CATEGORY_OTHER +#endif } ExifCategory; typedef struct { @@ -56,6 +70,12 @@ static ExifCategoryInfo exif_categories[] = { { N_("Image Taking Conditions"), "2" }, { N_("Maker Note"), "3" }, { N_("Other"), "4" }, +#ifdef HAVE_EXEMPI + { N_("XMP Exif"), "5" }, + { N_("XMP IPTC"), "6" }, + { N_("XMP Rights Management"), "7" }, + { N_("XMP Other"), "8" }, +#endif { NULL, NULL } }; @@ -441,3 +461,103 @@ eog_exif_details_update (EogExifDetails *exif_details, ExifData *data) exif_data_foreach_content (data, exif_content_cb, exif_details); } } + + +#ifdef HAVE_EXEMPI +typedef struct { + const char *id; + ExifCategory category; +} XmpNsCategory; + +static XmpNsCategory xmp_ns_category_map[] = { + { NS_EXIF, XMP_CATEGORY_EXIF}, + { NS_TIFF, XMP_CATEGORY_EXIF}, + { NS_XAP, XMP_CATEGORY_EXIF}, + { NS_XAP_RIGHTS, XMP_CATEGORY_RIGHTS}, + { NS_EXIF_AUX, XMP_CATEGORY_EXIF}, + { NS_DC, XMP_CATEGORY_IPTC}, + { NS_IPTC4XMP, XMP_CATEGORY_IPTC}, + { NS_CC, XMP_CATEGORY_RIGHTS}, + { NULL, -1} +}; + +static ExifCategory +get_xmp_category (XmpStringPtr schema) +{ + ExifCategory cat = XMP_CATEGORY_OTHER; + const char *s = xmp_string_cstr(schema); + int i; + + for (i = 0; xmp_ns_category_map[i].id != NULL; i++) { + if (strcmp (xmp_ns_category_map[i].id, s) == 0) { + cat = xmp_ns_category_map[i].category; + break; + } + } + + return cat; +} + +static void +xmp_entry_insert (EogExifDetails *view, XmpStringPtr xmp_schema, + XmpStringPtr xmp_path, XmpStringPtr xmp_prop) +{ + GtkTreeStore *store; + EogExifDetailsPrivate *priv; + ExifCategory cat; + char *path; + gchar *key; + + priv = view->priv; + + key = g_strdup_printf ("%s:%s", xmp_string_cstr (xmp_schema), + xmp_string_cstr(xmp_path)); + + store = GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (view))); + + path = g_hash_table_lookup (priv->id_path_hash, key); + + if (path != NULL) { + set_row_data (store, path, NULL, + xmp_string_cstr (xmp_path), + xmp_string_cstr (xmp_prop)); + + g_free(key); + } + else { + cat = get_xmp_category (xmp_schema); + + path = set_row_data (store, NULL, exif_categories[cat].path, + xmp_string_cstr(xmp_path), + xmp_string_cstr(xmp_prop)); + + g_hash_table_insert (priv->id_path_hash, key, path); + } +} + +void +eog_exif_details_xmp_update (EogExifDetails *view, XmpPtr data) +{ + EogExifDetailsPrivate *priv; + + g_return_if_fail (EOG_IS_EXIF_DETAILS (view)); + + priv = view->priv; + + if (data) { + XmpIteratorPtr iter = xmp_iterator_new(data, NULL, NULL, XMP_ITER_JUSTLEAFNODES); + XmpStringPtr the_schema = xmp_string_new (); + XmpStringPtr the_path = xmp_string_new (); + XmpStringPtr the_prop = xmp_string_new (); + + while (xmp_iterator_next (iter, the_schema, the_path, the_prop, NULL)) { + xmp_entry_insert (view, the_schema, the_path, the_prop); + } + + xmp_string_free (the_prop); + xmp_string_free (the_path); + xmp_string_free (the_schema); + xmp_iterator_free (iter); + } +} +#endif diff --git a/src/eog-exif-details.h b/src/eog-exif-details.h index f2a85474..832e0ccf 100644 --- a/src/eog-exif-details.h +++ b/src/eog-exif-details.h @@ -24,7 +24,12 @@ #include <glib-object.h> #include <gtk/gtk.h> +#if HAVE_EXIF #include <libexif/exif-data.h> +#endif +#if HAVE_EXEMPI +#include <exempi/xmp.h> +#endif G_BEGIN_DECLS @@ -53,8 +58,14 @@ GType eog_exif_details_get_type (void) G_GNUC_CONST; GtkWidget *eog_exif_details_new (void); +#if HAVE_EXIF void eog_exif_details_update (EogExifDetails *view, ExifData *data); +#endif +#if HAVE_EXEMPI +void eog_exif_details_xmp_update (EogExifDetails *view, + XmpPtr xmp_data); +#endif G_END_DECLS diff --git a/src/eog-image-private.h b/src/eog-image-private.h index ee7db871..e55698e1 100644 --- a/src/eog-image-private.h +++ b/src/eog-image-private.h @@ -53,6 +53,9 @@ struct _EogImagePrivate { gint orientation; ExifData *exif; #endif +#ifdef HAVE_EXEMPI + XmpPtr xmp; +#endif #ifdef HAVE_LCMS cmsHPROFILE profile; diff --git a/src/eog-image.c b/src/eog-image.c index 416974a1..edac99b9 100644 --- a/src/eog-image.c +++ b/src/eog-image.c @@ -110,6 +110,13 @@ eog_image_free_mem_private (EogImage *image) priv->exif_chunk_len = 0; +#ifdef HAVE_EXEMPI + if (priv->xmp != NULL) { + xmp_free (priv->xmp); + priv->xmp = NULL; + } +#endif + #ifdef HAVE_LCMS if (priv->profile != NULL) { cmsCloseProfile (priv->profile); @@ -239,7 +246,9 @@ eog_image_init (EogImage *img) img->priv->autorotate = FALSE; img->priv->exif = NULL; #endif - +#ifdef HAVE_EXEMPI + img->priv->xmp = NULL; +#endif #ifdef HAVE_LCMS img->priv->profile = NULL; #endif @@ -510,6 +519,8 @@ eog_image_determine_file_bytes (EogImage *img, GError **error) return bytes; } + + #ifdef HAVE_LCMS void eog_image_apply_display_profile (EogImage *img, cmsHPROFILE screen) @@ -740,7 +751,7 @@ eog_image_real_autorotate (EogImage *img) } else { eog_transform_compose (priv->trans, trans); } - + g_object_unref (trans); } @@ -759,6 +770,20 @@ eog_image_autorotate (EogImage *img) #endif static void +eog_image_set_xmp_data (EogImage *img, EogMetadataReader *md_reader) +{ +#ifdef HAVE_EXEMPI + EogImagePrivate *priv; + + g_return_if_fail (EOG_IS_IMAGE (img)); + + priv = img->priv; + + priv->xmp = eog_metadata_reader_get_xmp_data (md_reader); +#endif +} + +static void eog_image_set_exif_data (EogImage *img, EogMetadataReader *md_reader) { EogImagePrivate *priv; @@ -957,9 +982,14 @@ eog_image_real_load (EogImage *img, if (eog_metadata_reader_finished (md_reader)) { if (set_metadata) { eog_image_set_exif_data (img, md_reader); + #ifdef HAVE_LCMS eog_image_set_icc_data (img, md_reader); #endif + +#ifdef HAVE_EXEMPI + eog_image_set_xmp_data (img, md_reader); +#endif set_metadata = FALSE; } @@ -1071,6 +1101,13 @@ eog_image_has_data (EogImage *img, guint req_data) #endif } + if ((req_data & EOG_IMAGE_DATA_XMP) > 0) { + req_data = (req_data & !EOG_IMAGE_DATA_XMP); +#ifdef HAVE_EXEMPI + has_data = has_data && (priv->xmp != NULL); +#endif + } + if (req_data != 0) { g_warning ("Asking for unknown data, remaining: %i\n", req_data); has_data = FALSE; @@ -1792,6 +1829,27 @@ eog_image_get_exif_info (EogImage *img) return data; } + +gpointer +eog_image_get_xmp_info (EogImage *img) +{ + EogImagePrivate *priv; + gpointer data = NULL; + + g_return_val_if_fail (EOG_IS_IMAGE (img), NULL); + + priv = img->priv; + +#ifdef HAVE_EXEMPI + g_mutex_lock (priv->status_mutex); + data = (gpointer) xmp_copy (priv->xmp); + g_mutex_unlock (priv->status_mutex); +#endif + + return data; +} + + GnomeVFSURI * eog_image_get_uri (EogImage *img) { diff --git a/src/eog-image.h b/src/eog-image.h index 71372f5b..159b5b1b 100644 --- a/src/eog-image.h +++ b/src/eog-image.h @@ -40,6 +40,10 @@ #include <lcms.h> #endif +#ifdef HAVE_EXEMPI +#include <exempi/xmp.h> +#endif + G_BEGIN_DECLS #ifndef __EOG_IMAGE_DECLR__ @@ -59,12 +63,14 @@ typedef struct _EogImagePrivate EogImagePrivate; typedef enum { EOG_IMAGE_DATA_IMAGE = 1 << 0, EOG_IMAGE_DATA_DIMENSION = 1 << 1, - EOG_IMAGE_DATA_EXIF = 1 << 2 + EOG_IMAGE_DATA_EXIF = 1 << 2, + EOG_IMAGE_DATA_XMP = 1 << 3 } EogImageData; #define EOG_IMAGE_DATA_ALL (EOG_IMAGE_DATA_IMAGE | \ EOG_IMAGE_DATA_DIMENSION | \ - EOG_IMAGE_DATA_EXIF) + EOG_IMAGE_DATA_EXIF | \ + EOG_IMAGE_DATA_XMP) typedef enum { EOG_IMAGE_ERROR_SAVE_NOT_LOCAL, @@ -160,6 +166,8 @@ const gchar *eog_image_get_collate_key (EogImage *img); gpointer eog_image_get_exif_info (EogImage *img); +gpointer eog_image_get_xmp_info (EogImage *img); + GnomeVFSURI* eog_image_get_uri (EogImage *img); gchar* eog_image_get_uri_for_display (EogImage *img); diff --git a/src/eog-metadata-reader.c b/src/eog-metadata-reader.c index 29cdd6b1..e407fdb9 100644 --- a/src/eog-metadata-reader.c +++ b/src/eog-metadata-reader.c @@ -13,12 +13,21 @@ typedef enum { EMR_READ_SIZE_LOW_BYTE, EMR_READ_MARKER, EMR_SKIP_BYTES, + EMR_READ_APP1, EMR_READ_EXIF, + EMR_READ_XMP, EMR_READ_ICC, EMR_READ_IPTC, EMR_FINISHED } EogMetadataReaderState; +typedef enum { + EJA_EXIF = 0, + EJA_XMP, + EJA_OTHER +} EogJpegApp1Type; + + #define EOG_JPEG_MARKER_START 0xFF #define EOG_JPEG_MARKER_SOI 0xD8 #define EOG_JPEG_MARKER_APP1 0xE1 @@ -27,6 +36,11 @@ typedef enum { #define NO_DEBUG +#define IS_FINISHED(priv) (priv->exif_chunk != NULL && \ + priv->icc_chunk != NULL && \ + priv->iptc_chunk != NULL && \ + priv->xmp_chunk != NULL) + struct _EogMetadataReaderPrivate { EogMetadataReaderState state; @@ -39,6 +53,9 @@ struct _EogMetadataReaderPrivate { gpointer icc_chunk; guint icc_len; + + gpointer xmp_chunk; + guint xmp_len; /* management fields */ int size; @@ -74,6 +91,11 @@ eog_metadata_reader_dispose (GObject *object) emr->priv->iptc_chunk = NULL; } + if (emr->priv->xmp_chunk != NULL) { + g_free (emr->priv->xmp_chunk); + emr->priv->xmp_chunk = NULL; + } + if (emr->priv->icc_chunk != NULL) { g_free (emr->priv->icc_chunk); emr->priv->icc_chunk = NULL; @@ -126,10 +148,33 @@ eog_metadata_reader_finished (EogMetadataReader *emr) return (emr->priv->state == EMR_FINISHED); } + +static EogJpegApp1Type +eog_metadata_identify_app1 (gchar *buf, guint len) +{ + if (len < 5) { + return EJA_OTHER; + } + + if (len < 29) { + return (strncmp ("Exif", buf, 5) == 0 ? EJA_EXIF : EJA_OTHER); + } + + if (strncmp ("Exif", buf, 5) == 0) { + return EJA_EXIF; + } else if (strncmp ("http://ns.adobe.com/xap/1.0/", buf, 29) == 0) { + return EJA_XMP; + } + + return EJA_OTHER; +} + + void eog_metadata_reader_consume (EogMetadataReader *emr, guchar *buf, guint len) { EogMetadataReaderPrivate *priv; + EogJpegApp1Type app1_type; int i; g_return_if_fail (EOG_IS_METADATA_READER (emr)); @@ -178,23 +223,19 @@ eog_metadata_reader_consume (EogMetadataReader *emr, guchar *buf, guint len) if (priv->size == 0) { priv->state = EMR_READ; - } - else if (priv->last_marker == EOG_JPEG_MARKER_APP1 && - priv->exif_chunk == NULL) + } else if (priv->last_marker == EOG_JPEG_MARKER_APP1 && + ((priv->exif_chunk == NULL) || (priv->xmp_chunk == NULL))) { - priv->state = EMR_READ_EXIF; - } - else if (priv->last_marker == EOG_JPEG_MARKER_APP2 && + priv->state = EMR_READ_APP1; + } else if (priv->last_marker == EOG_JPEG_MARKER_APP2 && priv->icc_chunk == NULL) { priv->state = EMR_READ_ICC; - } - else if (priv->last_marker == EOG_JPEG_MARKER_APP14 && + } else if (priv->last_marker == EOG_JPEG_MARKER_APP14 && priv->iptc_chunk == NULL) { priv->state = EMR_READ_IPTC; - } - else { + } else { priv->state = EMR_SKIP_BYTES; } @@ -217,22 +258,66 @@ eog_metadata_reader_consume (EogMetadataReader *emr, guchar *buf, guint len) } break; - case EMR_READ_EXIF: - eog_debug_message (DEBUG_IMAGE_DATA, "Read EXIF data, Length: %i", priv->size); + case EMR_READ_APP1: + eog_debug_message (DEBUG_IMAGE_DATA, "Read APP1 data, Length: %i", priv->size); - if (priv->exif_chunk == NULL) { - priv->exif_chunk = g_new0 (guchar, priv->size); - priv->exif_len = priv->size; - priv->bytes_read = 0; + app1_type = eog_metadata_identify_app1 ((gchar*) &buf[i], priv->size); + + if (app1_type != EJA_OTHER) { + EogMetadataReaderState next_state; + guchar *chunk = NULL; + int offset = 0; + + switch (app1_type) { + case EJA_EXIF: + if (priv->exif_chunk == NULL) { + priv->exif_chunk = g_new0 (guchar, priv->size); + priv->exif_len = priv->size; + priv->bytes_read = 0; + chunk = priv->exif_chunk; + next_state = EMR_READ_EXIF; + } + break; + case EJA_XMP: + if (priv->xmp_chunk == NULL) { + offset = 29 + 54; /* skip the ID + packet */ + + if (priv->size > offset) { /* ensure that we have enough bytes */ + priv->xmp_chunk = g_new0 (guchar, priv->size); + priv->xmp_len = priv->size - offset; + priv->bytes_read = 0; + chunk = priv->xmp_chunk; + next_state = EMR_READ_XMP; + } + } + default: + break; + } + + if (chunk) { + if (i + priv->size < len) { + /* read data in one block */ + memcpy ((guchar*) (chunk) + priv->bytes_read, &buf[i + offset], priv->size); + priv->state = EMR_READ; + i = i + priv->size - 1; /* the for-loop consumes the other byte */ + } else { + int chunk_len = len - i; + memcpy ((guchar*) (priv->exif_chunk) + priv->bytes_read, &buf[i], chunk_len); + priv->bytes_read += chunk_len; /* bytes already read */ + priv->size = (i + priv->size) - len; /* remaining data to read */ + i = len - 1; + priv->state = next_state; + } + } } - if (i + priv->size < len) { - /* read data in one block */ - memcpy ((guchar*) (priv->exif_chunk) + priv->bytes_read, &buf[i], priv->size); - priv->state = EMR_READ; - i = i + priv->size - 1; /* the for-loop consumes the other byte */ - } - else { + if (IS_FINISHED(priv)) + priv->state = EMR_FINISHED; + break; + + case EMR_READ_EXIF: + eog_debug_message (DEBUG_IMAGE_DATA, "Read continuation of EXIF data, length: %i", priv->size); + { int chunk_len = len - i; memcpy ((guchar*) (priv->exif_chunk) + priv->bytes_read, &buf[i], chunk_len); priv->bytes_read += chunk_len; /* bytes already read */ @@ -240,11 +325,24 @@ eog_metadata_reader_consume (EogMetadataReader *emr, guchar *buf, guint len) i = len - 1; priv->state = EMR_READ_EXIF; } + if (IS_FINISHED(priv)) + priv->state = EMR_FINISHED; + break; - if (priv->exif_chunk != NULL && priv->icc_chunk != NULL && priv->iptc_chunk != NULL) + case EMR_READ_XMP: + eog_debug_message (DEBUG_IMAGE_DATA, "Read continuation of XMP data, length: %i", priv->size); + { + int chunk_len = len - i; + memcpy ((guchar*) (priv->xmp_chunk) + priv->bytes_read, &buf[i], chunk_len); + priv->bytes_read += chunk_len; /* bytes already read */ + priv->size = (i + priv->size) - len; /* remaining data to read */ + i = len - 1; + priv->state = EMR_READ_XMP; + } + if (IS_FINISHED (priv)) priv->state = EMR_FINISHED; break; - + case EMR_READ_ICC: eog_debug_message (DEBUG_IMAGE_DATA, "Read ICC data, Length: %i\n", priv->size); @@ -259,8 +357,7 @@ eog_metadata_reader_consume (EogMetadataReader *emr, guchar *buf, guint len) memcpy ((guchar*) (priv->icc_chunk) + priv->bytes_read, &buf[i], priv->size); priv->state = EMR_READ; i = i + priv->size - 1; /* the for-loop consumes the other byte */ - } - else { + } else { int chunk_len = len - i; memcpy ((guchar*) (priv->icc_chunk) + priv->bytes_read, &buf[i], chunk_len); priv->bytes_read += chunk_len; /* bytes already read */ @@ -269,7 +366,7 @@ eog_metadata_reader_consume (EogMetadataReader *emr, guchar *buf, guint len) priv->state = EMR_READ_ICC; } - if (priv->exif_chunk != NULL && priv->icc_chunk != NULL && priv->iptc_chunk != NULL) + if (IS_FINISHED(priv)) priv->state = EMR_FINISHED; break; @@ -284,8 +381,7 @@ eog_metadata_reader_consume (EogMetadataReader *emr, guchar *buf, guint len) /* read data in one block */ memcpy ((guchar*) (priv->iptc_chunk) + priv->bytes_read, &buf[i], priv->size); priv->state = EMR_READ; - } - else { + } else { int chunk_len = len - i; memcpy ((guchar*) (priv->iptc_chunk) + priv->bytes_read, &buf[i], chunk_len); priv->bytes_read += chunk_len; /* bytes already read */ @@ -294,7 +390,7 @@ eog_metadata_reader_consume (EogMetadataReader *emr, guchar *buf, guint len) priv->state = EMR_READ_IPTC; } - if (priv->exif_chunk != NULL && priv->icc_chunk != NULL && priv->iptc_chunk != NULL) + if (IS_FINISHED(priv)) priv->state = EMR_FINISHED; break; @@ -322,7 +418,7 @@ eog_metadata_reader_get_exif_chunk (EogMetadataReader *emr, guchar **data, guint priv->exif_len = 0; } -#if HAVE_EXIF +#ifdef HAVE_EXIF ExifData* eog_metadata_reader_get_exif_data (EogMetadataReader *emr) { @@ -340,8 +436,28 @@ eog_metadata_reader_get_exif_data (EogMetadataReader *emr) } #endif + +#ifdef HAVE_EXEMPI +XmpPtr +eog_metadata_reader_get_xmp_data (EogMetadataReader *emr ) +{ + EogMetadataReaderPrivate *priv; + XmpPtr xmp = NULL; + + g_return_val_if_fail (EOG_IS_METADATA_READER (emr), NULL); + + priv = emr->priv; + + if (priv->xmp_chunk != NULL) { + xmp = xmp_new (priv->xmp_chunk, priv->xmp_len); + } + + return xmp; +} +#endif + /* - * TODO: very broken, assumes the profile fits in a single chunk. Change to + * FIXME: very broken, assumes the profile fits in a single chunk. Change to * parse the sections and construct a single memory chunk, or maybe even parse * the profile. */ @@ -351,6 +467,7 @@ eog_metadata_reader_get_icc_chunk (EogMetadataReader *emr, guchar **data, guint EogMetadataReaderPrivate *priv; g_return_if_fail (EOG_IS_METADATA_READER (emr)); + priv = emr->priv; if (priv->icc_chunk) { diff --git a/src/eog-metadata-reader.h b/src/eog-metadata-reader.h index 966e318d..7ff64f6f 100644 --- a/src/eog-metadata-reader.h +++ b/src/eog-metadata-reader.h @@ -5,6 +5,9 @@ #if HAVE_EXIF #include <libexif/exif-data.h> #endif +#if HAVE_EXEMPI +#include <exempi/xmp.h> +#endif G_BEGIN_DECLS @@ -44,6 +47,10 @@ void eog_metadata_reader_get_exif_chunk (EogMetadataReader *emr, ExifData* eog_metadata_reader_get_exif_data (EogMetadataReader *emr); #endif +#if HAVE_EXEMPI +XmpPtr eog_metadata_reader_get_xmp_data (EogMetadataReader *emr); +#endif + #if 0 gpointer eog_metadata_reader_get_iptc_chunk (EogMetadataReader *emr); IptcData* eog_metadata_reader_get_iptc_data (EogMetadataReader *emr); diff --git a/src/eog-properties-dialog.c b/src/eog-properties-dialog.c index 6c030875..c50d9287 100644 --- a/src/eog-properties-dialog.c +++ b/src/eog-properties-dialog.c @@ -3,6 +3,7 @@ * Copyright (C) 2006 The Free Software Foundation * * Author: Lucas Rocha <lucasr@gnome.org> + * Hubert Figuiere <hub@figuiere.net> (XMP support) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,6 +39,15 @@ #include <libgnomevfs/gnome-vfs-mime-utils.h> #include <libgnomevfs/gnome-vfs-mime-handlers.h> +#if HAVE_EXEMPI +#include <exempi/xmp.h> +#include <exempi/xmpconsts.h> +#endif + +#if HAVE_EXIF || HAVE_EXEMPI +#define HAVE_METADATA 1 +#endif + #define EOG_PROPERTIES_DIALOG_GET_PRIVATE(object) \ (G_TYPE_INSTANCE_GET_PRIVATE ((object), EOG_TYPE_PROPERTIES_DIALOG, EogPropertiesDialogPrivate)) @@ -79,6 +89,16 @@ struct _EogPropertiesDialogPrivate { GtkWidget *exif_metering_label; GtkWidget *exif_model_label; GtkWidget *exif_date_label; +#endif +#ifdef HAVE_EXEMPI + GtkWidget *xmp_location_label; + GtkWidget *xmp_description_label; + GtkWidget *xmp_keywords_label; + GtkWidget *xmp_creator_label; + GtkWidget *xmp_rights_label; + GtkWidget *xmp_details; +#endif +#if HAVE_METADATA GtkWidget *exif_details_expander; GtkWidget *exif_details; #endif @@ -88,8 +108,8 @@ static void pd_update_general_tab (EogPropertiesDialog *prop_dlg, EogImage *image) { - const gchar *type_str; gchar *bytes_str, *dir_str, *mime_str, *uri_str; + const gchar *type_str; gint width, height, bytes; uri_str = eog_image_get_uri_for_display (image); @@ -129,67 +149,166 @@ pd_update_general_tab (EogPropertiesDialog *prop_dlg, g_free (dir_str); } -#ifdef HAVE_EXIF +#if HAVE_EXEMPI +static void +eog_xmp_set_label (XmpPtr xmp, + const char *ns, + const char *propname, + GtkWidget *w) +{ + uint32_t options; + + XmpStringPtr value = xmp_string_new (); + + if (xmp_get_property_and_bits (xmp, ns, propname, value, &options)) { + if (XMP_IS_PROP_SIMPLE (options)) { + gtk_label_set_text (GTK_LABEL (w), xmp_string_cstr (value)); + } else if (XMP_IS_PROP_ARRAY (options)) { + XmpIteratorPtr iter = xmp_iterator_new (xmp, + ns, + propname, + XMP_ITER_JUSTLEAFNODES); + + GString *string = g_string_new (""); + + if (iter) { + gboolean first = TRUE; + + while (xmp_iterator_next (iter, NULL, NULL, value, &options) + && !XMP_IS_PROP_QUALIFIER (options)) { + + if (!first) { + g_string_append_printf(string, ", "); + } else { + first = FALSE; + } + + g_string_append_printf (string, + "%s", + xmp_string_cstr (value)); + } + + xmp_iterator_free (iter); + } + + gtk_label_set_text (GTK_LABEL (w), string->str); + } + } + + xmp_string_free (value); +} +#endif + +#if HAVE_METADATA static void -pd_update_exif_tab (EogPropertiesDialog *prop_dlg, - EogImage *image) +pd_update_metadata_tab (EogPropertiesDialog *prop_dlg, + EogImage *image) { + EogPropertiesDialogPrivate *priv; GtkNotebook *notebook; - ExifData *exif_data; +#if HAVE_EXIF + ExifData *exif_data; const gchar *exif_value = NULL; +#endif +#if HAVE_EXEMPI + XmpPtr xmp_data; +#endif + + g_return_if_fail (EOG_IS_PROPERTIES_DIALOG (prop_dlg)); - notebook = GTK_NOTEBOOK (prop_dlg->priv->notebook); + priv = prop_dlg->priv; + + notebook = GTK_NOTEBOOK (priv->notebook); if (!eog_image_has_data (image, EOG_IMAGE_DATA_EXIF)) { if (gtk_notebook_get_current_page (notebook) == EOG_PROPERTIES_DIALOG_PAGE_EXIF) { gtk_notebook_prev_page (notebook); } - if (GTK_WIDGET_VISIBLE (prop_dlg->priv->exif_box)) { - gtk_widget_hide_all (prop_dlg->priv->exif_box); + if (GTK_WIDGET_VISIBLE (priv->exif_box)) { + gtk_widget_hide_all (priv->exif_box); } return; - } else if (!GTK_WIDGET_VISIBLE (prop_dlg->priv->exif_box)) { - gtk_widget_show_all (prop_dlg->priv->exif_box); + } else if (!GTK_WIDGET_VISIBLE (priv->exif_box)) { + gtk_widget_show_all (priv->exif_box); } +#if HAVE_EXIF exif_data = (ExifData *) eog_image_get_exif_info (image); - exif_value = eog_exif_util_get_value (exif_data, EXIF_TAG_APERTURE_VALUE); - gtk_label_set_text (GTK_LABEL (prop_dlg->priv->exif_aperture_label), + exif_value = eog_exif_util_get_value (exif_data, EXIF_TAG_FNUMBER); + gtk_label_set_text (GTK_LABEL (priv->exif_aperture_label), eog_util_make_valid_utf8 (exif_value)); exif_value = eog_exif_util_get_value (exif_data, EXIF_TAG_EXPOSURE_TIME); - gtk_label_set_text (GTK_LABEL (prop_dlg->priv->exif_exposure_label), + gtk_label_set_text (GTK_LABEL (priv->exif_exposure_label), eog_util_make_valid_utf8 (exif_value)); exif_value = eog_exif_util_get_value (exif_data, EXIF_TAG_FOCAL_LENGTH); - gtk_label_set_text (GTK_LABEL (prop_dlg->priv->exif_focal_label), + gtk_label_set_text (GTK_LABEL (priv->exif_focal_label), eog_util_make_valid_utf8 (exif_value)); exif_value = eog_exif_util_get_value (exif_data, EXIF_TAG_FLASH); - gtk_label_set_text (GTK_LABEL (prop_dlg->priv->exif_flash_label), + gtk_label_set_text (GTK_LABEL (priv->exif_flash_label), eog_util_make_valid_utf8 (exif_value)); exif_value = eog_exif_util_get_value (exif_data, EXIF_TAG_ISO_SPEED_RATINGS); - gtk_label_set_text (GTK_LABEL (prop_dlg->priv->exif_iso_label), + gtk_label_set_text (GTK_LABEL (priv->exif_iso_label), eog_util_make_valid_utf8 (exif_value)); exif_value = eog_exif_util_get_value (exif_data, EXIF_TAG_METERING_MODE); - gtk_label_set_text (GTK_LABEL (prop_dlg->priv->exif_metering_label), + gtk_label_set_text (GTK_LABEL (priv->exif_metering_label), eog_util_make_valid_utf8 (exif_value)); exif_value = eog_exif_util_get_value (exif_data, EXIF_TAG_MODEL); - gtk_label_set_text (GTK_LABEL (prop_dlg->priv->exif_model_label), + gtk_label_set_text (GTK_LABEL (priv->exif_model_label), eog_util_make_valid_utf8 (exif_value)); exif_value = eog_exif_util_get_value (exif_data, EXIF_TAG_DATE_TIME); - gtk_label_set_text (GTK_LABEL (prop_dlg->priv->exif_date_label), + gtk_label_set_text (GTK_LABEL (priv->exif_date_label), eog_exif_util_format_date (exif_value)); eog_exif_details_update (EOG_EXIF_DETAILS (prop_dlg->priv->exif_details), exif_data); + + exif_data_unref(exif_data); +#endif + +#if HAVE_EXEMPI + xmp_data = (XmpPtr) eog_image_get_xmp_info (image); + + if (xmp_data != NULL) { + eog_xmp_set_label (xmp_data, + NS_IPTC4XMP, + "Location", + prop_dlg->priv->xmp_location_label); + + eog_xmp_set_label (xmp_data, + NS_DC, + "description", + prop_dlg->priv->xmp_description_label); + + eog_xmp_set_label (xmp_data, + NS_DC, + "subject", + prop_dlg->priv->xmp_keywords_label); + + eog_xmp_set_label (xmp_data, + NS_DC, + "creator", + prop_dlg->priv->xmp_creator_label); + + eog_xmp_set_label (xmp_data, + NS_DC, + "rights", + prop_dlg->priv->xmp_rights_label); + + eog_exif_details_xmp_update (EOG_EXIF_DETAILS (prop_dlg->priv->exif_details), xmp_data); + + xmp_free (xmp_data); + } +#endif } static gboolean @@ -333,7 +452,10 @@ eog_properties_dialog_init (EogPropertiesDialog *prop_dlg) { EogPropertiesDialogPrivate *priv; GtkWidget *dlg; -#ifdef HAVE_EXIF +#ifndef HAVE_EXEMPI + GtkWidget *xmp_box, *xmp_box_label; +#endif +#if HAVE_METADATA GtkWidget *sw; #endif @@ -375,6 +497,17 @@ eog_properties_dialog_init (EogPropertiesDialog *prop_dlg) "exif_date_label", &priv->exif_date_label, "exif_details_expander", &priv->exif_details_expander, #endif +#ifdef HAVE_EXEMPI + "xmp_location_label", &priv->xmp_location_label, + "xmp_description_label", &priv->xmp_description_label, + "xmp_keywords_label", &priv->xmp_keywords_label, + "xmp_creator_label", &priv->xmp_creator_label, + "xmp_rights_label", &priv->xmp_rights_label, +#else + "xmp_box", &xmp_box, + "xmp_box_label", &xmp_box_label, +#endif + NULL); g_signal_connect (dlg, @@ -394,8 +527,8 @@ eog_properties_dialog_init (EogPropertiesDialog *prop_dlg) gtk_widget_set_size_request (priv->thumbnail_image, 100, 100); -#ifdef HAVE_EXIF - sw = gtk_scrolled_window_new (NULL, NULL); +#ifdef HAVE_METADATA + sw = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN); @@ -416,8 +549,14 @@ eog_properties_dialog_init (EogPropertiesDialog *prop_dlg) "notify::expanded", G_CALLBACK (pd_exif_details_activated_cb), dlg); + +#ifndef HAVE_EXEMPI + gtk_widget_hide_all (xmp_box); + gtk_widget_hide_all (xmp_box_label); +#endif + #else - gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), + gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), EOG_PROPERTIES_DIALOG_PAGE_EXIF); #endif } @@ -459,10 +598,9 @@ eog_properties_dialog_update (EogPropertiesDialog *prop_dlg, pd_update_general_tab (prop_dlg, image); -#ifdef HAVE_EXIF - pd_update_exif_tab (prop_dlg, image); +#ifdef HAVE_METADATA + pd_update_metadata_tab (prop_dlg, image); #endif - gtk_notebook_set_current_page (GTK_NOTEBOOK (prop_dlg->priv->notebook), prop_dlg->priv->current_page); diff --git a/src/eog-properties-dialog.h b/src/eog-properties-dialog.h index e1817235..9223c1e9 100644 --- a/src/eog-properties-dialog.h +++ b/src/eog-properties-dialog.h @@ -45,7 +45,8 @@ typedef struct _EogPropertiesDialogPrivate EogPropertiesDialogPrivate; typedef enum { EOG_PROPERTIES_DIALOG_PAGE_GENERAL = 0, - EOG_PROPERTIES_DIALOG_PAGE_EXIF + EOG_PROPERTIES_DIALOG_PAGE_EXIF, + EOG_PROPERTIES_DIALOG_PAGE_XMP } EogPropertiesDialogPage; struct _EogPropertiesDialog { @@ -48,6 +48,10 @@ #include <libgnomeui/gnome-app-helper.h> #include <libgnomeui/gnome-authentication-manager.h> +#if HAVE_EXEMPI +#include <exempi/xmp.h> +#endif + static EogStartupFlags flags; static gboolean fullscreen = FALSE; @@ -194,6 +198,9 @@ main (int argc, char **argv) gnome_authentication_manager_init (); +#ifdef HAVE_EXEMPI + xmp_init(); +#endif eog_debug_init (); eog_job_queue_init (); gdk_threads_init (); @@ -216,5 +223,8 @@ main (int argc, char **argv) g_object_unref (program); +#ifdef HAVE_EXEMPI + xmp_terminate(); +#endif return 0; } |