comparison src/bar_exif.c @ 9:d907d608745f

Sync to GQview 1.5.9 release. ######## DO NOT BASE ENHANCEMENTS OR TRANSLATION UPDATES ON CODE IN THIS CVS! This CVS is never up to date with current development and is provided solely for reference purposes, please use the latest official release package when making any changes or translation updates. ########
author gqview
date Sat, 26 Feb 2005 00:13:35 +0000
parents
children 6948407f52a5
comparison
equal deleted inserted replaced
8:e0d0593d519e 9:d907d608745f
1 /*
2 * GQview
3 * (C) 2004 John Ellis
4 *
5 * Author: John Ellis
6 *
7 * This software is released under the GNU General Public License (GNU GPL).
8 * Please read the included file COPYING for more information.
9 * This software comes with no warranty of any kind, use at your own risk!
10 */
11
12
13 #include "gqview.h"
14 #include "bar_exif.h"
15
16 #include "exif.h"
17 #include "ui_bookmark.h"
18 #include "ui_misc.h"
19
20 #include <math.h>
21
22 #define EXIF_BAR_SIZE_INCREMENT 48
23 #define EXIF_BAR_ARROW_SIZE 7
24
25 #define EXIF_BAR_CUSTOM_COUNT 20
26
27 static const gchar *bar_exif_key_list[] = {
28 "fCamera",
29 "fDateTime",
30 "fShutterSpeed",
31 "fAperture",
32 "ExposureProgram",
33 "fExposureBias",
34 "fISOSpeedRating",
35 "fFocalLength",
36 "fSubjectDistance",
37 "MeteringMode",
38 "fFlash",
39 "LightSource",
40 "fResolution",
41 "Orientation",
42 "ImageDescription",
43 "Copyright"
44 };
45
46 #define bar_exif_key_count (sizeof(bar_exif_key_list) / sizeof(gchar *))
47
48
49 /*
50 *-------------------------------------------------------------------
51 * table util
52 *-------------------------------------------------------------------
53 */
54
55 static void table_add_line_custom(GtkWidget *table, gint x, gint y,
56 const gchar *text1, const gchar *text2,
57 GtkWidget **label1, GtkWidget **label2)
58 {
59 GtkWidget *label;
60 gchar *buf;
61
62 buf = g_strconcat((text1) ? text1 : "fixme", ":", NULL);
63 if (!text2) text2 = "";
64
65 label = gtk_label_new(buf);
66 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.0);
67 pref_label_bold(label, TRUE, FALSE);
68 gtk_table_attach(GTK_TABLE(table), label,
69 x, x + 1, y, y + 1,
70 GTK_FILL, GTK_FILL,
71 2, 2);
72 *label1 = label;
73
74 label = gtk_label_new(text2);
75 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
76 gtk_table_attach(GTK_TABLE(table), label,
77 x + 1, x + 2, y, y + 1,
78 GTK_FILL, GTK_FILL,
79 2, 2);
80 *label2 = label;
81
82 g_free(buf);
83 }
84
85 static GtkWidget *table_add_line(GtkWidget *table, gint x, gint y,
86 const gchar *description, const gchar *text)
87 {
88 GtkWidget *key;
89 GtkWidget *label;
90
91 table_add_line_custom(table, x, y, description, text, &key, &label);
92 gtk_widget_show(key);
93 gtk_widget_show(label);
94
95 return label;
96 }
97
98
99 /*
100 *-------------------------------------------------------------------
101 * EXIF bar
102 *-------------------------------------------------------------------
103 */
104
105 typedef struct _ExifBar ExifBar;
106 struct _ExifBar
107 {
108 GtkWidget *vbox;
109 GtkWidget *scrolled;
110 GtkWidget *table;
111 GtkWidget *advanced_scrolled;
112 GtkWidget *listview;
113 GtkWidget **labels;
114
115 GtkWidget *custom_sep;
116 GtkWidget *custom_name[EXIF_BAR_CUSTOM_COUNT];
117 GtkWidget *custom_value[EXIF_BAR_CUSTOM_COUNT];
118
119 gchar *path;
120
121 gint allow_search;
122 };
123
124 enum {
125 EXIF_ADVCOL_ENABLED = 0,
126 EXIF_ADVCOL_TAG,
127 EXIF_ADVCOL_NAME,
128 EXIF_ADVCOL_VALUE,
129 EXIF_ADVCOL_FORMAT,
130 EXIF_ADVCOL_ELEMENTS,
131 EXIF_ADVCOL_DESCRIPTION,
132 EXIF_ADVCOL_COUNT
133 };
134
135 static gchar *bar_exif_validate_text(gchar *text)
136 {
137 if (text && !g_utf8_validate(text, strlen(text), NULL))
138 {
139 gchar *tmp = text;
140 text = g_convert(tmp, strlen(tmp), "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
141 g_free(tmp);
142 }
143 return text;
144 }
145
146 static void bar_exif_sensitive(ExifBar *eb, gint enable)
147 {
148 gtk_widget_set_sensitive(eb->table, enable);
149 if (eb->advanced_scrolled) gtk_widget_set_sensitive(eb->advanced_scrolled, enable);
150 }
151
152 static gint bar_exif_row_enabled(const gchar *name)
153 {
154 GList *list;
155
156 list = history_list_get_by_key("exif_extras");
157 while (list)
158 {
159 if (name && strcmp(name, (gchar *)(list->data)) == 0) return TRUE;
160 list = list->next;
161 }
162
163 return FALSE;
164 }
165
166 static void bar_exif_update(ExifBar *eb)
167 {
168 ExifData *exif;
169 gint len, i;
170
171 exif = exif_read(eb->path);
172
173 if (!exif)
174 {
175 bar_exif_sensitive(eb, FALSE);
176 return;
177 }
178
179 bar_exif_sensitive(eb, TRUE);
180
181 if (GTK_WIDGET_VISIBLE(eb->scrolled))
182 {
183 GList *list;
184 len = bar_exif_key_count;
185 for (i = 0; i < len; i++)
186 {
187 gchar *text;
188 text = exif_get_data_as_text(exif, bar_exif_key_list[i]);
189 text = bar_exif_validate_text(text);
190 gtk_label_set_text(GTK_LABEL(eb->labels[i]), text);
191 g_free(text);
192 }
193
194 list = g_list_last(history_list_get_by_key("exif_extras"));
195 if (list)
196 {
197 gtk_widget_show(eb->custom_sep);
198 }
199 else
200 {
201 gtk_widget_hide(eb->custom_sep);
202 }
203 i = 0;
204 while (list && i < EXIF_BAR_CUSTOM_COUNT)
205 {
206 gchar *text;
207 gchar *name;
208 gchar *buf;
209
210 name = list->data;
211 list = list->prev;
212
213 text = exif_get_data_as_text(exif, name);
214 text = bar_exif_validate_text(text);
215
216 buf = g_strconcat(name, ":", NULL);
217 gtk_label_set_text(GTK_LABEL(eb->custom_name[i]), buf);
218 g_free(buf);
219 gtk_label_set_text(GTK_LABEL(eb->custom_value[i]), text);
220 g_free(text);
221
222 gtk_widget_show(eb->custom_name[i]);
223 gtk_widget_show(eb->custom_value[i]);
224
225 i++;
226 }
227 while (i < EXIF_BAR_CUSTOM_COUNT)
228 {
229 gtk_widget_hide(eb->custom_name[i]);
230 gtk_widget_hide(eb->custom_value[i]);
231 i++;
232 }
233 }
234
235 if (eb->advanced_scrolled && GTK_WIDGET_VISIBLE(eb->advanced_scrolled))
236 {
237 GtkListStore *store;
238 GtkTreeIter iter;
239 GList *work;
240
241 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(eb->listview)));
242 gtk_list_store_clear(store);
243
244 work = exif->items;
245 while (work)
246 {
247 ExifItem *item;
248 gchar *tag;
249 const gchar *tag_name;
250 gchar *text;
251 const gchar *format;
252 gchar *elements;
253 const gchar *description;
254
255 item = work->data;
256 work = work->next;
257
258 tag = g_strdup_printf("0x%04x", item->tag);
259 tag_name = exif_item_get_tag_name(item);
260 format = exif_item_get_format_name(item, TRUE);
261 text = exif_item_get_data_as_text(item);
262 text = bar_exif_validate_text(text);
263 elements = g_strdup_printf("%d", item->elements);
264 description = exif_item_get_description(item);
265 if (!description) description = "";
266 gtk_list_store_append(store, &iter);
267 gtk_list_store_set(store, &iter,
268 EXIF_ADVCOL_ENABLED, bar_exif_row_enabled(tag_name),
269 EXIF_ADVCOL_TAG, tag,
270 EXIF_ADVCOL_NAME, tag_name,
271 EXIF_ADVCOL_VALUE, text,
272 EXIF_ADVCOL_FORMAT, format,
273 EXIF_ADVCOL_ELEMENTS, elements,
274 EXIF_ADVCOL_DESCRIPTION, description, -1);
275 g_free(tag);
276 g_free(text);
277 g_free(elements);
278 }
279 }
280
281 exif_free(exif);
282 }
283
284 static void bar_exif_clear(ExifBar *eb)
285 {
286 gint len;
287 gint i;
288
289 if (!GTK_WIDGET_SENSITIVE(eb->labels[0])) return;
290
291 len = bar_exif_key_count;
292 for (i = 0; i < len; i++)
293 {
294 gtk_label_set_text(GTK_LABEL(eb->labels[i]), "");
295 }
296 for (i = 0; i < EXIF_BAR_CUSTOM_COUNT; i++)
297 {
298 gtk_label_set_text(GTK_LABEL(eb->custom_value[i]), "");
299 }
300
301 if (eb->listview)
302 {
303 GtkListStore *store;
304
305 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(eb->listview)));
306 gtk_list_store_clear(store);
307 }
308 }
309
310 void bar_exif_set(GtkWidget *bar, const gchar *path)
311 {
312 ExifBar *eb;
313
314 eb = g_object_get_data(G_OBJECT(bar), "bar_exif_data");
315 if (!eb) return;
316
317 /* store this, advanced view toggle needs to reload data */
318 g_free(eb->path);
319 eb->path = g_strdup(path);
320
321 bar_exif_clear(eb);
322 bar_exif_update(eb);
323 }
324
325 static void bar_exif_row_toggled_cb(GtkCellRendererToggle *toggle, const gchar *path, gpointer data)
326 {
327 GtkWidget *listview = data;
328 GtkTreeModel *store;
329 GtkTreeIter iter;
330 GtkTreePath *tpath;
331 gchar *name = NULL;
332 gboolean active;
333
334 store = gtk_tree_view_get_model(GTK_TREE_VIEW(listview));
335
336 tpath = gtk_tree_path_new_from_string(path);
337 gtk_tree_model_get_iter(store, &iter, tpath);
338 gtk_tree_path_free(tpath);
339
340 gtk_tree_model_get(store, &iter, EXIF_ADVCOL_ENABLED, &active,
341 EXIF_ADVCOL_NAME, &name, -1);
342 active = (!active);
343
344 if (active &&
345 g_list_length(history_list_get_by_key("exif_extras")) >= EXIF_BAR_CUSTOM_COUNT)
346 {
347 active = FALSE;
348 }
349
350 gtk_list_store_set(GTK_LIST_STORE(store), &iter, EXIF_ADVCOL_ENABLED, active, -1);
351
352 if (active)
353 {
354 history_list_add_to_key("exif_extras", name, EXIF_BAR_CUSTOM_COUNT);
355 }
356 else
357 {
358 history_list_item_change("exif_extras", name, NULL);
359 }
360
361 g_free(name);
362 }
363
364 static void bar_exif_add_column_check(GtkWidget *listview, const gchar *title, gint n)
365 {
366 GtkTreeViewColumn *column;
367 GtkCellRenderer *renderer;
368
369 column = gtk_tree_view_column_new();
370 gtk_tree_view_column_set_title(column, title);
371 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
372
373 renderer = gtk_cell_renderer_toggle_new();
374 gtk_tree_view_column_pack_start(column, renderer, TRUE);
375 gtk_tree_view_column_add_attribute(column, renderer, "active", n);
376 gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column);
377
378 g_signal_connect(G_OBJECT(renderer), "toggled",
379 G_CALLBACK(bar_exif_row_toggled_cb), listview);
380 }
381
382 static void bar_exif_add_column(GtkWidget *listview, const gchar *title, gint n)
383 {
384 GtkTreeViewColumn *column;
385 GtkCellRenderer *renderer;
386
387 column = gtk_tree_view_column_new();
388 gtk_tree_view_column_set_title(column, title);
389 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
390
391 renderer = gtk_cell_renderer_text_new();
392 gtk_tree_view_column_pack_start(column, renderer, TRUE);
393 gtk_tree_view_column_add_attribute(column, renderer, "text", n);
394 gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column);
395 }
396
397 static void bar_exif_advanced_build_view(ExifBar *eb)
398 {
399 GtkListStore *store;
400
401 if (eb->listview) return;
402
403 store = gtk_list_store_new(7, G_TYPE_BOOLEAN,
404 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
405 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
406 eb->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
407 g_object_unref(store);
408
409 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(eb->listview), TRUE);
410 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(eb->listview), TRUE);
411
412 if (eb->allow_search)
413 {
414 gtk_tree_view_set_search_column(GTK_TREE_VIEW(eb->listview), EXIF_ADVCOL_NAME);
415 }
416 else
417 {
418 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(eb->listview), FALSE);
419 }
420
421 bar_exif_add_column_check(eb->listview, "", EXIF_ADVCOL_ENABLED);
422
423 bar_exif_add_column(eb->listview, _("Tag"), EXIF_ADVCOL_TAG);
424 bar_exif_add_column(eb->listview, _("Name"), EXIF_ADVCOL_NAME);
425 bar_exif_add_column(eb->listview, _("Value"), EXIF_ADVCOL_VALUE);
426 bar_exif_add_column(eb->listview, _("Format"), EXIF_ADVCOL_FORMAT);
427 bar_exif_add_column(eb->listview, _("Elements"), EXIF_ADVCOL_ELEMENTS);
428 bar_exif_add_column(eb->listview, _("Description"), EXIF_ADVCOL_DESCRIPTION);
429
430 eb->advanced_scrolled = gtk_scrolled_window_new(NULL, NULL);
431 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(eb->advanced_scrolled), GTK_SHADOW_IN);
432 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(eb->advanced_scrolled),
433 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
434 gtk_box_pack_start(GTK_BOX(eb->vbox), eb->advanced_scrolled, TRUE, TRUE, 0);
435 gtk_container_add(GTK_CONTAINER(eb->advanced_scrolled), eb->listview);
436 gtk_widget_show(eb->listview);
437 }
438
439 static void bar_exif_advanced_cb(GtkWidget *widget, gpointer data)
440 {
441 ExifBar *eb = data;
442 gint advanced;
443
444 advanced = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
445
446 if (advanced)
447 {
448 gtk_widget_hide(eb->scrolled);
449 bar_exif_advanced_build_view(eb);
450 gtk_widget_show(eb->advanced_scrolled);
451 }
452 else
453 {
454 gtk_widget_hide(eb->advanced_scrolled);
455 gtk_widget_show(eb->scrolled);
456 }
457
458 bar_exif_update(eb);
459 }
460
461 gint bar_exif_is_advanced(GtkWidget *bar)
462 {
463 ExifBar *eb;
464
465 eb = g_object_get_data(G_OBJECT(bar), "bar_exif_data");
466 if (!eb) return FALSE;
467
468 return (eb->advanced_scrolled && GTK_WIDGET_VISIBLE(eb->advanced_scrolled));
469 }
470
471 void bar_exif_close(GtkWidget *bar)
472 {
473 ExifBar *eb;
474
475 eb = g_object_get_data(G_OBJECT(bar), "bar_exif_data");
476 if (!eb) return;
477
478 gtk_widget_destroy(eb->vbox);
479 }
480
481 static void bar_exif_size(ExifBar *eb, gint val)
482 {
483 gint size;
484
485 size = eb->vbox->allocation.width;
486 size = CLAMP(size + val, EXIF_BAR_SIZE_INCREMENT * 2, EXIF_BAR_SIZE_INCREMENT * 16);
487
488 gtk_widget_set_size_request(eb->vbox, size, -1);
489 }
490
491 static void bar_exif_larger(GtkWidget *widget, gpointer data)
492 {
493 ExifBar *eb = data;
494
495 bar_exif_size(eb, EXIF_BAR_SIZE_INCREMENT);
496 }
497
498 static void bar_exif_smaller(GtkWidget *widget, gpointer data)
499 {
500 ExifBar *eb = data;
501
502 bar_exif_size(eb, -EXIF_BAR_SIZE_INCREMENT);
503 }
504
505 static void bar_exif_destroy(GtkWidget *widget, gpointer data)
506 {
507 ExifBar *eb = data;
508
509 g_free(eb->labels);
510 g_free(eb->path);
511 g_free(eb);
512 }
513
514 GtkWidget *bar_exif_new(gint show_title, const gchar *path, gint advanced, GtkWidget *bounding_widget)
515 {
516 ExifBar *eb;
517 GtkWidget *table;
518 GtkWidget *viewport;
519 GtkWidget *hbox;
520 GtkWidget *button;
521 gint len;
522 gint i;
523
524 eb = g_new0(ExifBar, 1);
525
526 eb->labels = g_new0(GtkWidget *, bar_exif_key_count);
527
528 eb->vbox = gtk_vbox_new(FALSE, PREF_PAD_GAP);
529 g_object_set_data(G_OBJECT(eb->vbox), "bar_exif_data", eb);
530 g_signal_connect_after(G_OBJECT(eb->vbox), "destroy",
531 G_CALLBACK(bar_exif_destroy), eb);
532
533 eb->allow_search = !show_title;
534
535 if (show_title)
536 {
537 GtkWidget *box;
538 GtkWidget *label;
539 GtkWidget *button;
540 GtkWidget *arrow;
541
542 box = gtk_hbox_new(FALSE, 0);
543
544 label = sizer_new(eb->vbox, bounding_widget, SIZER_POS_LEFT);
545 sizer_set_limits(label, EXIF_BAR_SIZE_INCREMENT * 2, -1, -1 , -1);
546 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
547 gtk_widget_show(label);
548
549 label = gtk_label_new(_("Exif"));
550 pref_label_bold(label, TRUE, FALSE);
551 gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 0);
552 gtk_widget_show(label);
553
554 button = gtk_button_new();
555 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
556 g_signal_connect(G_OBJECT(button), "clicked",
557 G_CALLBACK(bar_exif_smaller), eb);
558 gtk_box_pack_end(GTK_BOX(box), button, FALSE, FALSE, 0);
559 arrow = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
560 gtk_widget_set_size_request(arrow, EXIF_BAR_ARROW_SIZE, EXIF_BAR_ARROW_SIZE);
561 gtk_container_add(GTK_CONTAINER(button), arrow);
562 gtk_widget_show(arrow);
563 gtk_widget_show(button);
564
565 button = gtk_button_new();
566 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
567 g_signal_connect(G_OBJECT(button), "clicked",
568 G_CALLBACK(bar_exif_larger), eb);
569 gtk_box_pack_end(GTK_BOX(box), button, FALSE, FALSE, 0);
570 arrow = gtk_arrow_new(GTK_ARROW_LEFT, GTK_SHADOW_NONE);
571 gtk_widget_set_size_request(arrow, EXIF_BAR_ARROW_SIZE, EXIF_BAR_ARROW_SIZE);
572 gtk_container_add(GTK_CONTAINER(button), arrow);
573 gtk_widget_show(arrow);
574 gtk_widget_show(button);
575
576 gtk_box_pack_start(GTK_BOX(eb->vbox), box, FALSE, FALSE, 0);
577 gtk_widget_show(box);
578 }
579
580 table = gtk_table_new(2, bar_exif_key_count + 1 + EXIF_BAR_CUSTOM_COUNT, FALSE);
581
582 eb->table = table;
583
584 len = bar_exif_key_count;
585 for (i = 0; i < len; i++)
586 {
587 const gchar *text;
588
589 text = exif_get_description_by_key(bar_exif_key_list[i]);
590 eb->labels[i] = table_add_line(table, 0, i, text, NULL);
591 }
592
593 eb->custom_sep = gtk_hseparator_new();
594 gtk_table_attach(GTK_TABLE(table), eb->custom_sep, 0, 1,
595 bar_exif_key_count, bar_exif_key_count + 1,
596 GTK_FILL, GTK_FILL, 2, 2);
597
598 for (i = 0; i < EXIF_BAR_CUSTOM_COUNT; i++)
599 {
600 table_add_line_custom(table, 0, bar_exif_key_count + 1 + i,
601 "", "", &eb->custom_name[i], &eb->custom_value[i]);
602 }
603
604 eb->scrolled = gtk_scrolled_window_new(NULL, NULL);
605 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(eb->scrolled),
606 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
607
608 viewport = gtk_viewport_new(NULL, NULL);
609 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
610 gtk_container_add(GTK_CONTAINER(eb->scrolled), viewport);
611 gtk_widget_show(viewport);
612
613 gtk_container_add(GTK_CONTAINER(viewport), table);
614 gtk_widget_show(table);
615
616 gtk_box_pack_start(GTK_BOX(eb->vbox), eb->scrolled, TRUE, TRUE, 0);
617
618 hbox = gtk_hbox_new(FALSE, PREF_PAD_SPACE);
619 gtk_box_pack_end(GTK_BOX(eb->vbox), hbox, FALSE, FALSE, 0);
620 gtk_widget_show(hbox);
621
622 button = gtk_check_button_new_with_label(_("Advanced view"));
623 if (advanced) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
624 g_signal_connect(G_OBJECT(button), "toggled",
625 G_CALLBACK(bar_exif_advanced_cb), eb);
626 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
627 gtk_widget_show(button);
628
629 eb->advanced_scrolled = NULL;
630 eb->listview = NULL;
631
632 if (advanced)
633 {
634 bar_exif_advanced_build_view(eb);
635 gtk_widget_show(eb->advanced_scrolled);
636 }
637 else
638 {
639 gtk_widget_show(eb->scrolled);
640 }
641
642 eb->path = g_strdup(path);
643 bar_exif_update(eb);
644
645 return eb->vbox;
646 }
647