1 /* Eye Of Gnome - Image Properties Dialog
2 *
3 * Copyright (C) 2006 The Free Software Foundation
4 *
5 * Author: Lucas Rocha <lucasr@gnome.org>
6 * Hubert Figuiere <hub@figuiere.net> (XMP support)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "eog-properties-dialog.h"
28 #include "eog-image.h"
29 #include "eog-util.h"
30 #include "eog-thumb-view.h"
31
32 #ifdef HAVE_EXIF
33 #include "eog-exif-util.h"
34 #endif
35
36 #include <glib.h>
37 #include <glib/gi18n.h>
38 #include <glib-object.h>
39 #include <gio/gio.h>
40 #include <gtk/gtk.h>
41
42 #ifdef HAVE_EXEMPI
43 #include <exempi/xmp.h>
44 #include <exempi/xmpconsts.h>
45 #endif
46 #if defined(HAVE_EXIF) || defined(HAVE_EXEMPI)
47 #define HAVE_METADATA
48 #endif
49
50 #ifdef HAVE_METADATA
51 #include "eog-metadata-details.h"
52 #endif
53
54 enum {
55 PROP_0,
56 PROP_THUMBVIEW,
57 PROP_NETBOOK_MODE,
58 PROP_NEXT_ACTION,
59 PROP_PREV_ACTION
60 };
61
62 struct _EogPropertiesDialogPrivate {
63 EogThumbView *thumbview;
64
65 gboolean update_page;
66 EogPropertiesDialogPage current_page;
67
68 GtkWidget *notebook;
69 GtkWidget *next_button;
70 GtkWidget *previous_button;
71
72 GtkWidget *general_box;
73 GtkWidget *thumbnail_image;
74 GtkWidget *name_label;
75 GtkWidget *width_label;
76 GtkWidget *height_label;
77 GtkWidget *type_label;
78 GtkWidget *bytes_label;
79 GtkWidget *folder_button;
80 gchar *folder_button_uri;
81
82 #ifdef HAVE_EXIF
83 GtkWidget *exif_aperture_label;
84 GtkWidget *exif_exposure_label;
85 GtkWidget *exif_focal_label;
86 GtkWidget *exif_flash_label;
87 GtkWidget *exif_iso_label;
88 GtkWidget *exif_metering_label;
89 GtkWidget *exif_model_label;
90 GtkWidget *exif_date_label;
91 #endif
92 #ifdef HAVE_EXEMPI
93 GtkWidget *xmp_location_label;
94 GtkWidget *xmp_description_label;
95 GtkWidget *xmp_keywords_label;
96 GtkWidget *xmp_creator_label;
97 GtkWidget *xmp_rights_label;
98 #else
99 GtkWidget *xmp_box;
100 GtkWidget *xmp_box_label;
101 #endif
102 #ifdef HAVE_METADATA
103 GtkWidget *metadata_box;
104 GtkWidget *metadata_details_expander;
105 GtkWidget *metadata_details;
106 GtkWidget *metadata_details_box;
107 GtkWidget *metadata_details_sw;
108 #endif
109
110 gboolean netbook_mode;
111 };
112
113 G_DEFINE_TYPE_WITH_PRIVATE (EogPropertiesDialog, eog_properties_dialog, GTK_TYPE_DIALOG);
114
115 static void
parent_file_display_name_query_info_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)116 parent_file_display_name_query_info_cb (GObject *source_object,
117 GAsyncResult *res,
118 gpointer user_data)
119 {
120 EogPropertiesDialog *prop_dlg = EOG_PROPERTIES_DIALOG (user_data);
121 GFile *parent_file = G_FILE (source_object);
122 GFileInfo *file_info;
123 gchar *display_name;
124
125
126 file_info = g_file_query_info_finish (parent_file, res, NULL);
127 if (file_info == NULL) {
128 display_name = g_file_get_basename (parent_file);
129 } else {
130 display_name = g_strdup (
131 g_file_info_get_display_name (file_info));
132 g_object_unref (file_info);
133 }
134 gtk_button_set_label (GTK_BUTTON (prop_dlg->priv->folder_button),
135 display_name);
136 gtk_widget_set_sensitive (prop_dlg->priv->folder_button, TRUE);
137
138 g_free (display_name);
139 g_object_unref (prop_dlg);
140 }
141
142 static void
pd_update_general_tab(EogPropertiesDialog * prop_dlg,EogImage * image)143 pd_update_general_tab (EogPropertiesDialog *prop_dlg,
144 EogImage *image)
145 {
146 gchar *bytes_str;
147 gchar *width_str, *height_str;
148 GFile *file, *parent_file;
149 GFileInfo *file_info;
150 const char *mime_str;
151 char *type_str;
152 gint width, height;
153 goffset bytes;
154
155 g_object_set (G_OBJECT (prop_dlg->priv->thumbnail_image),
156 "pixbuf", eog_image_get_thumbnail (image),
157 NULL);
158
159 gtk_label_set_text (GTK_LABEL (prop_dlg->priv->name_label),
160 eog_image_get_caption (image));
161
162 eog_image_get_size (image, &width, &height);
163
164 width_str = g_strdup_printf ("%d %s", width,
165 ngettext ("pixel", "pixels", width));
166 height_str = g_strdup_printf ("%d %s", height,
167 ngettext ("pixel", "pixels", height));
168
169 gtk_label_set_text (GTK_LABEL (prop_dlg->priv->width_label), width_str);
170
171 gtk_label_set_text (GTK_LABEL (prop_dlg->priv->height_label),
172 height_str);
173
174 g_free (height_str);
175 g_free (width_str);
176
177 file = eog_image_get_file (image);
178 file_info = g_file_query_info (file,
179 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
180 0, NULL, NULL);
181 if (file_info == NULL) {
182 type_str = g_strdup (_("Unknown"));
183 } else {
184 mime_str = g_file_info_get_content_type (file_info);
185 type_str = g_content_type_get_description (mime_str);
186 g_object_unref (file_info);
187 }
188
189 gtk_label_set_text (GTK_LABEL (prop_dlg->priv->type_label), type_str);
190
191 bytes = eog_image_get_bytes (image);
192 bytes_str = g_format_size (bytes);
193
194 gtk_label_set_text (GTK_LABEL (prop_dlg->priv->bytes_label), bytes_str);
195
196 parent_file = g_file_get_parent (file);
197 if (parent_file == NULL) {
198 /* file is root directory itself */
199 parent_file = g_object_ref (file);
200 }
201
202 gtk_widget_set_sensitive (prop_dlg->priv->folder_button, FALSE);
203 gtk_button_set_label (GTK_BUTTON (prop_dlg->priv->folder_button), NULL);
204 g_free (prop_dlg->priv->folder_button_uri);
205 prop_dlg->priv->folder_button_uri = g_file_get_uri (parent_file);
206
207 g_file_query_info_async (parent_file,
208 G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
209 G_FILE_QUERY_INFO_NONE,
210 G_PRIORITY_DEFAULT,
211 NULL,
212 parent_file_display_name_query_info_cb,
213 g_object_ref (prop_dlg));
214
215 g_object_unref (parent_file);
216 g_free (type_str);
217 g_free (bytes_str);
218 }
219
220 #ifdef HAVE_EXEMPI
221 static void
eog_xmp_set_label(XmpPtr xmp,const char * ns,const char * propname,GtkWidget * w)222 eog_xmp_set_label (XmpPtr xmp,
223 const char *ns,
224 const char *propname,
225 GtkWidget *w)
226 {
227 uint32_t options;
228
229 XmpStringPtr value = xmp_string_new ();
230
231 if (xmp_get_property (xmp, ns, propname, value, &options)) {
232 if (XMP_IS_PROP_SIMPLE (options)) {
233 gtk_label_set_text (GTK_LABEL (w), xmp_string_cstr (value));
234 } else if (XMP_IS_PROP_ARRAY (options)) {
235 XmpIteratorPtr iter = xmp_iterator_new (xmp,
236 ns,
237 propname,
238 XMP_ITER_JUSTLEAFNODES);
239
240 GString *string = g_string_new ("");
241
242 if (iter) {
243 gboolean first = TRUE;
244
245 while (xmp_iterator_next (iter, NULL, NULL, value, &options)
246 && !XMP_IS_PROP_QUALIFIER (options)) {
247
248 if (!first) {
249 g_string_append_printf(string, ", ");
250 } else {
251 first = FALSE;
252 }
253
254 g_string_append_printf (string,
255 "%s",
256 xmp_string_cstr (value));
257 }
258
259 xmp_iterator_free (iter);
260 }
261
262 gtk_label_set_text (GTK_LABEL (w), string->str);
263 g_string_free (string, TRUE);
264 }
265 } else {
266 /* Property was not found */
267 /* Clear label so it won't show bogus data */
268 gtk_label_set_text (GTK_LABEL (w), NULL);
269 }
270
271 xmp_string_free (value);
272 }
273 #endif
274
275 #ifdef HAVE_METADATA
276 static void
pd_update_metadata_tab(EogPropertiesDialog * prop_dlg,EogImage * image)277 pd_update_metadata_tab (EogPropertiesDialog *prop_dlg,
278 EogImage *image)
279 {
280 EogPropertiesDialogPrivate *priv;
281 GtkNotebook *notebook;
282 #ifdef HAVE_EXIF
283 ExifData *exif_data;
284 #endif
285 #ifdef HAVE_EXEMPI
286 XmpPtr xmp_data;
287 #endif
288
289 g_return_if_fail (EOG_IS_PROPERTIES_DIALOG (prop_dlg));
290
291 priv = prop_dlg->priv;
292
293 notebook = GTK_NOTEBOOK (priv->notebook);
294
295 if (TRUE
296 #ifdef HAVE_EXIF
297 && !eog_image_has_data (image, EOG_IMAGE_DATA_EXIF)
298 #endif
299 #ifdef HAVE_EXEMPI
300 && !eog_image_has_data (image, EOG_IMAGE_DATA_XMP)
301 #endif
302 ) {
303 if (gtk_notebook_get_current_page (notebook) == EOG_PROPERTIES_DIALOG_PAGE_EXIF) {
304 gtk_notebook_prev_page (notebook);
305 } else if (gtk_notebook_get_current_page (notebook) == EOG_PROPERTIES_DIALOG_PAGE_DETAILS) {
306 gtk_notebook_set_current_page (notebook, EOG_PROPERTIES_DIALOG_PAGE_GENERAL);
307 }
308
309 if (gtk_widget_get_visible (priv->metadata_box)) {
310 gtk_widget_hide (priv->metadata_box);
311 }
312 if (gtk_widget_get_visible (priv->metadata_details_box)) {
313 gtk_widget_hide (priv->metadata_details_box);
314 }
315
316 return;
317 } else {
318 if (!gtk_widget_get_visible (priv->metadata_box))
319 gtk_widget_show_all (priv->metadata_box);
320 if (priv->netbook_mode &&
321 !gtk_widget_get_visible (priv->metadata_details_box)) {
322 gtk_widget_show_all (priv->metadata_details_box);
323 gtk_widget_hide (priv->metadata_details_expander);
324 }
325 }
326
327 #ifdef HAVE_EXIF
328 exif_data = (ExifData *) eog_image_get_exif_info (image);
329
330 eog_exif_util_set_label_text (GTK_LABEL (priv->exif_aperture_label),
331 exif_data, EXIF_TAG_FNUMBER);
332
333 eog_exif_util_set_label_text (GTK_LABEL (priv->exif_exposure_label),
334 exif_data, EXIF_TAG_EXPOSURE_TIME);
335
336 eog_exif_util_set_focal_length_label_text (GTK_LABEL (priv->exif_focal_label), exif_data);
337
338 eog_exif_util_set_label_text (GTK_LABEL (priv->exif_flash_label),
339 exif_data, EXIF_TAG_FLASH);
340
341 eog_exif_util_set_label_text (GTK_LABEL (priv->exif_iso_label),
342 exif_data, EXIF_TAG_ISO_SPEED_RATINGS);
343
344
345 eog_exif_util_set_label_text (GTK_LABEL (priv->exif_metering_label),
346 exif_data, EXIF_TAG_METERING_MODE);
347
348 eog_exif_util_set_label_text (GTK_LABEL (priv->exif_model_label),
349 exif_data, EXIF_TAG_MODEL);
350
351 eog_exif_util_set_label_text (GTK_LABEL (priv->exif_date_label),
352 exif_data, EXIF_TAG_DATE_TIME_ORIGINAL);
353
354 eog_metadata_details_update (EOG_METADATA_DETAILS (priv->metadata_details),
355 exif_data);
356
357 /* exif_data_unref can handle NULL-values */
358 exif_data_unref(exif_data);
359 #endif
360
361 #ifdef HAVE_EXEMPI
362 xmp_data = (XmpPtr) eog_image_get_xmp_info (image);
363
364 if (xmp_data != NULL) {
365 eog_xmp_set_label (xmp_data,
366 NS_IPTC4XMP,
367 "Location",
368 priv->xmp_location_label);
369
370 eog_xmp_set_label (xmp_data,
371 NS_DC,
372 "description",
373 priv->xmp_description_label);
374
375 eog_xmp_set_label (xmp_data,
376 NS_DC,
377 "subject",
378 priv->xmp_keywords_label);
379
380 eog_xmp_set_label (xmp_data,
381 NS_DC,
382 "creator",
383 priv->xmp_creator_label);
384
385 eog_xmp_set_label (xmp_data,
386 NS_DC,
387 "rights",
388 priv->xmp_rights_label);
389
390 eog_metadata_details_xmp_update (EOG_METADATA_DETAILS (priv->metadata_details), xmp_data);
391
392 xmp_free (xmp_data);
393 } else {
394 /* Image has no XMP data */
395
396 /* Clear the labels so they won't display foreign data.*/
397
398 gtk_label_set_text (GTK_LABEL (priv->xmp_location_label), NULL);
399 gtk_label_set_text (GTK_LABEL (priv->xmp_description_label),
400 NULL);
401 gtk_label_set_text (GTK_LABEL (priv->xmp_keywords_label), NULL);
402 gtk_label_set_text (GTK_LABEL (priv->xmp_creator_label), NULL);
403 gtk_label_set_text (GTK_LABEL (priv->xmp_rights_label), NULL);
404 }
405 #endif
406 }
407
408 static gboolean
pd_resize_dialog(gpointer user_data)409 pd_resize_dialog (gpointer user_data)
410 {
411 gint width, height;
412
413 gtk_window_get_size (GTK_WINDOW (user_data),
414 &width,
415 &height);
416
417 gtk_window_resize (GTK_WINDOW (user_data), width, 1);
418
419 return FALSE;
420 }
421
422 static void
pd_exif_details_activated_cb(GtkExpander * expander,GParamSpec * param_spec,GtkWidget * dialog)423 pd_exif_details_activated_cb (GtkExpander *expander,
424 GParamSpec *param_spec,
425 GtkWidget *dialog)
426 {
427 gboolean expanded;
428
429 expanded = gtk_expander_get_expanded (expander);
430
431 /*FIXME: this is depending on the expander animation
432 * duration. Need to find a safer way for doing that. */
433 if (!expanded)
434 g_timeout_add (150, pd_resize_dialog, dialog);
435 }
436 #endif
437
438 static void
pd_folder_button_clicked_cb(GtkButton * button,gpointer data)439 pd_folder_button_clicked_cb (GtkButton *button, gpointer data)
440 {
441 EogPropertiesDialogPrivate *priv = EOG_PROPERTIES_DIALOG (data)->priv;
442 GtkWindow *window;
443 guint32 timestamp;
444
445 if (!priv->folder_button_uri)
446 return;
447
448 timestamp = gtk_get_current_event_time ();
449
450 window = GTK_WINDOW (data);
451 gtk_show_uri_on_window (window, priv->folder_button_uri, timestamp, NULL);
452 }
453
454 static gboolean
eog_properties_dialog_page_switch(GtkNotebook * notebook,GtkWidget * page,gint page_index,EogPropertiesDialog * prop_dlg)455 eog_properties_dialog_page_switch (GtkNotebook *notebook,
456 GtkWidget *page,
457 gint page_index,
458 EogPropertiesDialog *prop_dlg)
459 {
460 if (prop_dlg->priv->update_page)
461 prop_dlg->priv->current_page = page_index;
462
463 return TRUE;
464 }
465
466 void
eog_properties_dialog_set_netbook_mode(EogPropertiesDialog * dlg,gboolean enable)467 eog_properties_dialog_set_netbook_mode (EogPropertiesDialog *dlg,
468 gboolean enable)
469 {
470 EogPropertiesDialogPrivate *priv;
471
472 g_return_if_fail (EOG_IS_PROPERTIES_DIALOG (dlg));
473
474 priv = dlg->priv;
475
476 if (priv->netbook_mode == enable)
477 return;
478
479 priv->netbook_mode = enable;
480
481 #ifdef HAVE_METADATA
482 if (enable) {
483 g_object_ref (priv->metadata_details_sw);
484 gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (priv->metadata_details_sw)),
485 priv->metadata_details_sw);
486 gtk_container_add (GTK_CONTAINER (priv->metadata_details_box), priv->metadata_details_sw);
487 g_object_unref (priv->metadata_details_sw);
488 // Only show details box if metadata is being displayed
489 if (gtk_widget_get_visible (priv->metadata_box))
490 gtk_widget_show_all (priv->metadata_details_box);
491
492 gtk_widget_hide (priv->metadata_details_expander);
493 } else {
494 g_object_ref (priv->metadata_details_sw);
495 gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (priv->metadata_details_sw)),
496 priv->metadata_details_sw);
497 gtk_container_add (GTK_CONTAINER (priv->metadata_details_expander), priv->metadata_details_sw);
498 g_object_unref (priv->metadata_details_sw);
499 gtk_widget_show_all (priv->metadata_details_expander);
500
501 if (gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)) == EOG_PROPERTIES_DIALOG_PAGE_DETAILS)
502 gtk_notebook_prev_page (GTK_NOTEBOOK (priv->notebook));
503 gtk_widget_hide (priv->metadata_details_box);
504 }
505 #endif
506 }
507
508 static void
eog_properties_dialog_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)509 eog_properties_dialog_set_property (GObject *object,
510 guint prop_id,
511 const GValue *value,
512 GParamSpec *pspec)
513 {
514 EogPropertiesDialog *prop_dlg = EOG_PROPERTIES_DIALOG (object);
515
516 switch (prop_id) {
517 case PROP_THUMBVIEW:
518 prop_dlg->priv->thumbview = g_value_get_object (value);
519 break;
520 case PROP_NETBOOK_MODE:
521 eog_properties_dialog_set_netbook_mode (prop_dlg,
522 g_value_get_boolean (value));
523 break;
524 case PROP_NEXT_ACTION:
525 gtk_actionable_set_action_name (GTK_ACTIONABLE (prop_dlg->priv->next_button),
526 g_value_get_string (value));
527 gtk_button_set_always_show_image(GTK_BUTTON(prop_dlg->priv->next_button), TRUE);
528 break;
529 case PROP_PREV_ACTION:
530 gtk_actionable_set_action_name (GTK_ACTIONABLE (prop_dlg->priv->previous_button),
531 g_value_get_string (value));
532 gtk_button_set_always_show_image(GTK_BUTTON(prop_dlg->priv->previous_button), TRUE);
533 break;
534 default:
535 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id,
536 pspec);
537 break;
538 }
539 }
540
541 static void
eog_properties_dialog_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)542 eog_properties_dialog_get_property (GObject *object,
543 guint prop_id,
544 GValue *value,
545 GParamSpec *pspec)
546 {
547 EogPropertiesDialog *prop_dlg = EOG_PROPERTIES_DIALOG (object);
548
549 switch (prop_id) {
550 case PROP_THUMBVIEW:
551 g_value_set_object (value, prop_dlg->priv->thumbview);
552 break;
553 case PROP_NETBOOK_MODE:
554 g_value_set_boolean (value,
555 prop_dlg->priv->netbook_mode);
556 break;
557 case PROP_NEXT_ACTION:
558 {
559 const gchar* action = gtk_actionable_get_action_name (
560 GTK_ACTIONABLE (prop_dlg->priv->next_button));
561 g_value_set_string (value, action);
562 break;
563 }
564 case PROP_PREV_ACTION:
565 {
566 const gchar* action = gtk_actionable_get_action_name (
567 GTK_ACTIONABLE (prop_dlg->priv->previous_button));
568 g_value_set_string (value, action);
569 break;
570 }
571 default:
572 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id,
573 pspec);
574 break;
575 }
576 }
577
578 static void
eog_properties_dialog_dispose(GObject * object)579 eog_properties_dialog_dispose (GObject *object)
580 {
581 EogPropertiesDialog *prop_dlg;
582 EogPropertiesDialogPrivate *priv;
583
584 g_return_if_fail (object != NULL);
585 g_return_if_fail (EOG_IS_PROPERTIES_DIALOG (object));
586
587 prop_dlg = EOG_PROPERTIES_DIALOG (object);
588 priv = prop_dlg->priv;
589
590 if (priv->thumbview) {
591 g_object_unref (priv->thumbview);
592 priv->thumbview = NULL;
593 }
594
595 g_free (priv->folder_button_uri);
596 priv->folder_button_uri = NULL;
597
598 G_OBJECT_CLASS (eog_properties_dialog_parent_class)->dispose (object);
599 }
600
601 static void
eog_properties_dialog_class_init(EogPropertiesDialogClass * klass)602 eog_properties_dialog_class_init (EogPropertiesDialogClass *klass)
603 {
604 GObjectClass *g_object_class = (GObjectClass *) klass;
605
606 g_object_class->dispose = eog_properties_dialog_dispose;
607 g_object_class->set_property = eog_properties_dialog_set_property;
608 g_object_class->get_property = eog_properties_dialog_get_property;
609
610 g_object_class_install_property (g_object_class,
611 PROP_THUMBVIEW,
612 g_param_spec_object ("thumbview",
613 "Thumbview",
614 "Thumbview",
615 EOG_TYPE_THUMB_VIEW,
616 G_PARAM_READWRITE |
617 G_PARAM_CONSTRUCT_ONLY |
618 G_PARAM_STATIC_STRINGS));
619 g_object_class_install_property (g_object_class, PROP_NETBOOK_MODE,
620 g_param_spec_boolean ("netbook-mode",
621 "Netbook Mode",
622 "Netbook Mode",
623 FALSE,
624 G_PARAM_READWRITE |
625 G_PARAM_STATIC_STRINGS));
626 g_object_class_install_property (g_object_class,
627 PROP_NEXT_ACTION,
628 g_param_spec_string ("next-action",
629 "Next Action",
630 "Action for Next button",
631 NULL,
632 G_PARAM_READWRITE |
633 G_PARAM_CONSTRUCT_ONLY |
634 G_PARAM_STATIC_STRINGS));
635 g_object_class_install_property (g_object_class,
636 PROP_PREV_ACTION,
637 g_param_spec_string ("prev-action",
638 "Prev Action",
639 "Action for Prev button",
640 NULL,
641 G_PARAM_READWRITE |
642 G_PARAM_CONSTRUCT_ONLY |
643 G_PARAM_STATIC_STRINGS));
644
645 gtk_widget_class_set_template_from_resource ((GtkWidgetClass *) klass, "/org/gnome/eog/ui/eog-image-properties-dialog.ui");
646
647 GtkWidgetClass *wklass = (GtkWidgetClass*) klass;
648 gtk_widget_class_bind_template_child_private(wklass,
649 EogPropertiesDialog,
650 notebook);
651 gtk_widget_class_bind_template_child_private(wklass,
652 EogPropertiesDialog,
653 previous_button);
654 gtk_widget_class_bind_template_child_private(wklass,
655 EogPropertiesDialog,
656 next_button);
657 gtk_widget_class_bind_template_child_private(wklass,
658 EogPropertiesDialog,
659 thumbnail_image);
660 gtk_widget_class_bind_template_child_private(wklass,
661 EogPropertiesDialog,
662 general_box);
663 gtk_widget_class_bind_template_child_private(wklass,
664 EogPropertiesDialog,
665 name_label);
666 gtk_widget_class_bind_template_child_private(wklass,
667 EogPropertiesDialog,
668 width_label);
669 gtk_widget_class_bind_template_child_private(wklass,
670 EogPropertiesDialog,
671 height_label);
672 gtk_widget_class_bind_template_child_private(wklass,
673 EogPropertiesDialog,
674 type_label);
675 gtk_widget_class_bind_template_child_private(wklass,
676 EogPropertiesDialog,
677 bytes_label);
678 gtk_widget_class_bind_template_child_private(wklass,
679 EogPropertiesDialog,
680 folder_button);
681
682 #ifdef HAVE_EXIF
683 gtk_widget_class_bind_template_child_private(wklass,
684 EogPropertiesDialog,
685 exif_aperture_label);
686 gtk_widget_class_bind_template_child_private(wklass,
687 EogPropertiesDialog,
688 exif_exposure_label);
689 gtk_widget_class_bind_template_child_private(wklass,
690 EogPropertiesDialog,
691 exif_focal_label);
692 gtk_widget_class_bind_template_child_private(wklass,
693 EogPropertiesDialog,
694 exif_flash_label);
695 gtk_widget_class_bind_template_child_private(wklass,
696 EogPropertiesDialog,
697 exif_iso_label);
698 gtk_widget_class_bind_template_child_private(wklass,
699 EogPropertiesDialog,
700 exif_metering_label);
701 gtk_widget_class_bind_template_child_private(wklass,
702 EogPropertiesDialog,
703 exif_model_label);
704 gtk_widget_class_bind_template_child_private(wklass,
705 EogPropertiesDialog,
706 exif_date_label);
707 #endif
708 #ifdef HAVE_EXEMPI
709 gtk_widget_class_bind_template_child_private(wklass,
710 EogPropertiesDialog,
711 xmp_location_label);
712 gtk_widget_class_bind_template_child_private(wklass,
713 EogPropertiesDialog,
714 xmp_description_label);
715 gtk_widget_class_bind_template_child_private(wklass,
716 EogPropertiesDialog,
717 xmp_keywords_label);
718 gtk_widget_class_bind_template_child_private(wklass,
719 EogPropertiesDialog,
720 xmp_creator_label);
721 gtk_widget_class_bind_template_child_private(wklass,
722 EogPropertiesDialog,
723 xmp_rights_label);
724 #else
725 gtk_widget_class_bind_template_child_private(wklass,
726 EogPropertiesDialog,
727 xmp_box);
728 gtk_widget_class_bind_template_child_private(wklass,
729 EogPropertiesDialog,
730 xmp_box_label);
731 #endif
732 #ifdef HAVE_METADATA
733 gtk_widget_class_bind_template_child_private(wklass,
734 EogPropertiesDialog,
735 metadata_box);
736 gtk_widget_class_bind_template_child_private(wklass,
737 EogPropertiesDialog,
738 metadata_details_expander);
739 gtk_widget_class_bind_template_child_private(wklass,
740 EogPropertiesDialog,
741 metadata_details_box);
742
743 gtk_widget_class_bind_template_callback(wklass,
744 pd_exif_details_activated_cb);
745 #endif
746 gtk_widget_class_bind_template_callback(wklass,
747 eog_properties_dialog_page_switch);
748 gtk_widget_class_bind_template_callback(wklass,
749 pd_folder_button_clicked_cb);
750
751 }
752
753 static void
eog_properties_dialog_init(EogPropertiesDialog * prop_dlg)754 eog_properties_dialog_init (EogPropertiesDialog *prop_dlg)
755 {
756 EogPropertiesDialogPrivate *priv;
757 #ifdef HAVE_METADATA
758 GtkWidget *sw;
759 #endif
760
761 prop_dlg->priv = eog_properties_dialog_get_instance_private (prop_dlg);
762
763 priv = prop_dlg->priv;
764
765 priv->update_page = FALSE;
766
767 gtk_widget_init_template (GTK_WIDGET (prop_dlg));
768
769
770 g_signal_connect (prop_dlg,
771 "delete-event",
772 G_CALLBACK (gtk_widget_hide_on_delete),
773 prop_dlg);
774
775 gtk_widget_set_tooltip_text (GTK_WIDGET (priv->folder_button),
776 _("Show the folder which contains this "
777 "file in the file manager"));
778 priv->folder_button_uri = NULL;
779
780 gtk_widget_set_size_request (priv->thumbnail_image, 100, 100);
781
782 #ifdef HAVE_METADATA
783 sw = gtk_scrolled_window_new (NULL, NULL);
784
785 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
786 GTK_SHADOW_IN);
787
788 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
789 GTK_POLICY_AUTOMATIC,
790 GTK_POLICY_AUTOMATIC);
791
792 priv->metadata_details = eog_metadata_details_new ();
793 gtk_widget_set_size_request (priv->metadata_details, -1, 170);
794 gtk_widget_set_vexpand (priv->metadata_details, TRUE);
795 gtk_container_set_border_width (GTK_CONTAINER (sw), 6);
796
797 gtk_container_add (GTK_CONTAINER (sw), priv->metadata_details);
798 gtk_widget_show_all (sw);
799
800 priv->metadata_details_sw = sw;
801
802 if (priv->netbook_mode) {
803 gtk_widget_hide (priv->metadata_details_expander);
804 gtk_box_pack_start (GTK_BOX (priv->metadata_details_box),
805 sw, TRUE, TRUE, 6);
806 } else {
807 gtk_container_add (GTK_CONTAINER (priv->metadata_details_expander),
808 sw);
809 }
810
811 #ifndef HAVE_EXEMPI
812 gtk_widget_hide (priv->xmp_box);
813 gtk_widget_hide (priv->xmp_box_label);
814 #endif
815
816 #else
817 /* Remove pages from back to front. Otherwise the page index
818 * needs to be adjusted when deleting the next page. */
819 gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook),
820 EOG_PROPERTIES_DIALOG_PAGE_DETAILS);
821 gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook),
822 EOG_PROPERTIES_DIALOG_PAGE_EXIF);
823 #endif
824 }
825
826 /**
827 * eog_properties_dialog_new:
828 * @parent: the dialog's parent window
829 * @thumbview:
830 * @next_image_action:
831 * @previous_image_action:
832 *
833 * If %parent implements #GActionMap its actions will be automatically
834 * inserted in the "win" namespace.
835 *
836 * Returns: (transfer full) (type EogPropertiesDialog): a new #EogPropertiesDialog
837 **/
838 GtkWidget *
eog_properties_dialog_new(GtkWindow * parent,EogThumbView * thumbview,const gchar * next_image_action,const gchar * previous_image_action)839 eog_properties_dialog_new (GtkWindow *parent,
840 EogThumbView *thumbview,
841 const gchar *next_image_action,
842 const gchar *previous_image_action)
843 {
844 GObject *prop_dlg;
845
846 g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
847 g_return_val_if_fail (EOG_IS_THUMB_VIEW (thumbview), NULL);
848
849 prop_dlg = g_object_new (EOG_TYPE_PROPERTIES_DIALOG,
850 "thumbview", thumbview,
851 "next-action", next_image_action,
852 "prev-action", previous_image_action,
853 "use-header-bar", TRUE,
854 NULL);
855
856 gtk_window_set_transient_for (GTK_WINDOW (prop_dlg), parent);
857
858 if (G_LIKELY (G_IS_ACTION_GROUP (parent))) {
859 gtk_widget_insert_action_group (GTK_WIDGET (prop_dlg),
860 "win",
861 G_ACTION_GROUP (parent));
862 }
863
864 return GTK_WIDGET (prop_dlg);
865 }
866
867 void
eog_properties_dialog_update(EogPropertiesDialog * prop_dlg,EogImage * image)868 eog_properties_dialog_update (EogPropertiesDialog *prop_dlg,
869 EogImage *image)
870 {
871 g_return_if_fail (EOG_IS_PROPERTIES_DIALOG (prop_dlg));
872
873 prop_dlg->priv->update_page = FALSE;
874
875 pd_update_general_tab (prop_dlg, image);
876
877 #ifdef HAVE_METADATA
878 pd_update_metadata_tab (prop_dlg, image);
879 #endif
880 gtk_notebook_set_current_page (GTK_NOTEBOOK (prop_dlg->priv->notebook),
881 prop_dlg->priv->current_page);
882
883 prop_dlg->priv->update_page = TRUE;
884 }
885
886 void
eog_properties_dialog_set_page(EogPropertiesDialog * prop_dlg,EogPropertiesDialogPage page)887 eog_properties_dialog_set_page (EogPropertiesDialog *prop_dlg,
888 EogPropertiesDialogPage page)
889 {
890 g_return_if_fail (EOG_IS_PROPERTIES_DIALOG (prop_dlg));
891
892 prop_dlg->priv->current_page = page;
893
894 gtk_notebook_set_current_page (GTK_NOTEBOOK (prop_dlg->priv->notebook),
895 page);
896 }
897