1 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
2 
3 /*
4  * GImageView
5  * Copyright (C) 2001 Takuro Ashie
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  *
21  * $Id: exif_view.c,v 1.23 2004/09/22 15:37:11 makeinu Exp $
22  */
23 
24 #include "gimageview.h"
25 
26 #ifdef ENABLE_EXIF
27 
28 #include <libexif/jpeg-data.h>
29 #include <libexif/exif-data.h>
30 
31 #include "exif_view.h"
32 #include "gimv_image.h"
33 #include "gimv_io_mem.h"
34 #include "gtkutils.h"
35 #include "gimv_icon_stock.h"
36 #include "gimv_image_loader.h"
37 
38 
39 #ifdef ENABLE_TREEVIEW
40 typedef enum {
41    COLUMN_TERMINATOR = -1,
42    COLUMN_KEY,
43    COLUMN_VALUE,
44    N_COLUMN
45 } ListStoreColumn;
46 #endif /* ENABLE_TREEVIEW */
47 
48 
49 /******************************************************************************
50  *
51  *   Callback Functions.
52  *
53  ******************************************************************************/
54 static void
cb_exif_view_destroy(GtkWidget * widget,ExifView * ev)55 cb_exif_view_destroy (GtkWidget *widget, ExifView *ev)
56 {
57    g_return_if_fail (ev);
58 
59    if (ev->exif_data)
60       exif_data_unref (ev->exif_data);
61    ev->exif_data = NULL;
62 
63    if (ev->jpeg_data)
64       jpeg_data_unref (ev->jpeg_data);
65    ev->jpeg_data = NULL;
66 
67    g_free (ev);
68 }
69 
70 
71 static void
cb_exif_window_close(GtkWidget * button,ExifView * ev)72 cb_exif_window_close (GtkWidget *button, ExifView *ev)
73 {
74    g_return_if_fail (ev);
75 
76    gtk_widget_destroy (ev->window);
77 }
78 
79 
80 /******************************************************************************
81  *
82  *   Other Private Functions.
83  *
84  ******************************************************************************/
85 static void
exif_view_content_list_set_data(GtkWidget * clist,ExifContent * content)86 exif_view_content_list_set_data (GtkWidget *clist,
87                                  ExifContent *content)
88 {
89    const gchar *text[2];
90    guint i;
91 
92    g_return_if_fail (clist);
93    g_return_if_fail (content);
94 
95 #ifdef ENABLE_TREEVIEW
96    {
97       GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (clist));
98       gtk_list_store_clear (GTK_LIST_STORE (model));
99    }
100 #else /* ENABLE_TREEVIEW */
101    gtk_clist_clear (GTK_CLIST (clist));
102 #endif /* ENABLE_TREEVIEW */
103 
104    for (i = 0; i < content->count; i++) {
105       text[0] = exif_tag_get_name (content->entries[i]->tag);
106       if (text[0] && *text[0]) text[0] = _(text[0]);
107       text[1] = exif_entry_get_value (content->entries[i]);
108       if (text[1] && *text[1]) text[1] = _(text[1]);
109 #ifdef ENABLE_TREEVIEW
110       {
111          GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (clist));
112          GtkTreeIter iter;
113 
114          gtk_list_store_append (GTK_LIST_STORE (model), &iter);
115          gtk_list_store_set (GTK_LIST_STORE (model), &iter,
116                              COLUMN_KEY,       text[0],
117                              COLUMN_VALUE,     text[1],
118                              COLUMN_TERMINATOR);
119       }
120 #else /* ENABLE_TREEVIEW */
121       gtk_clist_append (GTK_CLIST (clist), (gchar **) text);
122 #endif /* ENABLE_TREEVIEW */
123    }
124 }
125 
126 
127 /******************************************************************************
128  *
129  *   Public Functions.
130  *
131  ******************************************************************************/
132 ExifView *
exif_view_create_window(const gchar * filename,GtkWindow * parent)133 exif_view_create_window (const gchar *filename, GtkWindow *parent)
134 {
135    ExifView *ev;
136    GtkWidget *button;
137    gchar buf[BUF_SIZE];
138 
139    g_return_val_if_fail (filename && *filename, NULL);
140 
141    ev = exif_view_create (filename, parent);
142    if (!ev) return NULL;
143 
144    ev->window = gtk_dialog_new ();
145    if (parent)
146       gtk_window_set_transient_for (GTK_WINDOW (ev->window), parent);
147    g_snprintf (buf, BUF_SIZE, _("%s EXIF data"), filename);
148    gtk_window_set_title (GTK_WINDOW (ev->window), buf);
149    gtk_window_set_default_size (GTK_WINDOW (ev->window), 500, 400);
150    gtk_window_set_position (GTK_WINDOW (ev->window), GTK_WIN_POS_CENTER);
151 
152    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (ev->window)->vbox),
153                        ev->container,
154                        TRUE, TRUE, 0);
155 
156    gtk_widget_show_all (ev->window);
157 
158    /* button */
159    button = gtk_button_new_with_label (_("Close"));
160    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (ev->window)->action_area),
161                        button, TRUE, TRUE, 0);
162    gtk_signal_connect (GTK_OBJECT (button), "clicked",
163                        GTK_SIGNAL_FUNC (cb_exif_window_close), ev);
164    GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT);
165    gtk_widget_show (button);
166 
167    gtk_widget_grab_focus (button);
168 
169    gimv_icon_stock_set_window_icon (ev->window->window, "gimv_icon");
170 
171    return ev;
172 }
173 
174 
175 static GtkWidget *
exif_view_get_thumbnail(ExifData * edata)176 exif_view_get_thumbnail (ExifData *edata)
177 {
178    GtkWidget *image;
179    GimvImageLoader *loader;
180    GimvIO *gio;
181    GimvImage *gimvimage;
182    GdkPixmap *pixmap = NULL;
183    GdkBitmap *bitmap = NULL;
184 
185 
186    g_return_val_if_fail (edata, NULL);
187 
188    if (!edata->data) return NULL;
189    if (edata->size <= 0) return NULL;
190 
191    loader = gimv_image_loader_new ();
192    if (!loader) return NULL;
193 
194    gio = gimv_io_mem_new (NULL, "rb", GimvIOMemModeWrap);
195    gimv_io_mem_wrap ((GimvIOMem *) gio, edata->data, edata->size, FALSE);
196    gimv_image_loader_set_gio (loader, gio);
197 
198    gimv_image_loader_load (loader);
199 
200    gimvimage = gimv_image_loader_get_image (loader);
201    if (!gimvimage) {
202       gimv_image_loader_unref (loader);
203       return NULL;
204    }
205 
206    gimv_image_scale_get_pixmap (gimvimage,
207                                 gimv_image_width (gimvimage),
208                                 gimv_image_height (gimvimage),
209                                 &pixmap, &bitmap);
210 
211    gimv_image_loader_unref (loader);
212    gimv_io_unref (gio);
213 
214 #ifdef USE_GTK2
215    image = gtk_image_new_from_pixmap (pixmap, bitmap);
216 #else
217    image = gtk_pixmap_new (pixmap, bitmap);
218 #endif
219 
220    if (pixmap)
221       gdk_pixmap_unref (pixmap);
222 
223    return image;
224 }
225 
226 
227 ExifView *
exif_view_create(const gchar * filename,GtkWindow * parent)228 exif_view_create (const gchar *filename, GtkWindow *parent)
229 {
230    JPEGData *jdata;
231    ExifData *edata;
232    ExifView *ev = NULL;
233    ExifContent *contents[EXIF_IFD_COUNT];
234    GtkWidget *notebook, *label;
235    GtkWidget *vbox, *pixmap;
236    gint i;
237 
238    gchar *titles[] = {
239       N_("Tag"), N_("Value"),
240    };
241 
242    g_return_val_if_fail (filename && *filename, NULL);
243 
244    jdata = jpeg_data_new_from_file (filename);
245    if (!jdata) {
246       gtkutil_message_dialog (_("Error!!"), _("EXIF data not found."),
247                               GTK_WINDOW (ev->window));
248       return NULL;
249    }
250 
251    edata = jpeg_data_get_exif_data (jdata);
252    if (!edata) {
253       gtkutil_message_dialog (_("Error!!"), _("EXIF data not found."),
254                               GTK_WINDOW (parent));
255       goto ERROR;
256    }
257 
258    ev = g_new0 (ExifView, 1);
259    ev->exif_data = edata;
260    ev->jpeg_data = jdata;
261 
262 #if 0
263    contents[0] = edata->ifd0;
264    contents[1] = edata->ifd1;
265    contents[2] = edata->ifd_exif;
266    contents[3] = edata->ifd_gps;
267    contents[4] = edata->ifd_interoperability;
268 #else
269    for (i = 0; i < EXIF_IFD_COUNT; i++)
270       contents[i] = edata->ifd[i];
271 #endif
272 
273    ev->container = gtk_vbox_new (FALSE, 0);
274    gtk_signal_connect (GTK_OBJECT (ev->container), "destroy",
275                        GTK_SIGNAL_FUNC (cb_exif_view_destroy), ev);
276    gtk_widget_show (ev->container);
277 
278    notebook = gtk_notebook_new ();
279    gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);
280    gtk_box_pack_start(GTK_BOX(ev->container), notebook, TRUE, TRUE, 0);
281    gtk_widget_show (notebook);
282 
283    /* Tag Tables */
284    for (i = 0; i < EXIF_IFD_COUNT; i++) {
285       GtkWidget *scrolledwin, *clist;
286 
287       /* scrolled window & clist */
288       label = gtk_label_new (_(exif_ifd_get_name(i)));
289       scrolledwin = gtk_scrolled_window_new (NULL, NULL);
290       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrolledwin),
291                                       GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
292 #ifdef USE_GTK2
293       gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwin),
294                                           GTK_SHADOW_IN);
295 #endif /* USE_GTK2 */
296       gtk_container_set_border_width (GTK_CONTAINER (scrolledwin), 5);
297       gtk_notebook_append_page (GTK_NOTEBOOK(notebook),
298                                 scrolledwin, label);
299       gtk_widget_show (scrolledwin);
300 
301 #ifdef ENABLE_TREEVIEW
302       {
303          GtkListStore *store;
304          GtkTreeViewColumn *col;
305          GtkCellRenderer *render;
306 
307          store = gtk_list_store_new (N_COLUMN, G_TYPE_STRING, G_TYPE_STRING);
308          clist = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
309 
310          gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (clist), TRUE);
311 
312          /* set column for key */
313          col = gtk_tree_view_column_new();
314          gtk_tree_view_column_set_resizable (col, TRUE);
315          gtk_tree_view_column_set_title (col, _(titles[0]));
316          render = gtk_cell_renderer_text_new ();
317          gtk_tree_view_column_pack_start (col, render, TRUE);
318          gtk_tree_view_column_add_attribute (col, render, "text", COLUMN_KEY);
319          gtk_tree_view_append_column (GTK_TREE_VIEW (clist), col);
320 
321          /* set column for value */
322          col = gtk_tree_view_column_new();
323          gtk_tree_view_column_set_resizable (col, TRUE);
324          gtk_tree_view_column_set_title (col, _(titles[1]));
325          render = gtk_cell_renderer_text_new ();
326          gtk_tree_view_column_pack_start (col, render, TRUE);
327          gtk_tree_view_column_add_attribute (col, render, "text", COLUMN_VALUE);
328          gtk_tree_view_append_column (GTK_TREE_VIEW (clist), col);
329       }
330 #else /* ENABLE_TREEVIEW */
331       clist =  gtk_clist_new_with_titles (2, titles);
332       gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_SINGLE);
333       gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, TRUE);
334       gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 1, TRUE);
335 #endif /* ENABLE_TREEVIEW */
336 
337       gtk_container_add (GTK_CONTAINER (scrolledwin), clist);
338       gtk_widget_show (clist);
339 
340       exif_view_content_list_set_data (clist, contents[i]);
341    }
342 
343    /* Thumbnail page */
344    label = gtk_label_new (_("Thumbnail"));
345    vbox = gtk_vbox_new (TRUE, 0);
346    gtk_notebook_append_page (GTK_NOTEBOOK(notebook),
347                              vbox, label);
348    gtk_widget_show (vbox);
349 
350    pixmap = exif_view_get_thumbnail (edata);
351 
352    if (pixmap)
353       gtk_box_pack_start (GTK_BOX (vbox), pixmap, TRUE, TRUE, 0);
354 
355    return ev;
356 
357 ERROR:
358    jpeg_data_unref (jdata);
359    return NULL;
360 }
361 
362 #endif /* ENABLE_EXIF */
363