From b1c0911213e74d91059aaa8442898e52e13368af Mon Sep 17 00:00:00 2001 From: Felix Riemann Date: Mon, 19 Dec 2011 18:20:30 +0100 Subject: Make Exif/XMP summaries available as sidebar Makes the data from the properties dialog available as a sidebar. A button opens the details tab in the properties dialog. This is graphically still a bit roughg. Committing it in hopes to get some early feedback. https://bugzilla.gnome.org/show_bug.cgi?id=616438 origin commit: https://git.gnome.org/browse/eog/commit/?id=7ac112f --- src/Makefile.am | 2 + src/eom-exif-util.c | 91 +++++++ src/eom-exif-util.h | 17 +- src/eom-metadata-sidebar.c | 634 ++++++++++++++++++++++++++++++++++++++++++++ src/eom-metadata-sidebar.h | 61 +++++ src/eom-properties-dialog.c | 118 ++------- src/eom-window.c | 47 +++- src/eom-window.h | 2 + 8 files changed, 851 insertions(+), 121 deletions(-) create mode 100644 src/eom-metadata-sidebar.c create mode 100644 src/eom-metadata-sidebar.h diff --git a/src/Makefile.am b/src/Makefile.am index 8b3539c..d9ef069 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,6 +23,7 @@ NOINST_H_FILES = \ eom-config-keys.h \ eom-image-jpeg.h \ eom-image-private.h \ + eom-metadata-sidebar.h \ eom-uri-converter.h \ eom-metadata-reader.h \ eom-metadata-reader-jpg.h \ @@ -80,6 +81,7 @@ libeom_c_files = \ eom-scroll-view.c \ eom-thumb-view.c \ eom-list-store.c \ + eom-metadata-sidebar.c \ eom-thumbnail.c \ eom-job-queue.c \ eom-jobs.c \ diff --git a/src/eom-exif-util.c b/src/eom-exif-util.c index 8ff9636..8bc4afd 100644 --- a/src/eom-exif-util.c +++ b/src/eom-exif-util.c @@ -35,6 +35,7 @@ #include #include "eom-exif-util.h" +#include "eom-util.h" #include #include @@ -192,6 +193,96 @@ eom_exif_util_format_date (const gchar *date) return new_date; } +void +eom_exif_util_set_label_text (GtkLabel *label, + EomExifData *exif_data, + gint tag_id) +{ + gchar exif_buffer[512]; + const gchar *buf_ptr; + gchar *label_text = NULL; + + g_return_if_fail (GTK_IS_LABEL (label)); + + if (exif_data) { + buf_ptr = eom_exif_data_get_value (exif_data, tag_id, + exif_buffer, 512); + + if (tag_id == EXIF_TAG_DATE_TIME_ORIGINAL && buf_ptr) + label_text = eom_exif_util_format_date (buf_ptr); + else + label_text = eom_util_make_valid_utf8 (buf_ptr); + } + + gtk_label_set_text (label, label_text); + g_free (label_text); +} + +void +eom_exif_util_set_focal_length_label_text (GtkLabel *label, + EomExifData *exif_data) +{ + ExifEntry *entry = NULL, *entry35mm = NULL; + ExifByteOrder byte_order; + gfloat f_val = 0.0; + gchar *fl_text = NULL,*fl35_text = NULL; + + /* If no ExifData is supplied the label will be + * cleared later as fl35_text is NULL. */ + if (exif_data != NULL) { + entry = exif_data_get_entry (exif_data, EXIF_TAG_FOCAL_LENGTH); + entry35mm = exif_data_get_entry (exif_data, + EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM); + byte_order = exif_data_get_byte_order (exif_data); + } + + if (entry && G_LIKELY (entry->format == EXIF_FORMAT_RATIONAL)) { + ExifRational value; + + /* Decode value by hand as libexif is not necessarily returning + * it in the format we want it to be. + */ + value = exif_get_rational (entry->data, byte_order); + /* Guard against div by zero */ + if (G_LIKELY(value.denominator != 0)) + f_val = (gfloat)value.numerator/ + (gfloat)value.denominator; + + /* TRANSLATORS: This is the actual focal length used when + the image was taken.*/ + fl_text = g_strdup_printf (_("%.1f (lens)"), f_val); + + } + if (entry35mm && G_LIKELY (entry35mm->format == EXIF_FORMAT_SHORT)) { + ExifShort s_val; + + s_val = exif_get_short (entry35mm->data, byte_order); + + /* Print as float to get a similar look as above. */ + /* TRANSLATORS: This is the equivalent focal length assuming + a 35mm film camera. */ + fl35_text = g_strdup_printf(_("%.1f (35mm film)"),(float)s_val); + } + + if (fl_text) { + if (fl35_text) { + gchar *merged_txt; + + merged_txt = g_strconcat (fl35_text,", ", fl_text, NULL); + gtk_label_set_text (label, merged_txt); + g_free (merged_txt); + } else { + gtk_label_set_text (label, fl_text); + } + } else { + /* This will also clear the label if no ExifData was supplied */ + gtk_label_set_text (label, fl35_text); + } + + g_free (fl35_text); + g_free (fl_text); +} + /** * eom_exif_data_get_value: * @exif_data: pointer to an ExifData struct diff --git a/src/eom-exif-util.h b/src/eom-exif-util.h index f1bbf62..ebc7122 100644 --- a/src/eom-exif-util.h +++ b/src/eom-exif-util.h @@ -29,20 +29,29 @@ #include #include +#include #include G_BEGIN_DECLS #define EOM_TYPE_EXIF_DATA eom_exif_data_get_type() -gchar* eom_exif_util_format_date (const gchar *date); +gchar *eom_exif_util_format_date (const gchar *date); +void eom_exif_util_set_label_text (GtkLabel *label, + ExifData *exif_data, + gint tag_id); -const gchar *eom_exif_data_get_value (ExifData *exif_data, gint tag_id, gchar *buffer, guint buf_size); +void eom_exif_util_set_focal_length_label_text (GtkLabel *label, + ExifData *exif_data); + +const gchar *eom_exif_data_get_value (ExifData *exif_data, + gint tag_id, gchar *buffer, + guint buf_size); GType eom_exif_data_get_type (void) G_GNUC_CONST; -ExifData * eom_exif_data_copy (ExifData *data); -void eom_exif_data_free (ExifData *data); +ExifData *eom_exif_data_copy (ExifData *data); +void eom_exif_data_free (ExifData *data); G_END_DECLS diff --git a/src/eom-metadata-sidebar.c b/src/eom-metadata-sidebar.c new file mode 100644 index 0000000..1f8da5a --- /dev/null +++ b/src/eom-metadata-sidebar.c @@ -0,0 +1,634 @@ +/* + * eom-metadata-sidebar.c + * This file is part of eom + * + * Author: Felix Riemann + * + * Portions based on code by: Lucas Rocha + * Hubert Figuiere (XMP support) + * + * Copyright (C) 2011 GNOME Foundation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "eom-dialog.h" +#include "eom-image.h" +#include "eom-metadata-sidebar.h" +#include "eom-properties-dialog.h" +#include "eom-scroll-view.h" +#include "eom-util.h" +#include "eom-window.h" + +#if HAVE_EXEMPI +#include +#include +#endif + +enum { + PROP_0, + PROP_IMAGE, + PROP_PARENT_WINDOW +}; + +struct _EomMetadataSidebarPrivate { + EomWindow *parent_window; + EomImage *image; + + gulong image_changed_id; + gulong thumb_changed_id; + + GtkWidget *grid; + + GtkWidget *name_label; + GtkWidget *height_label; + GtkWidget *width_label; + GtkWidget *type_label; + GtkWidget *size_label; + GtkWidget *folder_button; + + GtkWidget *aperture_label; + GtkWidget *exposure_label; + GtkWidget *focallen_label; + GtkWidget *flash_label; + GtkWidget *iso_label; + GtkWidget *metering_label; + GtkWidget *model_label; + GtkWidget *date_label; + + GtkWidget *location_label; + GtkWidget *desc_label; + GtkWidget *keyword_label; + GtkWidget *creator_label; + GtkWidget *rights_label; + + GtkWidget *details_button; +}; + +#define EOM_METADATA_SIDEBAR_GET_PRIVATE(object) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((object), EOM_TYPE_METADATA_SIDEBAR, EomMetadataSidebarPrivate)) + +G_DEFINE_TYPE(EomMetadataSidebar, eom_metadata_sidebar, GTK_TYPE_SCROLLED_WINDOW) + +static GtkWidget* +_gtk_grid_append_title_line (GtkGrid *grid, GtkWidget *sibling, + const gchar *text) +{ + GtkWidget *label; + gchar *markup; + + label = gtk_label_new (NULL); + + markup = g_markup_printf_escaped ("%s", text); + gtk_label_set_markup (GTK_LABEL (label), markup); + + gtk_grid_attach_next_to (grid, label, sibling, GTK_POS_BOTTOM, 2, 1); + return label; +} + +static GtkWidget* +_gtk_grid_append_prop_line (GtkGrid *grid, GtkWidget *sibling, + GtkWidget **data_label, const gchar *text) +{ + GtkWidget *label; + + label = gtk_label_new (text); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + + gtk_grid_attach_next_to (grid, label, sibling, GTK_POS_BOTTOM, 1, 1); + + if (G_LIKELY (data_label != NULL)) { + *data_label = gtk_label_new (NULL); + gtk_label_set_ellipsize (GTK_LABEL (*data_label), PANGO_ELLIPSIZE_END); + gtk_misc_set_alignment (GTK_MISC (*data_label), 0.0, 0.5); + gtk_grid_attach_next_to (grid, *data_label, label, + GTK_POS_RIGHT, 1, 1); + } + + return label; +} + +#if HAVE_EXEMPI +static void +eom_xmp_set_label (XmpPtr xmp, + const char *ns, + const char *propname, + GtkWidget *w) +{ + uint32_t options; + + XmpStringPtr value = xmp_string_new (); + + if (xmp && xmp_get_property (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); + g_string_free (string, TRUE); + } + } else { + /* Property was not found */ + /* Clear label so it won't show bogus data */ + gtk_label_set_text (GTK_LABEL (w), NULL); + } + + xmp_string_free (value); +} +#endif + +static void +eom_metadata_sidebar_update_general_section (EomMetadataSidebar *sidebar) +{ + EomMetadataSidebarPrivate *priv = sidebar->priv; + EomImage *img = priv->image; + GFile *file, *parent_file; + GFileInfo *file_info; + gchar *str; + goffset bytes; + gint width, height; + + if (G_UNLIKELY (img == NULL)) { + gtk_label_set_text (GTK_LABEL (priv->name_label), NULL); + gtk_label_set_text (GTK_LABEL (priv->height_label), NULL); + gtk_label_set_text (GTK_LABEL (priv->width_label), NULL); + gtk_label_set_text (GTK_LABEL (priv->type_label), NULL); + gtk_label_set_text (GTK_LABEL (priv->size_label), NULL); + return; + } + + gtk_label_set_text (GTK_LABEL (priv->name_label), + eom_image_get_caption (img)); + eom_image_get_size (img, &width, &height); + str = g_strdup_printf ("%d %s", height, + ngettext ("pixel", "pixels", height)); + gtk_label_set_text (GTK_LABEL (priv->height_label), str); + g_free (str); + str = g_strdup_printf ("%d %s", width, + ngettext ("pixel", "pixels", width)); + gtk_label_set_text (GTK_LABEL (priv->width_label), str); + g_free (str); + + file = eom_image_get_file (img); + file_info = g_file_query_info (file, + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, + 0, NULL, NULL); + if (file_info == NULL) { + str = g_strdup (_("Unknown")); + } else { + const gchar *mime_str; + + mime_str = g_file_info_get_content_type (file_info); + str = g_content_type_get_description (mime_str); + g_object_unref (file_info); + } + gtk_label_set_text (GTK_LABEL (priv->type_label), str); + g_free (str); + + bytes = eom_image_get_bytes (img); + str = g_format_size (bytes); + gtk_label_set_text (GTK_LABEL (priv->size_label), str); + g_free (str); + + parent_file = g_file_get_parent (file); + if (parent_file == NULL) { + /* file is root directory itself */ + parent_file = g_object_ref (file); + } + str = g_file_get_basename (parent_file); + gtk_button_set_label (GTK_BUTTON (priv->folder_button), str); + g_free (str); + g_object_unref (parent_file); +} + +static void +eom_metadata_sidebar_update_metadata_section (EomMetadataSidebar *sidebar) +{ + EomMetadataSidebarPrivate *priv = sidebar->priv; + EomImage *img = priv->image; + ExifData *exif_data = NULL; + XmpPtr xmp_data = NULL; + + + if (img) { + exif_data = eom_image_get_exif_info (img); + xmp_data = eom_image_get_xmp_info (img); + } + + + eom_exif_util_set_label_text (GTK_LABEL (priv->aperture_label), + exif_data, EXIF_TAG_FNUMBER); + eom_exif_util_set_label_text (GTK_LABEL (priv->exposure_label), + exif_data, + EXIF_TAG_EXPOSURE_TIME); + eom_exif_util_set_focal_length_label_text ( + GTK_LABEL (priv->focallen_label), + exif_data); + eom_exif_util_set_label_text (GTK_LABEL (priv->flash_label), + exif_data, EXIF_TAG_FLASH); + eom_exif_util_set_label_text (GTK_LABEL (priv->iso_label), + exif_data, + EXIF_TAG_ISO_SPEED_RATINGS); + eom_exif_util_set_label_text (GTK_LABEL (priv->metering_label), + exif_data, + EXIF_TAG_METERING_MODE); + eom_exif_util_set_label_text (GTK_LABEL (priv->model_label), + exif_data, EXIF_TAG_MODEL); + eom_exif_util_set_label_text (GTK_LABEL (priv->date_label), + exif_data, + EXIF_TAG_DATE_TIME_ORIGINAL); + + /* exif_data_unref can handle NULL-values */ + exif_data_unref(exif_data); + +#if HAVE_EXEMPI + eom_xmp_set_label (xmp_data, + NS_IPTC4XMP, + "Location", + priv->location_label); + + eom_xmp_set_label (xmp_data, + NS_DC, + "description", + priv->desc_label); + + eom_xmp_set_label (xmp_data, + NS_DC, + "subject", + priv->keyword_label); + + eom_xmp_set_label (xmp_data, + NS_DC, + "creator", + priv->creator_label); + + eom_xmp_set_label (xmp_data, + NS_DC, + "rights", + priv->rights_label); + + + if (xmp_data != NULL) + xmp_free (xmp_data); +#endif + +} + +static void +eom_metadata_sidebar_update (EomMetadataSidebar *sidebar) +{ + g_return_if_fail (EOM_IS_METADATA_SIDEBAR (sidebar)); + + eom_metadata_sidebar_update_general_section (sidebar); + eom_metadata_sidebar_update_metadata_section (sidebar); +} + +static void +_thumbnail_changed_cb (EomImage *image, gpointer user_data) +{ + eom_metadata_sidebar_update (EOM_METADATA_SIDEBAR (user_data)); +} + +static void +eom_metadata_sidebar_set_image (EomMetadataSidebar *sidebar, EomImage *image) +{ + EomMetadataSidebarPrivate *priv = sidebar->priv; + + if (image == priv->image) + return; + + + if (priv->thumb_changed_id != 0) { + g_signal_handler_disconnect (priv->image, + priv->thumb_changed_id); + priv->thumb_changed_id = 0; + } + + if (priv->image) + g_object_unref (priv->image); + + priv->image = image; + + if (priv->image) { + g_object_ref (priv->image); + priv->thumb_changed_id = + g_signal_connect (priv->image, "thumbnail-changed", + G_CALLBACK (_thumbnail_changed_cb), + sidebar); + eom_metadata_sidebar_update (sidebar); + } + + g_object_notify (G_OBJECT (sidebar), "image"); +} + +static void +_notify_image_cb (GObject *gobject, GParamSpec *pspec, gpointer user_data) +{ + EomImage *image; + + g_return_if_fail (EOM_IS_METADATA_SIDEBAR (user_data)); + g_return_if_fail (EOM_IS_SCROLL_VIEW (gobject)); + + image = eom_scroll_view_get_image (EOM_SCROLL_VIEW (gobject)); + + eom_metadata_sidebar_set_image (EOM_METADATA_SIDEBAR (user_data), + image); + + if (image) + g_object_unref (image); +} + +static void +_folder_button_clicked_cb (GtkButton *button, gpointer user_data) +{ + EomMetadataSidebarPrivate *priv = EOM_METADATA_SIDEBAR(user_data)->priv; + EomImage *img; + GdkScreen *screen; + GFile *file; + + g_return_if_fail (priv->parent_window != NULL); + + img = eom_window_get_image (priv->parent_window); + screen = gtk_widget_get_screen (GTK_WIDGET (priv->parent_window)); + file = eom_image_get_file (img); + + eom_util_show_file_in_filemanager (file, screen); + + g_object_unref (file); +} + +static void +_details_button_clicked_cb (GtkButton *button, gpointer user_data) +{ + EomMetadataSidebarPrivate *priv = EOM_METADATA_SIDEBAR(user_data)->priv; + EomDialog *dlg; + + g_return_if_fail (priv->parent_window != NULL); + + dlg = eom_window_get_properties_dialog ( + EOM_WINDOW (priv->parent_window)); + g_return_if_fail (dlg != NULL); + eom_properties_dialog_set_page (EOM_PROPERTIES_DIALOG (dlg), + EOM_PROPERTIES_DIALOG_PAGE_DETAILS); + eom_dialog_show (dlg); +} + + +static void +eom_metadata_sidebar_set_parent_window (EomMetadataSidebar *sidebar, + EomWindow *window) +{ + EomMetadataSidebarPrivate *priv; + GtkWidget *view; + + g_return_if_fail (EOM_IS_METADATA_SIDEBAR (sidebar)); + priv = sidebar->priv; + g_return_if_fail (priv->parent_window == NULL); + + priv->parent_window = g_object_ref (window); + eom_metadata_sidebar_update (sidebar); + view = eom_window_get_view (window); + priv->image_changed_id = g_signal_connect (view, "notify::image", + G_CALLBACK (_notify_image_cb), + sidebar); + + g_object_notify (G_OBJECT (sidebar), "parent-window"); + +} + +static void +eom_metadata_sidebar_init (EomMetadataSidebar *sidebar) +{ + EomMetadataSidebarPrivate *priv; + GtkWidget *label; + + priv = sidebar->priv = EOM_METADATA_SIDEBAR_GET_PRIVATE (sidebar); + priv->grid = gtk_grid_new (); + g_object_set (G_OBJECT (priv->grid), + "row-spacing", 6, + "column-spacing", 6, + NULL); + + label = _gtk_grid_append_title_line (GTK_GRID (priv->grid), + NULL, _("General")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->name_label, _("Name:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->width_label, _("Width:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->height_label, _("Height:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->type_label, _("Type:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->size_label, _("File size:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + NULL, _("Folder:")); + + priv->folder_button = gtk_button_new_with_label (""); + g_signal_connect (priv->folder_button, "clicked", + G_CALLBACK (_folder_button_clicked_cb), sidebar); + gtk_grid_attach_next_to (GTK_GRID (priv->grid), priv->folder_button, + label, GTK_POS_RIGHT, 1, 1); + + label = _gtk_grid_append_title_line (GTK_GRID (priv->grid), + label, _("Metadata")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->aperture_label, + _("Aperture Value:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->exposure_label, + _("Exposure Time:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->focallen_label, + _("Focal Length:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->flash_label, _("Flash:")); + gtk_label_set_line_wrap (GTK_LABEL (priv->flash_label), TRUE); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->iso_label, + _("ISO Speed Rating:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->metering_label, + _("Metering Mode:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->model_label, + _("Camera Model:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->date_label, _("Date/Time:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->desc_label, + _("Description:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->location_label, + _("Location:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->keyword_label, + _("Keywords:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->creator_label, _("Author:")); + label = _gtk_grid_append_prop_line (GTK_GRID (priv->grid), label, + &priv->rights_label, + _("Copyright:")); + + priv->details_button = gtk_button_new_with_label (_("Details")); + g_signal_connect (priv->details_button, "clicked", + G_CALLBACK (_details_button_clicked_cb), sidebar); + gtk_grid_attach_next_to (GTK_GRID (priv->grid), priv->details_button, + label, GTK_POS_BOTTOM, 1, 1); + + + gtk_widget_show_all (priv->grid); +} + +static void +eom_metadata_sidebar_constructed (GObject *object) +{ + EomMetadataSidebarPrivate *priv; + + priv = EOM_METADATA_SIDEBAR (object)->priv; + + /* This can only happen after all construct properties for + * GtkScrolledWindow are set/handled. */ + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (object), + priv->grid); + gtk_widget_show (GTK_WIDGET (object)); + + G_OBJECT_CLASS (eom_metadata_sidebar_parent_class)->constructed (object); +} + +static void +eom_metadata_sidebar_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + EomMetadataSidebar *sidebar; + + g_return_if_fail (EOM_IS_METADATA_SIDEBAR (object)); + + sidebar = EOM_METADATA_SIDEBAR (object); + + switch (property_id) { + case PROP_IMAGE: + { + g_value_set_object (value, sidebar->priv->image); + break; + } + case PROP_PARENT_WINDOW: + g_value_set_object (value, sidebar->priv->parent_window); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +eom_metadata_sidebar_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + EomMetadataSidebar *sidebar; + + g_return_if_fail (EOM_IS_METADATA_SIDEBAR (object)); + + sidebar = EOM_METADATA_SIDEBAR (object); + + switch (property_id) { + case PROP_IMAGE: + { + break; + } + case PROP_PARENT_WINDOW: + { + EomWindow *window; + + window = g_value_get_object (value); + eom_metadata_sidebar_set_parent_window (sidebar, window); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } + +} +static void +eom_metadata_sidebar_class_init (EomMetadataSidebarClass *klass) +{ + GObjectClass *g_obj_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof(EomMetadataSidebarPrivate)); + + g_obj_class->constructed = eom_metadata_sidebar_constructed; + g_obj_class->get_property = eom_metadata_sidebar_get_property; + g_obj_class->set_property = eom_metadata_sidebar_set_property; +/* g_obj_class->dispose = eom_metadata_sidebar_dispose;*/ + + g_object_class_install_property ( + g_obj_class, PROP_PARENT_WINDOW, + g_param_spec_object ("parent-window", NULL, NULL, + EOM_TYPE_WINDOW, G_PARAM_READWRITE + | G_PARAM_CONSTRUCT_ONLY + | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property ( + g_obj_class, PROP_IMAGE, + g_param_spec_object ("image", NULL, NULL, EOM_TYPE_IMAGE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) + ); +} + + +GtkWidget* +eom_metadata_sidebar_new (EomWindow *window) +{ + return gtk_widget_new (EOM_TYPE_METADATA_SIDEBAR, + "hadjustment", NULL, + "vadjustment", NULL, + "hscrollbar-policy", GTK_POLICY_NEVER, + "vscrollbar-policy", GTK_POLICY_AUTOMATIC, + "border-width", 6, + "parent-window", window, + NULL); +} diff --git a/src/eom-metadata-sidebar.h b/src/eom-metadata-sidebar.h new file mode 100644 index 0000000..1b3cd96 --- /dev/null +++ b/src/eom-metadata-sidebar.h @@ -0,0 +1,61 @@ +/* + * eom-metadata-sidebar.h + * This file is part of eom + * + * Author: Felix Riemann + * + * Copyright (C) 2011 GNOME Foundation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __EOM_METADATA_SIDEBAR_H__ +#define __EOM_METADATA_SIDEBAR_H_ + +#include +#include + +#include "eom-window.h" + +G_BEGIN_DECLS + +#define EOM_TYPE_METADATA_SIDEBAR (eom_metadata_sidebar_get_type ()) +#define EOM_METADATA_SIDEBAR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EOM_TYPE_METADATA_SIDEBAR, EomMetadataSidebar)) +#define EOM_METADATA_SIDEBAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EOM_TYPE_METADATA_SIDEBAR, EomMetadataSidebarClass)) +#define EOM_IS_METADATA_SIDEBAR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EOM_TYPE_METADATA_SIDEBAR)) +#define EOM_IS_METADATA_SIDEBAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EOM_TYPE_METADATA_SIDEBAR)) +#define EOM_METADATA_SIDEBAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EOM_TYPE_METADATA_SIDEBAR, EomMetadataSidebarClass)) + +typedef struct _EomMetadataSidebar EomMetadataSidebar; +typedef struct _EomMetadataSidebarClass EomMetadataSidebarClass; +typedef struct _EomMetadataSidebarPrivate EomMetadataSidebarPrivate; + +struct _EomMetadataSidebar { + GtkScrolledWindow parent; + + EomMetadataSidebarPrivate *priv; +}; + +struct _EomMetadataSidebarClass { + GtkScrolledWindowClass parent_klass; +}; + +GType eom_metadata_sidebar_get_type (void) G_GNUC_CONST; + +GtkWidget* eom_metadata_sidebar_new (EomWindow *window); + +G_END_DECLS + +#endif /* __EOM_METADATA_SIDEBAR_H__ */ diff --git a/src/eom-properties-dialog.c b/src/eom-properties-dialog.c index 6ef84f9..00bada5 100644 --- a/src/eom-properties-dialog.c +++ b/src/eom-properties-dialog.c @@ -176,94 +176,6 @@ pd_update_general_tab (EomPropertiesDialog *prop_dlg, g_free (uri_str); } -#if HAVE_EXIF -static void -eom_exif_set_label (GtkWidget *w, ExifData *exif_data, gint tag_id) -{ - gchar exif_buffer[512]; - const gchar *buf_ptr; - gchar *label_text = NULL; - - if (exif_data) { - buf_ptr = eom_exif_data_get_value (exif_data, tag_id, - exif_buffer, 512); - - if (tag_id == EXIF_TAG_DATE_TIME_ORIGINAL && buf_ptr) - label_text = eom_exif_util_format_date (buf_ptr); - else - label_text = eom_util_make_valid_utf8 (buf_ptr); - } - - gtk_label_set_text (GTK_LABEL (w), label_text); - g_free (label_text); -} - -static void -eom_exif_set_focal_length_label (GtkWidget *w, ExifData *exif_data) -{ - ExifEntry *entry = NULL, *entry35mm = NULL; - ExifByteOrder byte_order; - gfloat f_val = 0.0; - gchar *fl_text = NULL,*fl35_text = NULL; - - /* If no ExifData is supplied the label will be - * cleared later as fl35_text is NULL. */ - if (exif_data != NULL) { - entry = exif_data_get_entry (exif_data, EXIF_TAG_FOCAL_LENGTH); - entry35mm = exif_data_get_entry (exif_data, - EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM); - byte_order = exif_data_get_byte_order (exif_data); - } - - if (entry && G_LIKELY (entry->format == EXIF_FORMAT_RATIONAL)) { - ExifRational value; - - /* Decode value by hand as libexif is not necessarily returning - * it in the format we want it to be. - */ - value = exif_get_rational (entry->data, byte_order); - /* Guard against div by zero */ - if (G_LIKELY(value.denominator != 0)) - f_val = (gfloat)value.numerator/ - (gfloat)value.denominator; - - /* TRANSLATORS: This is the actual focal length used when - the image was taken.*/ - fl_text = g_strdup_printf (_("%.1f (lens)"), f_val); - - } - if (entry35mm && G_LIKELY (entry35mm->format == EXIF_FORMAT_SHORT)) { - ExifShort s_val; - - s_val = exif_get_short (entry35mm->data, byte_order); - - /* Print as float to get a similar look as above. */ - /* TRANSLATORS: This is the equivalent focal length assuming - a 35mm film camera. */ - fl35_text = g_strdup_printf(_("%.1f (35mm film)"),(float)s_val); - } - - if (fl_text) { - if (fl35_text) { - gchar *merged_txt; - - merged_txt = g_strconcat (fl35_text,", ", fl_text, NULL); - gtk_label_set_text (GTK_LABEL (w), merged_txt); - g_free (merged_txt); - } else { - gtk_label_set_text (GTK_LABEL (w), fl_text); - } - } else { - /* This will also clear the label if no ExifData was supplied */ - gtk_label_set_text (GTK_LABEL (w), fl35_text); - } - - g_free (fl35_text); - g_free (fl_text); - -} -#endif - #if HAVE_EXEMPI static void eom_xmp_set_label (XmpPtr xmp, @@ -374,29 +286,29 @@ pd_update_metadata_tab (EomPropertiesDialog *prop_dlg, #if HAVE_EXIF exif_data = (ExifData *) eom_image_get_exif_info (image); - eom_exif_set_label (priv->exif_aperture_label, - exif_data, EXIF_TAG_FNUMBER); + eom_exif_util_set_label_text (GTK_LABEL (priv->exif_aperture_label), + exif_data, EXIF_TAG_FNUMBER); - eom_exif_set_label (priv->exif_exposure_label, - exif_data, EXIF_TAG_EXPOSURE_TIME); + eom_exif_util_set_label_text (GTK_LABEL (priv->exif_exposure_label), + exif_data, EXIF_TAG_EXPOSURE_TIME); - eom_exif_set_focal_length_label (priv->exif_focal_label, exif_data); + eom_exif_util_set_focal_length_label_text (GTK_LABEL (priv->exif_focal_label), exif_data); - eom_exif_set_label (priv->exif_flash_label, - exif_data, EXIF_TAG_FLASH); + eom_exif_util_set_label_text (GTK_LABEL (priv->exif_flash_label), + exif_data, EXIF_TAG_FLASH); - eom_exif_set_label (priv->exif_iso_label, - exif_data, EXIF_TAG_ISO_SPEED_RATINGS); + eom_exif_util_set_label_text (GTK_LABEL (priv->exif_iso_label), + exif_data, EXIF_TAG_ISO_SPEED_RATINGS); - eom_exif_set_label (priv->exif_metering_label, - exif_data, EXIF_TAG_METERING_MODE); + eom_exif_util_set_label_text (GTK_LABEL (priv->exif_metering_label), + exif_data, EXIF_TAG_METERING_MODE); - eom_exif_set_label (priv->exif_model_label, - exif_data, EXIF_TAG_MODEL); + eom_exif_util_set_label_text (GTK_LABEL (priv->exif_model_label), + exif_data, EXIF_TAG_MODEL); - eom_exif_set_label (priv->exif_date_label, - exif_data, EXIF_TAG_DATE_TIME_ORIGINAL); + eom_exif_util_set_label_text (GTK_LABEL (priv->exif_date_label), + exif_data, EXIF_TAG_DATE_TIME_ORIGINAL); eom_exif_details_update (EOM_EXIF_DETAILS (priv->exif_details), exif_data); diff --git a/src/eom-window.c b/src/eom-window.c index a7c3575..a56dfbf 100644 --- a/src/eom-window.c +++ b/src/eom-window.c @@ -52,6 +52,7 @@ #include "eom-save-as-dialog-helper.h" #include "eom-close-confirmation-dialog.h" #include "eom-clipboard-handler.h" +#include "eom-metadata-sidebar.h" #include "eom-enum-types.h" @@ -3010,26 +3011,26 @@ eom_window_cmd_print (GtkAction *action, gpointer user_data) eom_window_print (window); } -static void -eom_window_cmd_properties (GtkAction *action, gpointer user_data) +EomDialog* +eom_window_get_properties_dialog (EomWindow *window) { - EomWindow *window = EOM_WINDOW (user_data); EomWindowPrivate *priv; - GtkAction *next_image_action, *previous_image_action; - priv = window->priv; + g_return_val_if_fail (EOM_IS_WINDOW (window), NULL); - next_image_action = - gtk_action_group_get_action (priv->actions_collection, - "GoNext"); + priv = window->priv; - previous_image_action = - gtk_action_group_get_action (priv->actions_collection, - "GoPrevious"); + if (priv->properties_dlg == NULL) { + GtkAction *next_image_action, *previous_image_action; - if (window->priv->properties_dlg == NULL) { + next_image_action = + gtk_action_group_get_action (priv->actions_collection, + "GoNext"); - window->priv->properties_dlg = + previous_image_action = + gtk_action_group_get_action (priv->actions_collection, + "GoPrevious"); + priv->properties_dlg = eom_properties_dialog_new (GTK_WINDOW (window), EOM_THUMB_VIEW (priv->thumbview), next_image_action, @@ -3043,7 +3044,20 @@ eom_window_cmd_properties (GtkAction *action, gpointer user_data) G_SETTINGS_BIND_GET); } - eom_dialog_show (EOM_DIALOG (window->priv->properties_dlg)); + return EOM_DIALOG (priv->properties_dlg); +} + +static void +eom_window_cmd_properties (GtkAction *action, gpointer user_data) +{ + EomWindow *window = EOM_WINDOW (user_data); + EomWindowPrivate *priv; + EomDialog *dialog; + + priv = window->priv; + + dialog = eom_window_get_properties_dialog (window); + eom_dialog_show (dialog); } static void @@ -4459,6 +4473,11 @@ eom_window_construct_ui (EomWindow *window) window); priv->view = eom_scroll_view_new (); + + eom_sidebar_add_page (EOM_SIDEBAR (priv->sidebar), + _("Image Properties"), + GTK_WIDGET (eom_metadata_sidebar_new (window))); + gtk_widget_set_size_request (GTK_WIDGET (priv->view), 100, 100); g_signal_connect (G_OBJECT (priv->view), "zoom_changed", diff --git a/src/eom-window.h b/src/eom-window.h index 8be1e67..630645e 100644 --- a/src/eom-window.h +++ b/src/eom-window.h @@ -30,6 +30,7 @@ #include "eom-list-store.h" #include "eom-image.h" +#include "eom-dialog.h" #include #include @@ -124,6 +125,7 @@ void eom_window_open_file_list (EomWindow *window, gboolean eom_window_is_empty (EomWindow *window); void eom_window_reload_image (EomWindow *window); +EomDialog *eom_window_get_properties_dialog (EomWindow *window); G_END_DECLS #endif -- cgit v1.2.1